changeset 148:1620bde57dcb

expr: Implement yexpr_equal
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 03 Sep 2019 12:16:44 +0200
parents 1e9d534b903d
children df0e17d18c80
files src/expr.c src/expr.h
diffstat 2 files changed, 42 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/expr.c	Tue Sep 03 12:16:23 2019 +0200
+++ b/src/expr.c	Tue Sep 03 12:16:44 2019 +0200
@@ -76,12 +76,14 @@
             break;
         case YEXPR_LIST:
             // Recursively copy list...
-            yvec_init(&copy.value.list, orig->value.list.size, orig->value.list.len);
+            yvec_init(&copy.value.list, orig->value.list.size,
+                      orig->value.list.len);
             yvec_resize(&copy.value.list, orig->value.list.len);
 #define _list (&orig->value.list)
 #define _newlist (&copy.value.list)
             for (size_t i = 0; i < _list->len; i++)
-                *YVEC_AT(_newlist, i, yexpr_t) = yexpr_copy(YVEC_AT(_list, i, yexpr_t));
+                *YVEC_AT(_newlist, i, yexpr_t) =
+                    yexpr_copy(YVEC_AT(_list, i, yexpr_t));
 #undef _list
 #undef _newlist
             break;
@@ -152,6 +154,39 @@
     YVEC_PUSH(&v->value.list, &new_val);
 }
 
+bool yexpr_equal(yexpr_t* a, yexpr_t* b) {
+    if (a->typ != b->typ) return false;
+    switch (a->typ) {
+        case YEXPR_UNDEF:
+            return true;
+        case YEXPR_ATOM:
+            return a->value.atom == b->value.atom;
+        case YEXPR_BUILTIN:
+            return a->value.builtin == b->value.builtin;
+        case YEXPR_NUMBER:
+            return a->value.n == b->value.n;
+        case YEXPR_STRING:
+        case YEXPR_EXCEPTION:
+            return 0 == ystr_cmp(&a->value.str, &b->value.str);
+        case YEXPR_REF:
+            if (yref_eq(&a->value.ref, &b->value.ref)) return true;
+            yvalue_t* aexpr = yvalue_get(a->value.ref);
+            yvalue_t* bexpr = yvalue_get(b->value.ref);
+            if (aexpr->typ != bexpr->typ) return false;
+            return yexpr_equal(&aexpr->value.expr, &bexpr->value.expr);
+        case YEXPR_LIST:
+            if (a->value.list.len != b->value.list.len) return false;
+            for (size_t i = 0; i < a->value.list.len; i++) {
+                if (!yexpr_equal(YVEC_AT(&a->value.list, i, yexpr_t),
+                                 YVEC_AT(&b->value.list, i, yexpr_t)))
+                    return false;
+            }
+            return true;
+        default:
+            assert(false /* missing expression type! */);
+    }
+}
+
 void yexpr_init_or_extend(yexpr_t* expr, yexpr_t arg) {
     if (expr->typ == YEXPR_UNDEF) {
         yexpr_append_value(expr, arg);
--- a/src/expr.h	Tue Sep 03 12:16:23 2019 +0200
+++ b/src/expr.h	Tue Sep 03 12:16:44 2019 +0200
@@ -88,6 +88,11 @@
  */
 void yexpr_append_value(yexpr_t* v, yexpr_t new_val);
 
+/**
+ * Check if two expressions are equal.
+ */
+bool yexpr_equal(yexpr_t* a, yexpr_t* b);
+
 /****** helpers for parsing ******/
 
 /**