Commit f560c7e974457dcb19faa8d97d9a9840556851f5

Thomas de Grivel 2023-03-11T23:23:18

wip

diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index ecbe2ba..9605cf9 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -207,6 +207,7 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, s_tag *left,
   sw r;
   sw result = 0;
   s_tag *right;
+  s_tag *right_left;
   s_buf_save save;
   assert(buf);
   assert(dest);
@@ -217,21 +218,23 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, s_tag *left,
          >= min_precedence) {
     result += r;
     op = next_op;
-    if ((r = buf_parse_tag_primary(buf, &right)) <= 0)
+    if ((r = buf_parse_tag_primary(buf, right)) <= 0)
       goto restore;
     result += r;
     if ((r = buf_parse_ident(buf, &next_op)) < 0)
       goto restore;
     result += r;
-    while (r && (next_op_precedence = operator_precedence(&next_op))
-           >= op_precedence ||
-           (operator_is_right_associative(&next_op) &&
-            next_op_precedence == op_precedence)) {
+    while (r && ((next_op_precedence = operator_precedence(&next_op))
+                 >= op_precedence ||
+                 (operator_is_right_associative(&next_op) &&
+                  next_op_precedence == op_precedence))) {
       result += r;
       if (next_op_precedence > op_precedence)
         op_precedence++;
-      if ((r = buf_parse_call_op_rec(buf, (right = tag_new()), right,
-                                     op_precedence)) <= 0)
+      right_left = right;
+      right = tag_new();
+      if ((r = buf_parse_call_op_rec(buf, &right->data.call,
+                                     right_left, op_precedence)) <= 0)
         goto restore;
       result += r;
       if ((r = buf_parse_ident(buf, &next_op)) < 0)
@@ -239,6 +242,7 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, s_tag *left,
       left = tag_new_call_op(&op, left, right);
     }
   }
+  *dest = left->data.call;
   r = result;
   goto clean;
  restore:
@@ -1498,7 +1502,7 @@ sw buf_parse_tag (s_buf *buf, s_tag *dest)
       goto restore;
     result += r;
   }
-  if ((r = buf_parse_call_op(buf, dest)) != 0 ||
+  if ((r = buf_parse_tag_call_op(buf, dest)) != 0 ||
       (r = buf_parse_tag_primary(buf, dest)) != 0)
     goto end;
  end:
@@ -1534,6 +1538,14 @@ sw buf_parse_tag_call (s_buf *buf, s_tag *dest)
   return r;
 }
 
+sw buf_parse_tag_call_op (s_buf *buf, s_tag *dest)
+{
+  sw r;
+  if ((r = buf_parse_call_op(buf, &dest->data.call)) > 0)
+    dest->type.type = TAG_CALL;
+  return r;
+}
+
 sw buf_parse_tag_cfn (s_buf *buf, s_tag *dest)
 {
   sw r;
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index 8f2db29..fc37050 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -69,6 +69,7 @@ sw buf_parse_sym (s_buf *buf, const s_sym **dest);
 sw buf_parse_tag (s_buf *buf, s_tag *dest);
 sw buf_parse_tag_bool (s_buf *buf, s_tag *dest);
 sw buf_parse_tag_call (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_call_op (s_buf *buf, s_tag *dest);
 sw buf_parse_tag_cfn (s_buf *buf, s_tag *dest);
 sw buf_parse_tag_character (s_buf *buf, s_tag *dest);
 sw buf_parse_tag_fn (s_buf *buf, s_tag *dest);
diff --git a/libc3/env.c b/libc3/env.c
index e460488..efbd14a 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -486,7 +486,7 @@ s_module * env_module_load (s_env *env, s_module *module,
   return module;
 }
 
-bool env_operator_is_right_associative (const s_env *env, const s_ident *op)
+bool env_operator_is_right_associative (const s_env *env, s_ident *op)
 {
   s_facts_with_cursor cursor;
   s_tag tag_ident;
@@ -504,14 +504,11 @@ bool env_operator_is_right_associative (const s_env *env, const s_ident *op)
       NULL, NULL });
   if (! facts_with_cursor_next(&cursor))
     return false;
-  if (tag_var.type.type != TAG_U8)
-    errx(1, "%s.%s: invalid operator_precedence type",
-         op->module_name->str.ptr.ps8,
-         op->sym->str.ptr.ps8);
-  return tag_var.data.u8;
+  facts_with_cursor_clean(&cursor);
+  return true;
 }
 
-s8 env_operator_precedence (const s_env *env, const s_ident *op)
+s8 env_operator_precedence (const s_env *env, s_ident *op)
 {
   s_facts_with_cursor cursor;
   s_tag tag_ident;
@@ -535,6 +532,7 @@ s8 env_operator_precedence (const s_env *env, const s_ident *op)
     errx(1, "%s.%s: invalid operator_precedence type",
          op->module_name->str.ptr.ps8,
          op->sym->str.ptr.ps8);
+  facts_with_cursor_clean(&cursor);
   return tag_var.data.u8;
 }
 
diff --git a/libc3/env.h b/libc3/env.h
index 48b57b4..43ce7ef 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -45,8 +45,10 @@ bool       env_eval_progn (s_env *env, const s_list *program,
 bool       env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest);
 s_module * env_module_load (s_env *env, s_module *module,
                             const s_sym *name, s_facts *facts);
+bool       env_operator_is_right_associative (const s_env *env,
+                                              s_ident *op);
 s8         env_operator_precedence (const s_env *env,
-                                    const s_ident *op);
+                                    s_ident *op);
 
 /* control structures */
 void env_error_f (s_env *env, const char *fmt, ...);
diff --git a/libc3/operator.c b/libc3/operator.c
index 4041419..739f6cb 100644
--- a/libc3/operator.c
+++ b/libc3/operator.c
@@ -12,14 +12,14 @@
  * THIS SOFTWARE.
  */
 #include <assert.h>
-#include "types.h"
+#include "c3.h"
 
-bool operator_is_right_associative (const s_ident *op)
+bool operator_is_right_associative (s_ident *op)
 {
   return env_operator_is_right_associative(&g_c3_env, op);
 }
 
-s8 operator_precedence (const s_ident *op)
+s8 operator_precedence (s_ident *op)
 {
   return env_operator_precedence(&g_c3_env, op);
 }
diff --git a/libc3/operator.h b/libc3/operator.h
index afe3ae7..8167efd 100644
--- a/libc3/operator.h
+++ b/libc3/operator.h
@@ -17,7 +17,7 @@
 #include "types.h"
 
 /* Observers */
-bool operator_is_right_associative (const s_ident *op);
-s8   operator_precedence (const s_ident *op);
+bool operator_is_right_associative (s_ident *op);
+s8   operator_precedence (s_ident *op);
 
 #endif /* OPERATOR_H */