Compare commits

...

7 Commits

Author SHA1 Message Date
29a217928e Things are in motion. 2025-06-30 01:22:39 -04:00
482f2b4877 Big refactor to unclutter ast.h.
Moves all print functions to own file for sanity.

Also, just hit 2,000 lines; nice.
2025-06-28 12:25:10 -04:00
36fd838a8f Done with some things, saving here. 2025-06-28 12:05:07 -04:00
289243de38 Added lambda parsing. 2025-06-28 11:15:21 -04:00
67aafb3ead Updated syntax to abbreviate functions defs. 2025-06-28 10:55:15 -04:00
3b5bee0695 Added trap for GDB &c. 2025-06-18 17:21:45 -04:00
970fc39198 Cleaned up types with anonymous structs. 2025-06-14 11:22:07 -04:00
13 changed files with 392 additions and 244 deletions

View File

@ -1,7 +1,7 @@
0. Create file to describe properties of terminology used; param, arg, var, &c.
1. Differenciate parameters and arguments -- params for function definitions,
1. Differentiate parameters and arguments -- params for function definitions,
arguments for function calls
2. Add scope field to all ASTs, and new scope layer for those that need it.
Change editor to GNU Readline.
Make variables persist through lines in the editor.
Return syntax errors as exceptions.

36
definitions.md Normal file
View File

@ -0,0 +1,36 @@
Lambda
size_t parmc
AST** parmv
AST* body
Call
Lambda to
size_t parmc
AST** parmv
size_t argc
AST** argv
VDef
char* name
AST* exp
(\(x) x * 2)(4)
Call
to:
Lambda
parc: 1
parv: [ x ]
body:
Call
to:
BIF(mul)
argc: 2
argv: [
VRef
name: x
2
]
argc: 1
argv: [ 4 ]

191
src/ast.c
View File

