#include "rlang.h"


r_obj* r_new_pairlist(const struct r_pair* args,
                      int n,
                      r_obj** tail) {
  r_obj* shelter = KEEP(r_new_node(R_NilValue, R_NilValue));
  r_obj* node = shelter;

  for (int i = 0; i < n; ++i) {
    struct r_pair arg = args[i];
    r_obj* tag = arg.x;
    r_obj* car = arg.y;

    r_obj* cdr = r_new_node(car, r_null);
    r_node_poke_tag(cdr, tag);

    r_node_poke_cdr(node, cdr);
    node = cdr;
  }

  if (n && tail) {
    *tail = node;
  }

  FREE(1);
  return r_node_cdr(shelter);
}


// Shallow copy of a node tree. Other objects are not cloned.
r_obj* r_node_tree_clone(r_obj* x) {
  enum r_type type = r_typeof(x);
  if (type != R_TYPE_pairlist && type != R_TYPE_call) {
    return x;
  }

  x = KEEP(r_clone(x));

  r_obj* rest = x;
  while (rest != r_null) {
    r_obj* head = r_node_car(rest);
    enum r_type head_type = r_typeof(head);

    if (head_type == R_TYPE_pairlist || head_type == R_TYPE_call) {
      r_node_poke_car(rest, r_node_tree_clone(head));
    }
    rest = r_node_cdr(rest);
  }

  FREE(1);
  return x;
}

r_obj* r_pairlist_rev(r_obj* node) {
  if (node == r_null) {
    return node;
  }

  r_obj* prev = r_null;
  r_obj* tail = node;
  r_obj* next;
  while (tail != r_null) {
    next = r_node_cdr(tail);
    r_node_poke_cdr(tail, prev);
    prev = tail;
    tail = next;
  }

  return prev;
}
