Added lambda parsing.

This commit is contained in:
Jacob Signorovitch 2025-06-28 11:15:21 -04:00
parent 67aafb3ead
commit 289243de38
4 changed files with 94 additions and 43 deletions

View File

@ -17,7 +17,9 @@ static char* asttype_names[] = {
[AST_TYPE_BLOCK] = "BLOCK", [AST_TYPE_BLOCK] = "BLOCK",
[AST_TYPE_EXC] = "EXCEPTION", [AST_TYPE_EXC] = "EXCEPTION",
[AST_TYPE_FDEF] = "FUNCTION DEFINITION", [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) { AST* ast_init(ASTType type, void* data) {
@ -51,13 +53,14 @@ 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;
case AST_TYPE_FDEF: ast_fdef_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_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_LAMBDA: ast_lambda_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);
} }
@ -72,15 +75,16 @@ void ast_destroy_psv(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_psv(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_VREF: ast_vref_data_destroy(ast->data); break;
case AST_TYPE_VDEF: ast_vdef_data_destroy_psv(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_BLOCK: ast_block_data_destroy_psv(ast->data); break;
case AST_TYPE_FDEF: ast_fdef_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_ARG: ast_arg_data_destroy(ast->data); break;
case AST_TYPE_BIF: ast_bif_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_EXC: ast_exc_data_destroy(ast->data); break;
case AST_TYPE_LAMBDA: ast_lambda_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);
} }
@ -104,14 +108,15 @@ void ast_print_i(AST* ast, int i) {
case AST_TYPE_NUM: case AST_TYPE_NUM:
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_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;
case AST_TYPE_FDEF: ast_fdef_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_ARG: ast_arg_print(ast->data, i + 2); break;
default: exit(1); case AST_TYPE_LAMBDA: ast_lambda_print(ast->data, i + 2); break;
default: exit(1);
} }
INDENT_FIELD_NONL_END; INDENT_FIELD_NONL_END;
INDENT_END; INDENT_END;
@ -344,6 +349,32 @@ void ast_arg_print(ASTArgData* arg, int i) {
INDENT_END; 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) { AST* ast_find(Scope* scope, char* name) {
while (scope) { while (scope) {
AST* gotten = htab_get(scope->here, name); AST* gotten = htab_get(scope->here, name);

View File

@ -47,6 +47,8 @@
%token NL // Newline. %token NL // Newline.
%token BACKSLASH
%left ADD SUB %left ADD SUB
%left MUL DIV %left MUL DIV
%precedence NEG %precedence NEG
@ -132,6 +134,15 @@ exp:
$$ = ast_init(AST_TYPE_FDEF, ast_fdef_data_init($1, argc, argv, $5)); $$ = 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 { | BLOCKS block BLOCKE {
$$ = ast_init(AST_TYPE_BLOCK, ast_block_data_init((AST**) $2->buf, $2->ln)); $$ = ast_init(AST_TYPE_BLOCK, ast_block_data_init((AST**) $2->buf, $2->ln));
} }

View File

@ -18,13 +18,14 @@ typedef enum {
AST_TYPE_LIST, // A list (variable size, variable type). AST_TYPE_LIST, // A list (variable size, variable type).
// Misc. types. // Misc. types.
AST_TYPE_BIF, // Built-in function. 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.
AST_TYPE_BLOCK, // A block of code (scope). AST_TYPE_BLOCK, // A block of code (scope).
AST_TYPE_FDEF, // A function definition. AST_TYPE_FDEF, // A function definition.
AST_TYPE_ARG, // A definition argument. AST_TYPE_LAMBDA, // An anonymous function definition.
AST_TYPE_ARG, // A definition argument.
AST_TYPE_MAX = AST_TYPE_ARG, AST_TYPE_MAX = AST_TYPE_ARG,
} ASTType; } ASTType;
@ -60,8 +61,8 @@ void ast_num_print(ASTNumData*, int i);
// An exception. // An exception.
typedef struct ASTEXCDATA { typedef struct ASTEXCDATA {
const char* msg; // The exception message. const char* msg; // The exception message.
AST* trace; // The previous exception. AST* trace; // The previous exception.
} ASTExcData; } ASTExcData;
// Create a new `ASTExecData. `msg` should be static. // Create a new `ASTExecData. `msg` should be static.
ASTExcData* ast_exc_data_init(const char* msg, AST* trace); 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); void ast_exc_print(ASTExcData*, int i);
// arguments list as anonymous struct // 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. // A built-in function.
typedef AST* (*ASTBIFData)(size_t argc, AST** argv, Scope* scope); typedef AST* (*ASTBIFData)(size_t argc, AST** argv, Scope* scope);
@ -90,8 +95,8 @@ typedef struct {
*/ */
// A call (to a function). // A call (to a function).
typedef struct { typedef struct {
char* to; // What the call's to. char* to; // What the call's to.
ARGS; // argument list ARGS; // argument list
} ASTCallData; } ASTCallData;
// Create a new `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. // Destroy an `ASTCallData` recursively.
void ast_call_data_destroy(ASTCallData* call); void ast_call_data_destroy(ASTCallData* call);
// Destroy an `ASTCallData`. // Destroy an `ASTCallData`.
void ast_call_data_destroy_psv(ASTCallData *call); void ast_call_data_destroy_psv(ASTCallData* call);
// Print an `ASTCallData`. // Print an `ASTCallData`.
void ast_call_print(ASTCallData*, int i); 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. // Destroy an `ASTBlockData`, recursively.
void ast_block_data_destroy(ASTBlockData* block); void ast_block_data_destroy(ASTBlockData* block);
// Destroy an `ASTBlockData`. // Destroy an `ASTBlockData`.
void ast_block_data_destroy_psv(ASTBlockData *block); void ast_block_data_destroy_psv(ASTBlockData* block);
// Print an `ASTBlockData`. // Print an `ASTBlockData`.
void ast_block_print(ASTBlockData*, int i); void ast_block_print(ASTBlockData*, int i);
typedef struct { typedef struct {
char* name; // Function name. char* name; // Function name.
ARGS; // Function args. ARGS; // Function args.
AST* body; // Function body. AST* body; // Function body.
} ASTFDefData; } ASTFDefData;
// Create a new `ASTFDefData`. // Create a new `ASTFDefData`.
@ -179,7 +184,10 @@ typedef struct {
// Creates a new `ASTLambdaData`. // Creates a new `ASTLambdaData`.
ASTLambdaData* ast_lambda_data_init(size_t argc, AST** argv, AST* body); 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. // Find a name in the scope.
AST* ast_find(Scope* scope, char* name); AST* ast_find(Scope* scope, char* name);

View File

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