Commit 81ca20f6ac91f5dcaef0718348f9d1e75d3d1cb0

Thomas de Grivel 2023-03-13T08:04:33

wip buf_parse_call_op

diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index b9393fe..015f502 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -204,36 +204,39 @@ sw buf_parse_call_op (s_buf *buf, s_call *dest)
 
 sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, u8 min_precedence)
 {
-  s_tag *new_left = NULL;
+  s_tag *left;
   s_ident next_op;
   s8 next_op_precedence;
   s_ident op;
   s8 op_precedence;
   sw r;
   sw result = 0;
-  s_tag *right = NULL;
-  s_tag *right_first = NULL;
-  s_tag *right_left = NULL;
+  s_tag *right;
   s_buf_save save;
   s_call tmp;
+  s_call tmp2;
   assert(buf);
   assert(dest);
   buf_save_init(buf, &save);
-  if ((r = buf_parse_ident(buf, &next_op)) <= 0)
+  tmp = *dest;
+  left = &tmp.arguments->tag;
+  right = &list_next(tmp.arguments)->tag;
+  if ((r = buf_parse_ident_peek(buf, &next_op)) <= 0)
     goto clean;
   while (r && (op_precedence = operator_precedence(&next_op))
          >= min_precedence) {
+    if ((r = buf_parse_ident(buf, &next_op)) <= 0)
+      goto clean;
     result += r;
+    op = next_op;
     if ((r = buf_ignore_spaces(buf)) < 0)
       goto restore;
-    op = next_op;
-    right = tag_new();
     if ((r = buf_parse_tag_primary(buf, right)) <= 0)
       goto restore;
     result += r;
     if ((r = buf_ignore_spaces(buf)) < 0)
       goto restore;
-    if ((r = buf_parse_ident(buf, &next_op)) < 0)
+    if ((r = buf_parse_ident_peek(buf, &next_op)) < 0)
       goto restore;
     result += r;
     while (r && ((next_op_precedence = operator_precedence(&next_op))
@@ -241,25 +244,22 @@ sw buf_parse_call_op_rec (s_buf *buf, s_call *dest, u8 min_precedence)
                  (operator_is_right_associative(&next_op) &&
                   next_op_precedence == op_precedence))) {
       result += r;
-      if (next_op_precedence > op_precedence)
-        op_precedence++;
-      right_left = right;
-      right = tag_new();
-      if ((r = buf_parse_call_op_rec(buf, &right->data.call,
-                                     op_precedence)) <= 0)
+      call_init_op(&tmp2);
+      tmp2.arguments->tag = *right;
+      if ((r = buf_parse_call_op_rec(buf, &tmp2, (next_op_precedence > op_precedence) ? op_precedence + 1 : op_precedence)) <= 0)
         goto restore;
-      free(right_left);
+      tag_init_call(right, &tmp2);
       result += r;
       if ((r = buf_ignore_spaces(buf)) < 0)
         goto restore;
-      if ((r = buf_parse_ident(buf, &next_op)) < 0)
+      result += r;
+      if ((r = buf_parse_ident_peek(buf, &next_op)) < 0)
         goto restore;
-      new_left = tag_new_call_op(&op, left, right);
-      free(left);
-      left = new_left;
     }
+    tmp.ident = op;
+    tag_init_call(left, &tmp);
   }
-  *dest = left->data.call;
+  *dest = tmp;
   r = result;
   goto clean;
  restore:
@@ -872,6 +872,16 @@ sw buf_parse_ident (s_buf *buf, s_ident *dest)
   return r;
 }
 
