From 289243de38c3be48eafb8cb7addd618ff2af277b Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 28 Jun 2025 11:15:21 -0400 Subject: [PATCH] Added lambda parsing. --- src/ast.c | 81 ++++++++++++++++++++++++++++++++--------------- src/grammar.y | 11 +++++++ src/include/ast.h | 44 ++++++++++++++----------- src/lexer.c | 1 + 4 files changed, 94 insertions(+), 43 deletions(-) diff --git a/src/ast.c b/src/ast.c index b21866c..e8eba2f 100644 --- a/src/ast.c +++ b/src/ast.c @@ -17,7 +17,9 @@ static char* asttype_names[] = { [AST_TYPE_BLOCK] = "BLOCK", [AST_TYPE_EXC] = "EXCEPTION", [AST_TYPE_FDEF] = "FUNCTION DEFINITION", - [AST_TYPE_ARG] = "DEFINITION ARGUMENT" + [AST_TYPE_ARG] = "DEFINITION ARGUMENT", + [AST_TYPE_LAMBDA] = "LAMBDA EXPRESSION" + }; AST* ast_init(ASTType type, void* data) { @@ -51,13 +53,14 @@ void ast_destroy(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(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_NUM: ast_num_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_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); } @@ -72,15 +75,16 @@ 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_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); } @@ -104,14 +108,15 @@ void ast_print_i(AST* ast, int i) { 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); + 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; @@ -344,6 +349,32 @@ void ast_arg_print(ASTArgData* arg, int i) { INDENT_END; } +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); +} + +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; +} + AST* ast_find(Scope* scope, char* name) { while (scope) { AST* gotten = htab_get(scope->here, name); diff --git a/src/grammar.y b/src/grammar.y index c5375c5..4eb1508 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -47,6 +47,8 @@ %token NL // Newline. +%token BACKSLASH + %left ADD SUB %left MUL DIV %precedence NEG @@ -132,6 +134,15 @@ exp: $$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $5)); } + // Lambda definitions. + | BACKSLASH GROUPS arg GROUPE exp { + size_t argc = $3->ln; + AST** argv = $3->buf; + argarr_destroypsv($3); + $$ = ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init(argc, argv, $5)); + } + + | 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 a47f67c..9f2239d 100644 --- a/src/include/ast.h +++ b/src/include/ast.h @@ -18,13 +18,14 @@ typedef enum { 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_VDEF, // A variable definition. - AST_TYPE_VREF, // A variable reference. - AST_TYPE_BLOCK, // A block of code (scope). - AST_TYPE_FDEF, // A function definition. - AST_TYPE_ARG, // A definition argument. + AST_TYPE_BIF, // Built-in function. + AST_TYPE_CALL, // A function call. + AST_TYPE_VDEF, // A variable definition. + 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; @@ -60,8 +61,8 @@ void ast_num_print(ASTNumData*, int i); // An exception. typedef struct ASTEXCDATA { - const char* msg; // The exception message. - AST* trace; // The previous exception. + const char* msg; // The exception message. + AST* trace; // The previous exception. } ASTExcData; // Create a new `ASTExecData. `msg` should be static. ASTExcData* ast_exc_data_init(const char* msg, AST* trace); @@ -71,7 +72,11 @@ void ast_exc_data_destroy(ASTExcData* exc); void ast_exc_print(ASTExcData*, int i); // arguments list as anonymous struct -#define ARGS struct { size_t argc; AST** argv; } +#define ARGS \ + struct { \ + size_t argc; \ + AST** argv; \ + } // A built-in function. typedef AST* (*ASTBIFData)(size_t argc, AST** argv, Scope* scope); @@ -90,8 +95,8 @@ typedef struct { */ // A call (to a function). typedef struct { - char* to; // What the call's to. - ARGS; // argument list + char* to; // What the call's to. + ARGS; // argument list } ASTCallData; // Create a new `ASTCallData`. @@ -99,7 +104,7 @@ ASTCallData* ast_call_data_init(char* to, size_t argc, AST** argv); // Destroy an `ASTCallData` recursively. void ast_call_data_destroy(ASTCallData* call); // Destroy an `ASTCallData`. -void ast_call_data_destroy_psv(ASTCallData *call); +void ast_call_data_destroy_psv(ASTCallData* call); // Print an `ASTCallData`. void ast_call_print(ASTCallData*, int i); @@ -141,14 +146,14 @@ 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); +void ast_block_data_destroy_psv(ASTBlockData* block); // Print an `ASTBlockData`. void ast_block_print(ASTBlockData*, int i); typedef struct { - char* name; // Function name. - ARGS; // Function args. - AST* body; // Function body. + char* name; // Function name. + ARGS; // Function args. + AST* body; // Function body. } ASTFDefData; // Create a new `ASTFDefData`. @@ -179,7 +184,10 @@ typedef struct { // Creates a new `ASTLambdaData`. ASTLambdaData* ast_lambda_data_init(size_t argc, AST** argv, AST* body); -// Destroy an `AST +// Destroy an `ASTLambdaData`. +void ast_lambda_data_destroy(ASTLambdaData*); +// Print an `ASTLambdaData`. +void ast_lambda_print(ASTLambdaData* arg, int i); // Find a name in the scope. AST* ast_find(Scope* scope, char* name); diff --git a/src/lexer.c b/src/lexer.c index 5c909d7..f3217fa 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -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); }