changeset 115:1d1f29d0954d

eval: Fix in-place evaluation of lists and strings
author Lewin Bormann <lbo@spheniscida.de>
date Thu, 29 Aug 2019 22:48:22 +0200
parents 4107207b761d
children 3267a9631763
files src/eval.c
diffstat 1 files changed, 10 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c	Thu Aug 29 22:48:04 2019 +0200
+++ b/src/eval.c	Thu Aug 29 22:48:22 2019 +0200
@@ -4,8 +4,6 @@
 #include <src/expr.h>
 #include <src/value.h>
 
-static void nothing(void){/* labels need to be followed by statement */};
-
 yexpr_t yeval_call_func(yvalue_t* ref, yexpr_t* call) { return yexpr_new(); }
 
 yexpr_t yeval_list_return_last(yeval_state_t* state, yvec_t* list, size_t off) {
@@ -23,19 +21,22 @@
     switch (expr->typ) {
         case YEXPR_ATOM:
         case YEXPR_NUMBER:
-        case YEXPR_STRING:
         case YEXPR_EXCEPTION:
         case YEXPR_BUILTIN:
             if (in_place) break;  // values can't have side effects
             // Flat copy is enough.
             return *expr;
+        case YEXPR_STRING:
+            if (in_place) break;
+            result = *expr;
+            result.value.str = ystr_new(ystr_str(&expr->value.str));
+            return result;
         case YEXPR_REF:
             // Reference is resolved if expr-ref. func-refs are not resolved.
             // NOTE: Can this result in infinite recursion?
-            nothing();
+            if (in_place) break;  // values can't have side effects
             yvalue_t* val = yvalue_get(expr->value.ref);
             if (val->typ == YVALUE_EXPR) {
-                if (in_place) break;  // values can't have side effects
                 result = yexpr_copy(&val->value.expr);
                 return result;
             } else if (val->typ == YVALUE_FUNC) {
@@ -78,6 +79,8 @@
                 }
             }
 
+            result = *expr;
+
             // Don't store results
             if (in_place) {
                 for (size_t i = 0; i < result.value.list.len; i++) {
@@ -89,7 +92,8 @@
                 return result;
             }
 
-            result = *expr;
+            // Store results; input list is copied shallowly, and assigned with
+            // copied values from yeval.
             result.value.list = yvec_clone(&expr->value.list);
             for (size_t i = 0; i < result.value.list.len; i++) {
                 yexpr_t* elem = YVEC_AT(&result.value.list, i, yexpr_t);