diff --git a/src/calendar.c b/src/calendar.c index 3e5c0343..31ff5081 100644 --- a/src/calendar.c +++ b/src/calendar.c @@ -1761,6 +1761,8 @@ static void GenerateCalEntries(int col) tok.type != T_Else && tok.type != T_EndIf && tok.type != T_IfTrig && + tok.type != T_Set && + tok.type != T_Fset && should_ignore_line()) { /* DO NOTHING */ diff --git a/src/expr.c b/src/expr.c index 7187d836..6367b43f 100644 --- a/src/expr.c +++ b/src/expr.c @@ -747,6 +747,10 @@ eval_userfunc(expr_node *node, Value *locals, Value *ans, int *nonconst) FuncRecursionLevel++; + if (!f->is_constant) { + nonconst_debug(*nonconst, tr("User function `%s' defined in non-constant context makes expression non-constant"), f->name); + *nonconst = 1; + } /* Add a call to the call stack for better error messages */ pushed = push_call(f->filename, f->name, f->lineno, f->lineno_start); diff --git a/src/main.c b/src/main.c index b9e217f7..6d994c7e 100644 --- a/src/main.c +++ b/src/main.c @@ -287,6 +287,8 @@ static void DoReminders(void) tok.type != T_Else && tok.type != T_EndIf && tok.type != T_IfTrig && + tok.type != T_Set && + tok.type != T_Fset && should_ignore_line()) { /*** IGNORE THE LINE ***/ diff --git a/src/types.h b/src/types.h index 8e604aa5..0769d1e5 100644 --- a/src/types.h +++ b/src/types.h @@ -296,6 +296,7 @@ typedef struct { typedef struct udf_struct { struct hash_link link; char name[VAR_NAME_LEN+1]; + char is_constant; expr_node *node; char **args; int nargs; diff --git a/src/userfns.c b/src/userfns.c index 325fb8f4..8bf60a30 100644 --- a/src/userfns.c +++ b/src/userfns.c @@ -196,6 +196,20 @@ int DoFset(ParsePtr p) /* Convert to lower-case */ strtolower(DBufValue(&buf)); + /* If we're ignoring the line, just update is_constant flag if needed */ + if (should_ignore_line()) { + if (in_constant_context()) { + DBufFree(&buf); + return OK; + } + existing = FindUserFunc(DBufValue(&buf)); + if (existing) { + nonconst_debug(!existing->is_constant, tr("Function definition considered non-constant because of context")); + existing->is_constant = 0; + } + DBufFree(&buf); + return OK; + } /* If the function exists and was defined at the same line of the same file, do nothing */ existing = FindUserFunc(DBufValue(&buf)); @@ -240,6 +254,12 @@ int DoFset(ParsePtr p) func->lineno = LineNo; func->lineno_start = LineNoStart; func->recurse_flag = 0; + if (in_constant_context()) { + func->is_constant = 1; + } else { + nonconst_debug(0, tr("Function definition considered non-constant because of context")); + func->is_constant = 0; + } StrnCpy(func->name, DBufValue(&buf), VAR_NAME_LEN); DBufFree(&buf); if (!Hush) { diff --git a/src/var.c b/src/var.c index d7ee663e..cb72fef5 100644 --- a/src/var.c +++ b/src/var.c @@ -604,14 +604,31 @@ int DoSet (Parser *p) Value v; int r; int ch; + int ignoring = should_ignore_line(); DynamicBuffer buf; DynamicBuffer buf2; DBufInit(&buf); DBufInit(&buf2); + Var *var; r = ParseIdentifier(p, &buf); if (r) return r; + if (ignoring) { + /* We're only here to mark a variable as non-const */ + if (in_constant_context()) { + DBufFree(&buf); + return OK; + } + var = FindVar(DBufValue(&buf), 0); + if (var) { + nonconst_debug(var->nonconstant, tr("Variable assignment considered non-constant because of context")); + var->nonconstant = 1; + } + DBufFree(&buf); + return OK; + } + /* Allow optional equals-sign: SET var = value */ ch = ParseNonSpaceChar(p, &r, 1); if (r) return r; diff --git a/tests/test.cmp b/tests/test.cmp index 5445c7e6..d48f6279 100644 --- a/tests/test.cmp +++ b/tests/test.cmp @@ -24813,6 +24813,7 @@ TRANSLATE "Executing `%s' for INCLUDECMD and caching as `%s'" "" TRANSLATE "Found cached directory listing for `%s'" "" TRANSLATE "Function `%s' defined at %s(%s) should take %d argument%s, but actually takes %d" "" TRANSLATE "Function `%s' redefined: previously defined at %s(%s)" "" +TRANSLATE "Function definition considered non-constant because of context" "" TRANSLATE "GetValidHebDate: Bad adarbehave value %d" "" TRANSLATE "Global variable `%s' makes expression non-constant" "" TRANSLATE "In" "" @@ -24841,6 +24842,7 @@ TRANSLATE "System variable `$%s' makes expression non-constant" "" TRANSLATE "Undefined %s function: `%s'" "" TRANSLATE "Unmatched PUSH-OMIT-CONTEXT at %s(%d)" "" TRANSLATE "Unrecognized command; interpreting as REM" "" +TRANSLATE "User function `%s' defined in non-constant context makes expression non-constant" "" TRANSLATE "Variable assignment considered non-constant because of context" "" TRANSLATE "Warning: Function name `%s...' truncated to `%s'" "" TRANSLATE "Warning: OMIT is ignored if you use OMITFUNC" "" diff --git a/tests/test.rem b/tests/test.rem index b67ba6cd..9a690681 100644 --- a/tests/test.rem +++ b/tests/test.rem @@ -1532,6 +1532,32 @@ REM SCANFROM -7 MSG foo REM MSG [g(3)] +# Check user-functions for constant-ness +FUNSET f +IF today() > '1990-01-01' + FSET f(x) 2 +ELSE + FSET f(x) 3 +ENDIF + +SET a f(1) + +FUNSET f +FSET f(x) '1990-01-01' +IF today() < '1990-01-01' + FSET f(x) '2025-12-31' +ENDIF + +set a f(1) +FUNSET F + +SET a 1 +IF today() < '1990-01-01' + SET a 2 +ENDIF + +dump -c a + DEBUG -n DEBUG -e