From 2ce89fb39a7529fa416b7724f4c786ff3921d4af Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 11 Jan 2025 10:35:42 -0500 Subject: [PATCH] Added arbitrary length functions. --- README.md | 2 +- src/exec.c | 6 ++++++ src/grammar.y | 35 +++++++++++++++++++++++++++++------ src/include/lexer.h | 18 +++++++++++++++++- src/lexer.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 5489fa8..f02a16d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ include the [Unity](https://github.com/ThrowTheSwitch/Unity) test framework. - [x] Negative numbers - [x] Basic binary infix operators; `+`, `-`, `*`, `/` - [x] The same as conventional functions; `sum()`, `sub()`, `mul()`, `div()` -- [ ] Arbitrary length functions +- [x] Arbitrary length functions - [ ] User-defined variables - [ ] Control flow - [ ] User-defined functions diff --git a/src/exec.c b/src/exec.c index d0744dd..9335ca5 100644 --- a/src/exec.c +++ b/src/exec.c @@ -41,6 +41,12 @@ ASTNumData exec_call(AST* ast) { ASTNumData n2 = exec_expr(calldata->argv[1]); return n1 / n2; + } else if (!strcmp(calldata->to, "sum") && calldata->argc == 3) { + ASTNumData n1 = exec_expr(calldata->argv[0]); + ASTNumData n2 = exec_expr(calldata->argv[1]); + ASTNumData n3 = exec_expr(calldata->argv[2]); + + return n1 + n2 + n3; } return -1000; } diff --git a/src/grammar.y b/src/grammar.y index 5ec3dd4..1a9a2be 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -17,6 +17,7 @@ double fval; char* strval; AST* ast; + ArgArr* argarr; } %define parse.error verbose @@ -41,6 +42,8 @@ %type num; %type exp; +%type arg; +%type argstart; %% @@ -54,15 +57,35 @@ num: | SUB NUM { $$ = -$2; } %prec NEG ; +argstart: + exp { + ArgArr* argarr = argarr_init(); + argarr_add(argarr, $1); + $$ = argarr; + } + +arg: + argstart { $$ = $1; } + | arg SEP exp { + argarr_add($1, $3); + $$ = $1; + } + ; + exp: num { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); } - // name(thing, thing) - | CALL LGROUP exp SEP exp RGROUP { - AST** argv = calloc(2, sizeof(AST*)); - argv[0] = $3; - argv[1] = $5; - $$ = ast_init(AST_TYPE_CALL, ast_call_data_init($1, 2, argv)); + // name(thing-1, thing-2, ..., thing-n) + // name(thing) + // name() + + // larg: lgroup marg + // lgroup rgroup + // marg: exp sep marg + // exp rgroup + + | CALL LGROUP arg RGROUP { + $$ = ast_init(AST_TYPE_CALL, ast_call_data_init($1, $3->ln, $3->buf)); } | exp PLUS exp { diff --git a/src/include/lexer.h b/src/include/lexer.h index e5d7e1d..6f883ac 100644 --- a/src/include/lexer.h +++ b/src/include/lexer.h @@ -2,11 +2,27 @@ #define LEXER_H #include +#include + +#include "ast.h" + +#define ARLN 8 + +extern char* inp; + +typedef struct { + size_t sz; + size_t ln; + AST** buf; +} ArgArr; + +ArgArr* argarr_init(); +void argarr_destroy(ArgArr* argarr); +void argarr_add(ArgArr* argarr, AST* arg); #include "../../build/grammars/grammar.tab.h" extern YYSTYPE yylval; -extern char* inp; // Accumulate an integer. int acc_int(int c); diff --git a/src/lexer.c b/src/lexer.c index eea5788..83be8da 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -1,11 +1,43 @@ +#include #include #include #include #include #include "include/dstr.h" +#include "include/util.h" #include "include/lexer.h" +ArgArr* argarr_init() { + ArgArr* argarr = malloc(sizeof(ArgArr)); + + argarr->sz = ARLN; + argarr->ln = 0; + argarr->buf = malloc(ARLN); + + return argarr; +} + +void argarr_destroy(ArgArr* argarr) { + free(argarr->buf); + free(argarr); +} + +void argarr_add(ArgArr* argarr, AST* arg) { + if (argarr->ln + 1 > argarr->sz) { + argarr->sz *= 2; + argarr->buf = realloc(argarr->buf, argarr->sz); + log_dbgf( + "ArgArr @ %p doubled from %ld to %ld", + argarr, + argarr->sz/2, + argarr->sz + ); + } + + argarr->buf[argarr->ln++] = arg; +} + int acc_int(int c) { int value = c - '0'; while (isdigit(*inp)) {