summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-28 16:08:49 +0200
committerPaul Buetow <paul@buetow.org>2026-02-28 16:08:49 +0200
commit5f557ebafb596755cb3047cbdafa6122166c26ac (patch)
tree38311c31975d8cb9c8b211252c3c0865802d2d90
parent946fac7d813f6283c18087a46b9e2ee084852c64 (diff)
Refactor _term() by extracting _term_ident(), _term_array_literal(), _term_paren() [SRP]
_term() was ~130 lines mixing literal push, array literal construction, identifier resolution, parenthesized expressions, and defined/undef/syms. Extracted three static helpers: - _term_ident(): resolves TT_IDENT as array access, builtin call, self-defined function/proc call, or variable/procedure (~90 lines; acceptable given the complexity of identifier resolution) - _term_array_literal(): builds an array from [expr, ...] syntax - _term_paren(): evaluates a parenthesised expression and checks ')' _term() is now a ~100-line dispatcher. The defined/undef/syms cases remain inline as they are self-contained ~10-line blocks. Also fixes a latent double-assignment bug in _term_array_literal(): the original `TokenType tt = tt = p_interpret->tt;` is now `= p_interpret->tt;`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--docs/help.txt2
-rw-r--r--docs/stats.txt2
-rw-r--r--docs/version.txt2
-rwxr-xr-xfypebin288168 -> 288368 bytes
-rw-r--r--src/build.h2
-rw-r--r--src/core/interpret.c301
-rw-r--r--tags3
7 files changed, 169 insertions, 143 deletions
diff --git a/docs/help.txt b/docs/help.txt
index f4a8e65..fae20f2 100644
--- a/docs/help.txt
+++ b/docs/help.txt
@@ -1,4 +1,4 @@
-Fype Superalpha Build 9691
+Fype Superalpha Build 9701
(c) Paul C. Buetow (2005 - 2008) <fype@dev.buetow.org>
-e Executes given code string (see synopses)
-h Prints this help
diff --git a/docs/stats.txt b/docs/stats.txt
index bf4e4cc..47a0f36 100644
--- a/docs/stats.txt
+++ b/docs/stats.txt
@@ -1,6 +1,6 @@
make[1]: Entering directory '/home/paul/git/fype'
===> Num of C source files : 46
-===> Num of C source lines : 8702
+===> Num of C source lines : 8725
===> Num of Fype source examples : 19
===> Num of Fype source lines : 883
make[1]: Leaving directory '/home/paul/git/fype'
diff --git a/docs/version.txt b/docs/version.txt
index e0f6705..dbb9597 100644
--- a/docs/version.txt
+++ b/docs/version.txt
@@ -1 +1 @@
-Fype Superalpha Build 9691
+Fype Superalpha Build 9701
diff --git a/fype b/fype
index c4efecd..0d4febb 100755
--- a/fype
+++ b/fype
Binary files differ
diff --git a/src/build.h b/src/build.h
index fce9d6f..b96d7c4 100644
--- a/src/build.h
+++ b/src/build.h
@@ -36,7 +36,7 @@
#ifndef BUILD_H
#define BUILD_H
-#define BUILDNR 9698
+#define BUILDNR 9702
#define OS_LINUX
#endif
diff --git a/src/core/interpret.c b/src/core/interpret.c
index 085f716..b6c7c33 100644
--- a/src/core/interpret.c
+++ b/src/core/interpret.c
@@ -79,6 +79,9 @@ int _program(Interpret *p_interpret);
int _statement(Interpret *p_interpret);
int _sum(Interpret *p_interpret);
int _term(Interpret *p_interpret);
+static int _term_ident(Interpret *p_interpret);
+static int _term_array_literal(Interpret *p_interpret);
+static int _term_paren(Interpret *p_interpret);
int _term_array_access(Interpret *p_interpret,
Token *p_token_array, Array *p_array);
int _var_assign(Interpret *p_interpret);
@@ -1053,132 +1056,190 @@ _term_array_access(Interpret *p_interpret,
return (1);
}
-int
-_term(Interpret *p_interpret) {
- _CHECK TRACK
+/* Handle the TT_IDENT case in _term(): resolve the identifier as an array
+ * access, builtin call, self-defined function/procedure call, or variable.
+ * Returns 1 on success, 0 if no matching symbol kind is handled. */
+static int
+_term_ident(Interpret *p_interpret) {
+ if (_NEXT_TT != TT_ASSIGN) {
+ if (_NEXT_TT == TT_PARANT_AL) {
+ /* Delegate to the array-access / slice helper */
+ char *c_name = token_get_val(p_interpret->p_token);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
- switch (p_interpret->tt) {
- case TT_ARRAY:
- case TT_STRING:
- case TT_INTEGER:
- case TT_DOUBLE:
- stack_push(p_interpret->p_stack, p_interpret->p_token);
- // Checks if the term is the last element of an array
- // say ["element"] # The "element"
- // or of a function
- // func foo { say 1 } # The 1
- if (_NEXT_TT != TT_PARANT_AR && _NEXT_TT != TT_PARANT_CR)
- _NEXT
- return (1);
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
- case TT_IDENT:
- {
- if (_NEXT_TT != TT_ASSIGN) {
- if (_NEXT_TT == TT_PARANT_AL) {
- /* Delegate to the array-access / slice helper */
- char *c_name = token_get_val(p_interpret->p_token);
- Symbol *p_symbol = scope_get(
- p_interpret->p_scope, c_name);
+ Token *p_token_array = symbol_get_val(p_symbol);
+ Array *p_array = TOKEN_GET_ARRAY(p_token_array);
- if (p_symbol == NULL)
- _INTERPRET_ERROR("No such symbol",
- p_interpret->p_token);
- Token *p_token_array = symbol_get_val(p_symbol);
- Array *p_array = TOKEN_GET_ARRAY(p_token_array);
- if (p_array == NULL)
- _INTERPRET_ERROR("Expected an array",
- p_interpret->p_token);
+ if (p_array == NULL)
+ _INTERPRET_ERROR("Expected an array", p_interpret->p_token);
- return (_term_array_access(p_interpret,
- p_token_array, p_array));
+ return (_term_array_access(p_interpret, p_token_array, p_array));
- } else if (function_is_buildin(p_interpret->p_token)) {
- Token *p_token = p_interpret->p_token;
- Stack *p_stack = p_interpret->p_stack;
- p_interpret->p_stack = stack_new();
+ } else if (function_is_buildin(p_interpret->p_token)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
- if (_HAS_NEXT) {
- _NEXT
- //if (_expression_(p_interpret));
- _expression_(p_interpret);
+ if (_HAS_NEXT) {
+ _NEXT
+ //if (_expression_(p_interpret));
+ _expression_(p_interpret);
- } else {
- _SKIP
+ } else {
+ _SKIP
+ }
+
+ function_process_buildin(p_interpret, p_token,
+ p_interpret->p_stack);
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ return (1);
+
+ } else if (function_is_self_defined(p_interpret)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ _NEXT /* advance past function name */
+ if (p_interpret->tt == TT_PARANT_L) {
+ /* Parenthesised call: func(arg1, arg2) — collect args */
+ _NEXT /* past '(' */
+ while (p_interpret->tt != TT_PARANT_R
+ && p_interpret->tt != TT_NONE) {
+ _expression_(p_interpret);
+ if (p_interpret->tt == TT_COMMA)
+ _NEXT /* past ',' between arguments */
}
+ _NEXT /* past ')' */
+ } else {
+ /* Old-style call without parens (procedures; zero-arg funcs) */
+ if (_expression_(p_interpret));
+ }
- function_process_buildin(p_interpret, p_token,
- p_interpret->p_stack);
+ function_process_self_defined(p_interpret, p_token);
- stack_merge(p_stack, p_interpret->p_stack);
- stack_delete(p_interpret->p_stack);
- p_interpret->p_stack = p_stack;
+ if (stack_empty(p_interpret->p_stack)) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, 0);
+ stack_push(p_interpret->p_stack, p_token);
+ }
- return (1);
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
- } else if (function_is_self_defined(p_interpret)) {
- Token *p_token = p_interpret->p_token;
- Stack *p_stack = p_interpret->p_stack;
- p_interpret->p_stack = stack_new();
+ return (1);
+ }
+ }
- _NEXT /* advance past function name */
- if (p_interpret->tt == TT_PARANT_L) {
- /* Parenthesised call: func(arg1, arg2) — collect args */
- _NEXT /* past '(' */
- while (p_interpret->tt != TT_PARANT_R
- && p_interpret->tt != TT_NONE) {
- _expression_(p_interpret);
- if (p_interpret->tt == TT_COMMA)
- _NEXT /* past ',' between arguments */
- }
- _NEXT /* past ')' */
- } else {
- /* Old-style call without parens (procedures; zero-arg funcs) */
- if (_expression_(p_interpret));
- }
+ /* It is not a function, it is a variable or some sort of */
- function_process_self_defined(p_interpret, p_token);
+ char *c_name = token_get_val(p_interpret->p_token);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
- if (stack_empty(p_interpret->p_stack)) {
- Token *p_token = token_new_dummy();
- token_set_tt(p_token, TT_INTEGER);
- token_set_ival(p_token, 0);
- stack_push(p_interpret->p_stack, p_token);
- }
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
- stack_merge(p_stack, p_interpret->p_stack);
- stack_delete(p_interpret->p_stack);
- p_interpret->p_stack = p_stack;
+ SymbolType st = symbol_get_sym(p_symbol);
- return (1);
+ switch (st) {
+ case SYM_VARIABLE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ /* Example: proc foo { foo = "Hello"; } foo; say foo; */
+ case SYM_PROCEDURE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ NO_DEFAULT;
+ }
+
+ return (0);
+}
+
+/* Handle the TT_PARANT_AL case in _term(): construct an array literal.
+ * Reads comma/semicolon-separated expressions until ']' and pushes the
+ * resulting array token onto the eval stack. */
+static int
+_term_array_literal(Interpret *p_interpret) {
+ Token *p_token_arr = token_new_array(ARRAY_SIZE);
+ Array *p_array = p_token_arr->p_array;
+
+ _NEXT
+ /* Collect array elements; commas and semicolons are skipped */
+ while (p_interpret->tt != TT_PARANT_AR) {
+ TokenType tt = p_interpret->tt;
+ if (tt != TT_COMMA && tt != TT_SEMICOLON) {
+ UNLESS (_expression_(p_interpret)) {
+ Token *p_token = p_interpret->p_token;
+ _INTERPRET_ERROR("Expected expression", p_token);
}
+
+ array_unshift(p_array, stack_pop(p_interpret->p_stack));
}
- /* It is not a function, it is a variable or some sort of */
+ _NEXT
+ }
- char *c_name = token_get_val(p_interpret->p_token);
- Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
+ stack_push(p_interpret->p_stack, p_token_arr);
+ _NEXT
+ return (1);
+}
- if (p_symbol == NULL)
- _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
+/* Handle the TT_PARANT_L case in _term(): evaluate a parenthesised
+ * expression and verify the closing ')'. */
+static int
+_term_paren(Interpret *p_interpret) {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
- SymbolType st = symbol_get_sym(p_symbol);
+ if (_expression_(p_interpret)) {
+ if (p_interpret->tt != TT_PARANT_R)
+ _INTERPRET_ERROR("Expected ')'", p_token);
- switch (st) {
- case SYM_VARIABLE:
- stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
- _NEXT
- return (1);
+ } else {
+ _INTERPRET_ERROR("Expected expression", p_token);
+ }
- /* Example: proc foo { foo = "Hello"; } foo; say foo; */
- case SYM_PROCEDURE:
- stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+}
+
+/* Evaluate a single atomic expression term and push its value onto the eval
+ * stack. Dispatches to per-case helpers for the complex TT_IDENT,
+ * TT_PARANT_AL, and TT_PARANT_L cases.
+ * Returns 1 on match, 2 on token-stream exhaustion, 0 on no match. */
+int
+_term(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ switch (p_interpret->tt) {
+ case TT_ARRAY:
+ case TT_STRING:
+ case TT_INTEGER:
+ case TT_DOUBLE:
+ stack_push(p_interpret->p_stack, p_interpret->p_token);
+ // Checks if the term is the last element of an array
+ // say ["element"] # The "element"
+ // or of a function
+ // func foo { say 1 } # The 1
+ if (_NEXT_TT != TT_PARANT_AR && _NEXT_TT != TT_PARANT_CR)
_NEXT
return (1);
- NO_DEFAULT;
- }
- }
- break;
+ case TT_IDENT:
+ return (_term_ident(p_interpret));
+
case TT_DEFINED:
{
_NEXT
@@ -1210,7 +1271,7 @@ _term(Interpret *p_interpret) {
Token *p_token = NULL;
Symbol *p_symbol = NULL;
- if ((p_symbol = scope_remove(p_interpret->p_scope, c_name))) {
+ if ((p_symbol = scope_remove(p_interpret->p_scope, c_name))) {
symbol_delete(p_symbol);
p_token = token_new_integer(1);
@@ -1237,7 +1298,6 @@ _term(Interpret *p_interpret) {
if (p_symbol == NULL)
_INTERPRET_ERROR("No such symbol", p_interpret->p_token);
-
Token *p_token_num_refs = token_new_integer(p_symbol->i_refs);
stack_push(p_interpret->p_stack, p_token_num_refs);
@@ -1247,47 +1307,10 @@ _term(Interpret *p_interpret) {
break;
case TT_PARANT_AL:
- {
- Token *p_token_arr = token_new_array(ARRAY_SIZE);
- Array *p_array = p_token_arr->p_array;
-
- _NEXT
- // Get the array elements
- while (p_interpret->tt != TT_PARANT_AR) {
- TokenType tt = tt = p_interpret->tt;
- if (tt != TT_COMMA && tt != TT_SEMICOLON) {
- UNLESS (_expression_(p_interpret)) {
- Token *p_token = p_interpret->p_token;
- _INTERPRET_ERROR("Expected expression", p_token);
- }
-
- array_unshift(p_array, stack_pop(p_interpret->p_stack));
- }
-
- _NEXT
- }
-
- stack_push(p_interpret->p_stack, p_token_arr);
- _NEXT
- return (1);
- }
- break;
+ return (_term_array_literal(p_interpret));
case TT_PARANT_L:
- {
- Token *p_token = p_interpret->p_token;
- _NEXT
-
- if (_expression_(p_interpret)) {
- if (p_interpret->tt != TT_PARANT_R)
- _INTERPRET_ERROR("Expected ')'", p_token);
-
- } else {
- _INTERPRET_ERROR("Expected expression", p_token);
- }
- }
- _NEXT
- return (1);
+ return (_term_paren(p_interpret));
default:
break;
diff --git a/tags b/tags
index 15c91fa..97d0b0b 100644
--- a/tags
+++ b/tags
@@ -131,6 +131,9 @@ _statement ./src/core/interpret.c /^_statement(Interpret *p_interpret) {$/;" f t
_sum ./src/core/interpret.c /^_sum(Interpret *p_interpret) {$/;" f typeref:typename:int
_term ./src/core/interpret.c /^_term(Interpret *p_interpret) {$/;" f typeref:typename:int
_term_array_access ./src/core/interpret.c /^_term_array_access(Interpret *p_interpret,$/;" f typeref:typename:int
+_term_array_literal ./src/core/interpret.c /^_term_array_literal(Interpret *p_interpret) {$/;" f typeref:typename:int file:
+_term_ident ./src/core/interpret.c /^_term_ident(Interpret *p_interpret) {$/;" f typeref:typename:int file:
+_term_paren ./src/core/interpret.c /^_term_paren(Interpret *p_interpret) {$/;" f typeref:typename:int file:
_tree_print ./src/data/tree.c /^_tree_print(TreeNode *p_treenode, int i_indent) {$/;" f typeref:typename:void
_tree_print_cb ./src/data/tree.c /^_tree_print_cb(void *p_void, void *p_indent) {$/;" f typeref:typename:void
_tree_print_cb2 ./src/data/tree.c /^_tree_print_cb2(void *p_void, void *p_indent) {$/;" f typeref:typename:void