diff --git a/definitions.md b/definitions.md new file mode 100644 index 0000000..9cff019 --- /dev/null +++ b/definitions.md @@ -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 ] diff --git a/src/ast.c b/src/ast.c index 019417d..d7408b1 100644 --- a/src/ast.c +++ b/src/ast.c @@ -43,28 +43,6 @@ 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; - 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); - } - - // 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; @@ -106,10 +84,27 @@ ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**, Scope*)) { 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; @@ -120,40 +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. -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); -} +// VRef. ASTVrefData* ast_vref_data_init(char* to) { talloc(ASTVrefData, vref); @@ -221,21 +203,6 @@ ASTArgData* ast_arg_data_init(char* name) { void ast_arg_data_destroy(ASTArgData* arg) { free(arg->name); } -ASTLambdaData* ast_lambda_data_init(size_t argc, AST** argv, AST* body) { - talloc(ASTLambdaData, lambda); - - lambda->argc = argc; - lambda->argv = argv; - lambda->body = body; - - return lambda; -} - -void ast_lambda_data_destroy(ASTLambdaData* lambda) { - free(lambda->argv); - free(lambda); -} - AST* ast_find(Scope* scope, char* name) { while (scope) { AST* gotten = htab_get(scope->here, name); diff --git a/src/ast_print.c b/src/ast_print.c new file mode 100644 index 0000000..cb656ca --- /dev/null +++ b/src/ast_print.c @@ -0,0 +1,139 @@ +#include "include/ast_print.h" +#include "include/dstr.h" +#include "include/util.h" +#include + +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; +} diff --git a/src/exec.c b/src/exec.c index ba64b71..d896424 100644 --- a/src/exec.c +++ b/src/exec.c @@ -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; diff --git a/src/grammar.y b/src/grammar.y index 973efe0..1c1f38e 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -126,32 +126,27 @@ block: exp: NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); } - // Function definitions. + // Function definitions. Convert to VDef of Lambda. | WORD GROUPS arg GROUPE exp { - size_t argc = $3->ln; - AST** argv = $3->buf; + size_t parc = $3->ln; + AST** parv = $3->buf; argarr_destroypsv($3); - $$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $5)); + $$ = 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 argc = $3->ln; - AST** argv = $3->buf; + size_t parc = $3->ln; + AST** parv = $3->buf; argarr_destroypsv($3); - $$ = ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init(argc, argv, $5)); + $$ = ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init(parc, parv, $5)); } - /* - // Inline call. - | exp GROUPS arg GROUPE { - size_t argc = $3->ln; - AST** argv = $3->buf; - argarr_destroypsv($3); - $$ = ast_init(AST_TYPE_CALL, ($1, argc, argv)); - } - */ - | BLOCKS block BLOCKE { $$ = ast_init(AST_TYPE_BLOCK, ast_block_data_init((AST**) $2->buf, $2->ln)); } diff --git a/src/include/ast.h b/src/include/ast.h index 05d76d1..cbf1163 100644 --- a/src/include/ast.h +++ b/src/include/ast.h @@ -40,10 +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); +void ast_destroy(AST* ast); // A number. typedef double ASTNumData; @@ -63,15 +61,6 @@ ASTExcData* ast_exc_data_init(const char* msg, AST* trace); // Destroy an `ASTExecData`. void ast_exc_data_destroy(ASTExcData* exc); -// A variable; associates a name with an expression. -typedef struct { - char* name; - AST* val; -} ASTVar; - -#define ARG(VAL) (ASTVar){NULL, VAL} -#define PAR(NAME) (ASTVar){NAME, NULL} - // Argument list as anonymous struct. #define ARGS \ struct { \ @@ -94,33 +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. - ARGS; // argument list + 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); +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); +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; @@ -165,6 +162,7 @@ ASTArgData* ast_arg_data_init(char* name); // Destroy an `ASTArgData`. void ast_arg_data_destroy(ASTArgData* arg); +/* // Represents a function as data. typedef struct { ARGS; @@ -176,6 +174,7 @@ 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); diff --git a/src/include/ast_print.h b/src/include/ast_print.h new file mode 100644 index 0000000..e6cd57f --- /dev/null +++ b/src/include/ast_print.h @@ -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 diff --git a/type-notes.md b/type-notes.md new file mode 100644 index 0000000..e59cc4a --- /dev/null +++ b/type-notes.md @@ -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 |