@ -2,24 +2,12 @@
#include <stdio.h>
#include "include/ast.h"
#include "include/dstr.h"
#include "include/gc.h"
#include "include/scope.h"
#include "include/util.h"
extern AST* root;
static char* asttype_names[] = {
[AST_TYPE_CALL] = "FUNC CALL",
[AST_TYPE_NUM] = "NUMBER",
[AST_TYPE_VREF] = "VAR REFERENCE",
[AST_TYPE_VDEF] = "VAR DEFINITION",
[AST_TYPE_BLOCK] = "BLOCK",
[AST_TYPE_EXC] = "EXCEPTION",
[AST_TYPE_FDEF] = "FUNCTION DEFINITION",
[AST_TYPE_ARG] = "DEFINITION ARGUMENT"
};
AST* ast_init(ASTType type, void* data) {
AST* ast = gc_alloc(sizeof(AST), GC_TYPE_AST);
@ -55,32 +43,12 @@ void ast_destroy(AST* ast) {
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_VDEF: ast_vdef_data_destroy(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_data_destroy(ast->data); break;
case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break;
default:
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
}
// If there're no more `AST`s linked to the scope, free.
if (ast->scope && !--ast->scope->uses) scope_destroy_psv(ast->scope);
free(ast);
}
void ast_destroy_psv(AST* ast) {
if (!ast) return;
switch (ast->type) {
case AST_TYPE_NUM: ast_num_data_destroy(ast->data); break;
case AST_TYPE_CALL: ast_call_data_destroy_psv(ast->data); break;
case AST_TYPE_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy_psv(ast->data); break;
case AST_TYPE_BLOCK: ast_block_data_destroy_psv(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_data_destroy_psv(ast->data); break;
case AST_TYPE_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_BIF: ast_bif_data_destroy(ast->data); break;
case AST_TYPE_EXC: ast_exc_data_destroy(ast->data); break;
case AST_TYPE_LAMBDA: ast_lambda_data_destroy(ast->data); break;
default:
log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX);
}
@ -88,35 +56,6 @@ void ast_destroy_psv(AST* ast) {
free(ast);
}
void ast_print(AST* ast) {
if (!ast) return;
ast_print_i(ast, 0);
}
void ast_print_i(AST* ast, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("AST", ast);
INDENT_FIELD("type", "%s", asttype_names[ast->type]);
INDENT_FIELD("scope", "%p", ast->scope);
INDENT_FIELD_EXT_NONL_START("data");
switch (ast->type) {
case AST_TYPE_NUM:
printf("%s %lf\n", INDENT_spacing->buf, *(ASTNumData*)ast->data);
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_VDEF: ast_vdef_print(ast->data, i + 2); break;
case AST_TYPE_BLOCK: ast_block_print(ast->data, i + 2); break;
case AST_TYPE_FDEF: ast_fdef_print(ast->data, i + 2); break;
case AST_TYPE_ARG: ast_arg_print(ast->data, i + 2); break;
default: exit(1);
}
INDENT_FIELD_NONL_END;
INDENT_END;
}
ASTNumData* ast_num_data_init(double val) {
talloc(ASTNumData, num);
@ -127,14 +66,6 @@ ASTNumData* ast_num_data_init(double val) {
void ast_num_data_destroy(ASTNumData* num) { free(num); }
void ast_num_print(ASTNumData* data, int i) {
INDENT_BEGIN(i);
INDENT_FIELD("data", "%lf", *data);
INDENT_END;
}
ASTExcData* ast_exc_data_init(const char* msg, AST* trace) {
ASTExcData* data = malloc(sizeof(ASTExcData));
data->msg = msg;
@ -147,31 +78,33 @@ void ast_exc_data_destroy(ASTExcData* exc) {
free(exc);
}
void ast_exc_print(ASTExcData* data, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTExcData", data);
INDENT_FIELD("msg", "\"%s\"", data->msg);
if (data->trace == NULL) {
INDENT_FIELD("trace", "%p", NULL)
} else {
INDENT_FIELD_EXT_NONL_START("trace");
ast_print_i(data->trace, i + 1);
INDENT_FIELD_NONL_END;
}
INDENT_END;
}
ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**, Scope*)) {
return (ASTBIFData*)fn;
}
void ast_bif_data_destroy(ASTBIFData* bif) { return; }
ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv) {
talloc(ASTCallData, call);
// Lambda.
log_dbgf("to: %s", to);
ASTLambdaData* ast_lambda_data_init(size_t parc, AST** parv, AST* body) {
talloc(ASTLambdaData, lambda);
lambda->parc = parc;
lambda->parv = parv;
lambda->body = body;
return lambda;
}
void ast_lambda_data_destroy(ASTLambdaData* lambda) {
free(lambda->parv);
free(lambda);
}
// Call.
ASTCallData* ast_call_data_init(size_t argc, AST** argv, AST* to) {
talloc(ASTCallData, call);
call->to = to;
call->argc = argc;
@ -182,63 +115,27 @@ ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv) {
void ast_call_data_destroy(ASTCallData* call) {
if (!call) return;
free(call->to);
for (size_t i = 0; i < call->argc; i++) ast_destroy(call->argv[i]);
free(call->argv);
free(call);
}
void ast_call_data_destroy_psv(ASTCallData* call) {
if (!call) return;
free(call->to);
call->to = NULL;
free(call->argv);
call->argv = NULL;
free(call);
}
// VDef.
void ast_call_print(ASTCallData* data, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTCallData", data);
INDENT_FIELD("to", "%s", data->to);
INDENT_FIELD("argc", "%ld", data->argc);
INDENT_FIELD_LIST("argv", data->argv, data->argc, ast_print_i);
INDENT_END;
}
ASTVDefData* ast_vdef_data_init(char* name, AST* val) {
ASTVDefData* ast_vdef_data_init(char* name, AST* exp) {
talloc(ASTVDefData, vdef);
vdef->name = name;
vdef->val = val;
vdef->exp = exp;
return vdef;
}
void ast_vdef_data_destroy(ASTVDefData* vdef) {
ast_destroy(vdef->val);
free(vdef->name);
free(vdef);
}
void ast_vdef_data_destroy_psv(ASTVDefData* vdef) {
free(vdef->name);
free(vdef);
}
void ast_vdef_print(ASTVDefData* vdef, int depth) {
INDENT_BEGIN(depth);
INDENT_TITLE("ASTVDefData", vdef);
INDENT_FIELD("name", "%s", vdef->name);
INDENT_FIELD_EXT_NONL_START("val");
ast_print_i(vdef->val, depth + 2); // 2 because already indented.
INDENT_FIELD_NONL_END;
INDENT_END;
}
// VRef.
ASTVrefData* ast_vref_data_init(char* to) {
talloc(ASTVrefData, vref);
@ -253,15 +150,6 @@ void ast_vref_data_destroy(ASTVrefData* vref) {
free(vref);
}
void ast_vref_print(ASTVrefData* data, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTVrefData", data);
INDENT_FIELD("to", "%s", data->to);
INDENT_END;
}
ASTBlockData* ast_block_data_init(AST** inside, size_t ln) {
ASTBlockData* block = malloc(sizeof(ASTBlockData));
@ -283,16 +171,6 @@ void ast_block_data_destroy_psv(ASTBlockData* block) {
free(block);
}
void ast_block_print(ASTBlockData* data, int depth) {
INDENT_BEGIN(depth);
INDENT_TITLE("ASTBlockData", data);
INDENT_FIELD("ln", "%ld", data->ln);
INDENT_FIELD_LIST("inside", data->inside, data->ln, ast_print_i);
INDENT_END;
}
ASTFDefData*
ast_fdef_data_init(char* name, size_t argc, AST** argv, AST* body) {
ASTFDefData* fdef = malloc(sizeof(ASTFDefData));
@ -317,18 +195,6 @@ void ast_fdef_data_destroy_psv(ASTFDefData* fdef) {
free(fdef);
}
void ast_fdef_print(ASTFDefData* fdef, int i) {
INDENT_BEGIN(i)
INDENT_TITLE("ASTFDefData", fdef);
INDENT_FIELD("name", "%s", fdef->name);
INDENT_FIELD("argc", "%ld", fdef->argc);
INDENT_FIELD_LIST("argv", fdef->argv, fdef->argc, ast_print_i);
INDENT_FIELD_EXT_NONL_START("body");
ast_print_i(fdef->body, i + 2);
INDENT_FIELD_NONL_END;
INDENT_END;
}
ASTArgData* ast_arg_data_init(char* name) {
ASTArgData* arg = malloc(sizeof(ASTArgData));
arg->name = name;
@ -337,13 +203,6 @@ ASTArgData* ast_arg_data_init(char* name) {
void ast_arg_data_destroy(ASTArgData* arg) { free(arg->name); }
void ast_arg_print(ASTArgData* arg, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTArgData", arg);
INDENT_FIELD("name", "%s", arg->name);
INDENT_END;
}
AST* ast_find(Scope* scope, char* name) {
while (scope) {
AST* gotten = htab_get(scope->here, name);

139
src/ast_print.c Normal file
View File

@ -0,0 +1,139 @@
#include "include/ast_print.h"
#include "include/dstr.h"
#include "include/util.h"
#include <stdio.h>
static char* asttype_names[] = {
[AST_TYPE_CALL] = "FUNC CALL",
[AST_TYPE_NUM] = "NUMBER",
[AST_TYPE_VREF] = "VAR REFERENCE",
[AST_TYPE_VDEF] = "VAR DEFINITION",
[AST_TYPE_BLOCK] = "BLOCK",
[AST_TYPE_EXC] = "EXCEPTION",
[AST_TYPE_FDEF] = "FUNCTION DEFINITION",
[AST_TYPE_ARG] = "DEFINITION ARGUMENT",
[AST_TYPE_LAMBDA] = "LAMBDA EXPRESSION"
};
void ast_print(AST* ast) {
if (!ast) return;
ast_print_i(ast, 0);
}
void ast_print_i(AST* ast, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("AST", ast);
INDENT_FIELD("type", "%s", asttype_names[ast->type]);
// INDENT_FIELD("scope", "%p", ast->scope);
INDENT_FIELD_EXT_NONL_START("data");
switch (ast->type) {
case AST_TYPE_NUM:
printf("%s %lf\n", INDENT_spacing->buf, *(ASTNumData*)ast->data);
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_VDEF: ast_vdef_print(ast->data, i + 2); break;
case AST_TYPE_BLOCK: ast_block_print(ast->data, i + 2); break;
case AST_TYPE_FDEF: ast_fdef_print(ast->data, i + 2); break;
case AST_TYPE_ARG: ast_arg_print(ast->data, i + 2); break;
case AST_TYPE_LAMBDA: ast_lambda_print(ast->data, i + 2); break;
default: exit(1);
}
INDENT_FIELD_NONL_END;
INDENT_END;
}
void ast_num_print(ASTNumData* data, int i) {
INDENT_BEGIN(i);
INDENT_FIELD("data", "%lf", *data);
INDENT_END;
}
void ast_exc_print(ASTExcData* data, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTExcData", data);
INDENT_FIELD("msg", "\"%s\"", data->msg);
if (data->trace == NULL) {
INDENT_FIELD("trace", "%p", NULL)
} else {
INDENT_FIELD_EXT_NONL_START("trace");
ast_print_i(data->trace, i + 1);
INDENT_FIELD_NONL_END;
}
INDENT_END;
}
void ast_call_print(ASTCallData* data, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTCallData", data);
INDENT_FIELD("to", "%s", data->to);
INDENT_FIELD("argc", "%ld", data->argc);
INDENT_FIELD_LIST("argv", data->argv, data->argc, ast_print_i);
INDENT_END;
}
void ast_vdef_print(ASTVDefData* vdef, int depth) {
INDENT_BEGIN(depth);
INDENT_TITLE("ASTVDefData", vdef);
INDENT_FIELD("name", "%s", vdef->name);
INDENT_FIELD_EXT_NONL_START("val");
ast_print_i(vdef->val, depth + 2); // 2 because already indented.
INDENT_FIELD_NONL_END;
INDENT_END;
}
void ast_vref_print(ASTVrefData* data, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTVrefData", data);
INDENT_FIELD("to", "%s", data->to);
INDENT_END;
}
void ast_block_print(ASTBlockData* data, int depth) {
INDENT_BEGIN(depth);
INDENT_TITLE("ASTBlockData", data);
INDENT_FIELD("ln", "%ld", data->ln);
INDENT_FIELD_LIST("inside", data->inside, data->ln, ast_print_i);
INDENT_END;
}
void ast_fdef_print(ASTFDefData* fdef, int i) {
INDENT_BEGIN(i)
INDENT_TITLE("ASTFDefData", fdef);
INDENT_FIELD("name", "%s", fdef->name);
INDENT_FIELD("argc", "%ld", fdef->argc);
INDENT_FIELD_LIST("argv", fdef->argv, fdef->argc, ast_print_i);
INDENT_FIELD_EXT_NONL_START("body");
ast_print_i(fdef->body, i + 2);
INDENT_FIELD_NONL_END;
INDENT_END;
}
void ast_arg_print(ASTArgData* arg, int i) {
INDENT_BEGIN(i);
INDENT_TITLE("ASTArgData", arg);
INDENT_FIELD("name", "%s", arg->name);
INDENT_END;
}
void ast_lambda_print(ASTLambdaData* lambda, int i) {
INDENT_BEGIN(i)
INDENT_TITLE("ASTLambdaData", lambda);
INDENT_FIELD("argc", "%ld", lambda->argc);
INDENT_FIELD_LIST("argv", lambda->argv, lambda->argc, ast_print_i);
INDENT_FIELD_EXT_NONL_START("body");
ast_print_i(lambda->body, i + 2);
INDENT_FIELD_NONL_END;
INDENT_END;
}

View File

@ -4,7 +4,6 @@
#include "include/ast.h"
#include "include/builtin.h"
#include "include/dlist.h"
#include "include/exec.h"
#include "include/htab.h"
#include "include/scope.h"
@ -42,6 +41,7 @@ AST* exec_exp(AST* ast, Scope* parent) {
case AST_TYPE_VREF: return exec_vref(ast, parent);
case AST_TYPE_VDEF: return exec_vdef(ast, parent);
case AST_TYPE_FDEF: return exec_fdef(ast, parent);
case AST_TYPE_LAMBDA: return exec_lambda(ast, parent);
default: printf("what\n"); exit(1);
}
}
@ -64,7 +64,8 @@ AST* exec_call(AST* ast, Scope* parent) {
ASTCallData* data = (ASTCallData*)ast->data;
size_t argc = data->argc;
AST** argv = data->argv;
char* fname = data->to;
// char* fname = data->to;
AST* exp = data->to;
ast->scope = parent;
@ -80,6 +81,7 @@ AST* exec_call(AST* ast, Scope* parent) {
ASTBIFData bifdata = fdef->data;
return bifdata(argc, argv, parent);
case AST_TYPE_FDEF: return exec_cf(fdef, argc, argv);
case AST_TYPE_LAMBDA: return exec_lambda_call(fdef, argc, argv);
default:
return ast_init(AST_TYPE_EXC, ast_exc_data_init("Good job!", NULL));
}
@ -132,14 +134,29 @@ AST* exec_vref(AST* ast, Scope* parent) {
AST* exec_fdef(AST* ast, Scope* parent) {
ast->scope = scope_init(parent);
ASTFDefData* fdef = (ASTFDefData*)ast->data;
log_dbgf("IS THIS SUSPICIOUS??? %i", fdef->body->type);
AST* val = ast;
char* key = fdef->name;
scope_add(parent, key, val);
// TODO: Create lambda functions.
return fdef->body; // Function definitions return function body.
}
AST* exec_lambda(AST* ast, Scope* parent) {
// Executing a lambda on its own with no arguments returns itself.
return ast;
}
AST* exec_lambda_call(AST* ast, size_t argc, AST** argv) {
Scope* callscope = scope_init(ast->scope);
ASTFDefData* lambda = (ASTFDefData*)ast->data;
for (int i = 0; i < argc; i++) {
char* key = ((ASTArgData*)lambda->argv[i]->data)->name;
AST* val = argv[i];
scope_add(callscope, key, val);
}
return exec_exp(lambda->body, callscope);
}
void exec_print(double n) { printf("= %lf\n", n); }
inline void exec_new_scope(AST* ast, Scope* inherit) {

View File

@ -47,6 +47,8 @@
%token NL // Newline.
%token BACKSLASH
%left ADD SUB
%left MUL DIV
%precedence NEG
@ -124,12 +126,25 @@ block:
exp:
NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); }
// Function definitions.
| WORD GROUPS arg GROUPE EQ exp {
size_t argc = $3->ln;
AST** argv = $3->buf;
// Function definitions. Convert to VDef of Lambda.
| WORD GROUPS arg GROUPE exp {
size_t parc = $3->ln;
AST** parv = $3->buf;
argarr_destroypsv($3);
$$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $6));
$$ = ast_init(AST_TYPE_VDEF, ast_vdef_data_init(
$1,
ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init(
parc, parv, $5
)
));
}
// Lambda definitions.
| BACKSLASH GROUPS arg GROUPE exp {
size_t parc = $3->ln;
AST** parv = $3->buf;
argarr_destroypsv($3);
$$ = ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init(parc, parv, $5));
}
| BLOCKS block BLOCKE {

View File

@ -24,6 +24,7 @@ typedef enum {
AST_TYPE_VREF, // A variable reference.
AST_TYPE_BLOCK, // A block of code (scope).
AST_TYPE_FDEF, // A function definition.
AST_TYPE_LAMBDA, // An anonymous function definition.
AST_TYPE_ARG, // A definition argument.
AST_TYPE_MAX = AST_TYPE_ARG,
} ASTType;
@ -39,14 +40,8 @@ typedef struct {
AST* ast_init(ASTType type, void* data);
// Create a new `AST` with a specified scope.
AST* ast_init_scope(ASTType type, void* data, Scope* scope);
// Destroy an `AST`, recursively.
void ast_destroy(AST* ast);
// Destroy an `AST`.
void ast_destroy_psv(AST* ast);
// Print an `AST`, recursively.
void ast_print(AST* ast);
// Helper function to `ast_print()`, where `i` is indentation level.
void ast_print_i(AST* ast, int i);
void ast_destroy(AST* ast);
// A number.
typedef double ASTNumData;
@ -55,8 +50,6 @@ typedef double ASTNumData;
ASTNumData* ast_num_data_init(double val);
// Destroy an `ASTNumData`.
void ast_num_data_destroy(ASTNumData* num);
// Print an `ASTNumData`.
void ast_num_print(ASTNumData*, int i);
// An exception.
typedef struct ASTEXCDATA {
@ -67,8 +60,20 @@ typedef struct ASTEXCDATA {
ASTExcData* ast_exc_data_init(const char* msg, AST* trace);
// Destroy an `ASTExecData`.
void ast_exc_data_destroy(ASTExcData* exc);
// Print an `ASTExecData`.
void ast_exc_print(ASTExcData*, int i);
// Argument list as anonymous struct.
#define ARGS \
struct { \
size_t argc; \
AST** argv; \
}
// Parameter list as anonymous struct.
#define PARS \
struct { \
size_t parc; \
AST** parv; \
}
// A built-in function.
typedef AST* (*ASTBIFData)(size_t argc, AST** argv, Scope* scope);
@ -78,38 +83,41 @@ ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**, Scope*));
// Destroy an `ASTBIFData`.
void ast_bif_data_destroy(ASTBIFData* bif);
// A call (to a function).
// A lambda.
typedef struct {
char* to; // What the call's to.
size_t argc; // Argument count.
AST** argv; // Argument vector.
PARS; // The parameters the lambda can accept.
AST* body; // The body expression to be executed.
} ASTLambdaData;
// Creates a new `ASTLambdaData`.
ASTLambdaData* ast_lambda_data_init(size_t parc, AST** parv, AST* body);
// Destroy an `ASTLambdaData`.
void ast_lambda_data_destroy(ASTLambdaData*);
// A call.
typedef struct {
ARGS; // The arguments the call is made with.
AST* to; // The expression the call is to (probably either lambda or
// builtin).
} ASTCallData;
// Create a new `ASTCallData`.
ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv);
// Destroy an `ASTCallData` recursively.
void ast_call_data_destroy(ASTCallData* call);
ASTCallData* ast_call_data_init(size_t argc, AST** argv, AST* to);
// Destroy an `ASTCallData`.
void ast_call_data_destroy_psv(ASTCallData *call);
// Print an `ASTCallData`.
void ast_call_print(ASTCallData*, int i);
void ast_call_data_destroy(ASTCallData* call);
// A variable definition's data.
// A variable definition. Associates a name with an expression.
typedef struct {
char* name;
AST* val;
AST* exp;
} ASTVDefData;
// Create a new `ASTVDefData`.
ASTVDefData* ast_vdef_data_init(char* name, AST* val);
// Destroys the `ASTVDefData`, `ASTVDefData->name`, and `ASTVDefData->val`.
void ast_vdef_data_destroy(ASTVDefData* vdef);
ASTVDefData* ast_vdef_data_init(char* name, AST* exp);
// Destroy an `ASTVDefData`.
void ast_vdef_data_destroy_psv(ASTVDefData* vdef);
// Print an `ASTVDefData`.
void ast_vdef_print(ASTVDefData*, int depth);
void ast_vdef_data_destroy(ASTVDefData* vdef);
// A variable reference's data.
// A variable reference.
typedef struct {
char* to; // What the reference's to.
} ASTVrefData;
@ -118,8 +126,6 @@ typedef struct {
ASTVrefData* ast_vref_data_init(char* to);
// Destroy an `ASTVRefData`.
void ast_vref_data_destroy(ASTVrefData* call);
// Print an `ASTVRefData`.
void ast_vref_print(ASTVrefData*, int i);
// A code block.
typedef struct {
@ -132,14 +138,11 @@ ASTBlockData* ast_block_data_init(AST** inside, size_t ln);
// Destroy an `ASTBlockData`, recursively.
void ast_block_data_destroy(ASTBlockData* block);
// Destroy an `ASTBlockData`.
void ast_block_data_destroy_psv(ASTBlockData *block);
// Print an `ASTBlockData`.
void ast_block_print(ASTBlockData*, int i);
void ast_block_data_destroy_psv(ASTBlockData* block);
typedef struct {
char* name; // Function name.
size_t argc; // Argument count.
AST** argv; // Argument vector.
ARGS; // Function args.
AST* body; // Function body.
} ASTFDefData;
@ -149,8 +152,6 @@ ASTFDefData* ast_fdef_data_init(char* name, size_t argc, AST** argv, AST* body);
void ast_fdef_data_destroy(ASTFDefData* fdef);
// Destroy an `ASTFDefData`.
void ast_fdef_data_destroy_psv(ASTFDefData* fdef);
// Print an `ASTFDefData`.
void ast_fdef_print(ASTFDefData* fdef, int i);
typedef struct {
char* name; // Argument name.
@ -160,9 +161,20 @@ typedef struct {
ASTArgData* ast_arg_data_init(char* name);
// Destroy an `ASTArgData`.
void ast_arg_data_destroy(ASTArgData* arg);
// Print an `ASTArgData`.
void ast_arg_print(ASTArgData* arg, int i);
/*
// Represents a function as data.
typedef struct {
ARGS;
AST* body;
} ASTLambdaData;
// Creates a new `ASTLambdaData`.
ASTLambdaData* ast_lambda_data_init(size_t argc, AST** argv, AST* body);
// Destroy an `ASTLambdaData`.
void ast_lambda_data_destroy(ASTLambdaData*);
*/
// Find a name in the scope.
AST* ast_find(Scope* scope, char* name);

38
src/include/ast_print.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef AST_PRINT_H
#define AST_PRINT_H
#include "ast.h"
// Print an `AST`, recursively.
void ast_print(AST* ast);
// Helper function to `ast_print()`, where `i` is indentation level.
void ast_print_i(AST* ast, int i);
// Print an `ASTNumData`.
void ast_num_print(ASTNumData*, int i);
// Print an `ASTExecData`.
void ast_exc_print(ASTExcData*, int i);
// Print an `ASTCallData`.
void ast_call_print(ASTCallData*, int i);
// Print an `ASTVDefData`.
void ast_vdef_print(ASTVDefData*, int depth);
// Print an `ASTVRefData`.
void ast_vref_print(ASTVrefData*, int i);
// Print an `ASTBlockData`.
void ast_block_print(ASTBlockData*, int i);
// Print an `ASTFDefData`.
void ast_fdef_print(ASTFDefData* fdef, int i);
// Print an `ASTArgData`.
void ast_arg_print(ASTArgData* arg, int i);
// Print an `ASTLambdaData`.
void ast_lambda_print(ASTLambdaData* arg, int i);
#endif

View File

@ -20,6 +20,10 @@ AST* exec_vdef(AST* ast, Scope* parent);
AST* exec_vref(AST* ast, Scope* parent);
// Execute a function definition.
AST* exec_fdef(AST* ast, Scope* parent);
// Execute a lambda expression.
AST* exec_lambda(AST* ast, Scope* parent);
// Execute a lambda call.
AST* exec_lambda_call(AST* ast, size_t argc, AST** argv);
// Print the result of an execution.
void exec_print(double n);

View File

@ -1,6 +1,8 @@
#ifndef UTIL_H
#define UTIL_H
#include <signal.h>
// Most of this file is cursed printing macros for `ast_print()`. Do not attempt
// to comprehend.
@ -10,6 +12,9 @@
// Get the length of an array.
#define arrln(A) (sizeof(A)/sizeof(*A))
// Trap GDB &c.
#define TRAP() RAISE(SIGTRAP)
#ifdef DBG // Debug macros
// Log a message.

View File

@ -116,6 +116,7 @@ int yylex() {
case '{': return BLOCKS;
case '}': return BLOCKE;
case '=': return EQ;
case '\\': return BACKSLASH;
default: fprintf(stderr, "Unexpected character: %c\n", c);
}

View File

@ -2,6 +2,7 @@
#include <string.h>
#include "include/ast.h"
#include "include/ast_print.h"
#include "include/dstr.h"
#include "include/exec.h"
#include "include/gc.h"

21
type-notes.md Normal file
View File

@ -0,0 +1,21 @@
Primitive Types
- num
- bool
- str
```
fact(x) = ? (x <= 1) 1 : f(x-1) * x
> lambda
fact(5) == 120
> True
```
Ordered collections.
| Name | Homogeneous | Fixed Size | Unique |
|---|---|---|---|
| Collection | No | No | No |
| List | Yes | No | No |
| Array | Yes | Yes | No |
| Group | No | Yes | No |
| Set | Yes | No | Yes |
| Perm | Yes | Yes | Yes |