+sw buf_parse_ident_peek (s_buf *buf, s_ident *dest)
+{
+  sw r;
+  s_buf_save save;
+  buf_save_init(buf, &save);
+  r = buf_parse_ident(buf, dest);
+  buf_save_restore_rpos(buf, &save);
+  return r;
+}
+
 sw buf_parse_integer (s_buf *buf, s_integer *dest)
 {
   sw r;
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index bdd6206..664eea9 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -56,6 +56,7 @@ sw buf_parse_integer_unsigned_dec (s_buf *buf, s_integer *dest);
 sw buf_parse_integer_unsigned_hex (s_buf *buf, s_integer *dest);
 sw buf_parse_integer_unsigned_oct (s_buf *buf, s_integer *dest);
 sw buf_parse_ident (s_buf *buf, s_ident *dest);
+sw buf_parse_ident_peek (s_buf *buf, s_ident *dest);
 sw buf_parse_integer (s_buf *buf, s_integer *dest);
 sw buf_parse_list (s_buf *buf, s_list **dest);
 sw buf_parse_module_name (s_buf *buf, const s_sym **dest);
diff --git a/libc3/call.c b/libc3/call.c
index c82e3bf..2632575 100644
--- a/libc3/call.c
+++ b/libc3/call.c
@@ -12,6 +12,7 @@
  * THIS SOFTWARE.
  */
 #include <assert.h>
+#include <string.h>
 #include "buf.h"
 #include "buf_inspect.h"
 #include "buf_parse.h"
@@ -45,10 +46,9 @@ s_call * call_init_1 (s_call *call, const s8 *p)
 
 s_call * call_init_op (s_call *call)
 {
-  s_list *args;
   assert(call);
   assert(op);
-  call->ident = NULL;
+  bzero(&call->ident, sizeof(s_ident));
   call->arguments = list_new(list_new(NULL));
   return call;
 }
diff --git a/libc3/tag.c b/libc3/tag.c
index aee39a8..57c8045 100644
--- a/libc3/tag.c
+++ b/libc3/tag.c
@@ -290,6 +290,16 @@ s_tag * tag_init_bool (s_tag *tag, bool b)
   return tag;
 }
 
+s_tag * tag_init_call (s_tag *tag, const s_call *call)
+{
+  assert(tag);
+  assert(call);
+  bzero(tag, sizeof(s_tag));
+  tag->type.type = TAG_CALL;
+  tag->data.call = *call;
+  return tag;
+}
+
 s_tag * tag_init_character (s_tag *tag, character c)
 {
   assert(tag);
diff --git a/libc3/tag.h b/libc3/tag.h
index 3be4811..ed23870 100644
--- a/libc3/tag.h
+++ b/libc3/tag.h
@@ -34,9 +34,8 @@ extern s_tag g_tag_last;
 /* Stack allocation compatible functions */
 s_tag * tag_init (s_tag *tag);
 s_tag * tag_init_1 (s_tag *tag, const s8 *p);
-s_tag * tag_init_str (s_tag *tag, s8 *free, uw size, const s8 *p);
-s_tag * tag_init_str_1 (s_tag *tag, s8 *free, const s8 *p);
 s_tag * tag_init_bool (s_tag *tag, bool p);
+s_tag * tag_init_call (s_tag *tag, const s_call *call);
 s_tag * tag_init_character (s_tag *tag, character c);
 s_tag * tag_init_f32 (s_tag *tag, f32 f);
 s_tag * tag_init_f64 (s_tag *tag, f64 f);
@@ -50,6 +49,8 @@ s_tag * tag_init_s8 (s_tag *tag, s8 i);
 s_tag * tag_init_s16 (s_tag *tag, s16 i);
 s_tag * tag_init_s32 (s_tag *tag, s32 i);
 s_tag * tag_init_s64 (s_tag *tag, s64 i);
+s_tag * tag_init_str (s_tag *tag, s8 *free, uw size, const s8 *p);
+s_tag * tag_init_str_1 (s_tag *tag, s8 *free, const s8 *p);
 s_tag * tag_init_sym (s_tag *tag, const s_sym *p);
 s_tag * tag_init_sym_1 (s_tag *tag, const s8 *p);
 s_tag * tag_init_tuple (s_tag *tag, uw count);