Exemplo n.º 1
0
Arquivo: eval.c Projeto: merolle/ripe
static const char* eval_static_call(const char* ssym, Node* arg_list)
{
  FuncInfo* fi = stran_get_function(ssym);
  if (fi == NULL){
    fatal_node(arg_list, "unknown static call to '%s'", ssym);
  }

  int num_args = node_num_children(arg_list);
  int min_params = num_args;
  int num_params = fi->num_params;
  bool is_vararg = false;

  // Check if vararg
  if (num_params > 0 and strequal("*", fi->param_types[num_params-1])){
    is_vararg = true;
    min_params = num_params - 1;
    if (num_args < min_params)
      fatal_node(arg_list, "'%s' called with %d arguments but expect at least %d",
               ssym, num_args, min_params);
  } else {
    if (num_params != num_args)
      fatal_node(arg_list, "'%s' called with %d arguments but expect %d", ssym,
               num_args, num_params);
  }

  cache_prototype(ssym); // Make certain the C compiler knows fi->c_name
  const char* buf = mem_asprintf("%s(", fi->c_name);
  for (int i = 0; i < min_params; i++){
    Node* arg = node_get_child(arg_list, i);
    if (i == 0)
      buf = mem_asprintf("%s%s", buf, eval_Value(arg));
    else
      buf = mem_asprintf("%s, %s", buf, eval_Value(arg));
  }
  if (is_vararg){
    if (min_params == 0)
      buf = mem_asprintf("%stuple_to_val(%d", buf, num_args - min_params);
    else
      buf = mem_asprintf("%s, tuple_to_val(%d", buf, num_args - min_params);

    for (int i = min_params; i < num_args; i++){
      Node* arg = node_get_child(arg_list, i);
      buf = mem_asprintf("%s, %s", buf, eval_Value(arg));
    }
    buf = mem_asprintf("%s)", buf);
  }
  buf = mem_asprintf("%s)", buf);

  return buf;
}
Exemplo n.º 2
0
void* bintree_contains(bintree* b, void* data)
{
	if (!b->root)
		return 0;
	bintree_node* n = node_get_child(b->root,data,b->comp);
	return (n ? n->data : 0);
}
Exemplo n.º 3
0
void node_extend_children(Node* new_parent, Node* old_parent)
{
  for (int i = 0; i < node_num_children(old_parent); i++){
    Node* child = node_get_child(old_parent, i);
    node_add_child(new_parent, child);
  }
}
Exemplo n.º 4
0
bintree_node* node_get_child(bintree_node* n, void* data, compfunc comp)
{
	printf("node_get_child: %s,%s,%x\n",
		(char*)n->data,(char*)data,(uint)(llong)comp);
	
	int r = comp(data,n->data);
	if (r < 0)
	{
		if (!n->left) return 0;
		return node_get_child(n->left,data,comp);
	}
	else if (r > 0)
	{
		if (!n->right) return 0;
		return node_get_child(n->right,data,comp);
	}
	return n;
}
Exemplo n.º 5
0
void
node_create_children_snapshot(node_t *f, gint created_event, gboolean emit)
{
	GDir *dir;
	GError *err = NULL;
    
    FN_W ("%s %s [0x%p]\n", __func__, NODE_NAME(f), f);

    dir = g_dir_open (NODE_NAME(f), 0, &err);
    if (dir) {
        const char *basename;
        node_t *child = NULL;
        
        while ((basename = g_dir_read_name (dir))) {
            node_t* data;
            GList *idx;

            child = node_get_child (f, basename);
            if (child == NULL) {
                gchar *filename;
            
                child = node_new (f, basename);
                children_add (f, child);
            }

            if (f->dir_subs) {
                /* We need monitor the new children, or the existed child which
                 * is in the DELETED mode.
                 */
                if (!NODE_HAS_STATE(child, NODE_STATE_ASSOCIATED) &&
                  node_lstat(child) == 0 && port_add(child) == 0) {
                    if (emit) {
                        /* Emit the whatever event for the new found file. */
                        node_emit_one_event(child, child->dir_subs, NULL, created_event);
                        node_emit_one_event(child, child->subs, NULL, created_event);
                        node_emit_one_event(child, f->dir_subs, NULL, created_event);
                        node_emit_one_event(child, f->subs, NULL, created_event);
                    }
                }
                /* else ignore, because it may be deleted. */
            }
        }
        g_dir_close (dir);

        /* We have finished children snapshot. Any other new added subs should
         * directory iterate the snapshot instead of scan directory again.
         */
        NODE_SET_FLAG(f, NODE_FLAG_SNAPSHOT_UPDATED);

    } else {
        FN_W (err->message);
        g_error_free (err);
    }
}
Exemplo n.º 6
0
Arquivo: eval.c Projeto: merolle/ripe
static const char* eval_expr_list(Node* expr_list, bool first_comma)
{
  assert(expr_list->type == EXPR_LIST);
  StringBuf sb_temp;
  sbuf_init(&sb_temp, "");
  for (uint i = 0; i < expr_list->children.size; i++){
    if (i == 0 and not first_comma){
      sbuf_printf(&sb_temp, 
                  "%s", 
                  eval_Value(node_get_child(expr_list, i)));
    } else {
      sbuf_printf(&sb_temp,
                  ", %s",
                  eval_Value(node_get_child(expr_list, i)));
    }
  }
  const char* result = mem_strdup(sb_temp.str);
  sbuf_deinit(&sb_temp);
  return result;
}
Exemplo n.º 7
0
Arquivo: eval.c Projeto: merolle/ripe
// Returns code for accessing index (if assign = NULL), or setting index
// when assign is of type expr.
const char* eval_index(Node* self, Node* idx, Node* assign)
{
  if (assign == NULL) {
    return eval_obj_call(self, "index", idx);
  } else {
    Node* arg_list = node_new(EXPR_LIST);
    for (int i = 0; i < node_num_children(idx); i++){
      node_add_child(arg_list, node_get_child(idx, i));
    }
    node_add_child(arg_list, assign);
    return eval_obj_call(self, "index_set", arg_list);
  }
}
Exemplo n.º 8
0
Arquivo: btree.c Projeto: shiva/fun
void btree_node_insert(node_t node, node_t newnode)
{
	node_t child = NULL;
	node_orientation_t orientation;

	orientation = (newnode->data < node->data) ? NODE_LEFT : NODE_RIGHT;
	child = node_get_child(node, orientation);
	if (child) {
		return btree_node_insert(child, newnode);
	} else {  // reached leaf, add newnode
		return node_add_child(node, orientation, newnode);
	}
}
Exemplo n.º 9
0
static void node_draw_r(Node* ast, int level)
{
  for (int i = 0; i < level; i++){
    printf("  ");
  }
  if (ast->text != NULL){
    printf("Type: %4d '%s'\n", ast->type, ast->text);
  } else {
    printf("Type: %4d\n", ast->type);
  }
  for (int i = 0; i < node_num_children(ast); i++)
  {
    node_draw_r(node_get_child(ast, i), level+1);
  }
}
Exemplo n.º 10
0
node_t*
node_find(node_t* node, const gchar* filename, gboolean create_on_missing)
{
    gchar* str;
    gchar* token;
    gchar* lasts;
    node_t* parent;
    node_t* child;
    
    g_assert (filename && filename[0] == '/');

    if (node == NULL) {
        node = ROOT;
    }
    
    FN_W ("%s %s\n", __func__, filename);

    parent = child = node;
    str = g_strdup (filename);
    
    for (token = strtok_r (str, G_DIR_SEPARATOR_S, &lasts);
         token != NULL && child != NULL;
         token = strtok_r (NULL, G_DIR_SEPARATOR_S, &lasts)) {
        FN_W ("%s %s + %s\n", __func__, NODE_NAME(parent), token);
        child = node_get_child(parent, token);
        if (child) {
            parent = child;
        } else if (create_on_missing) {
            child = node_new (parent, token);
            if (child) {
                children_add (parent, child);
                parent = child;
                continue;
            } else {
                FN_W ("%s create %s failed", __func__, token);
            }
        } else {
            break;
        }
    }
    
    g_free (str);
    return child;
}
Exemplo n.º 11
0
Arquivo: eval.c Projeto: merolle/ripe
// Attempt to evaluate the expression as an identifier with dots, otherwise
// return NULL.
// I.e. Std.println would evaluate and return "Std.println", but (1+1).to_s
// would not.
static const char* eval_expr_as_id(Node* expr)
{
  switch(expr->type){
    case ID:
      if (var_query(expr->text)) return NULL;
      return expr->text;
    case EXPR_FIELD:
      {
        Node* parent = node_get_child(expr, 0);
        const char* field = node_get_string(expr, "name");
        const char* s = eval_expr_as_id(parent);
        if (s != NULL) return mem_asprintf("%s.%s", s, field);
        else return NULL;
      }
    default:
      // Anything other than ID or EXPR_FIELD means that it cannot be a
      // static symbol.
      return NULL;
  }
}
Exemplo n.º 12
0
Arquivo: eval.c Projeto: merolle/ripe
EE* eval_expr(Node* expr)
{
  if (is_unary_op(expr))
    return ee_new(UNTYPED, 
                  mem_asprintf("%s(%s)",
                               unary_op_map(expr->type),
                               eval_Value(node_get_child(expr, 0))));
  if (is_binary_op(expr))
    return ee_new (UNTYPED, 
                   mem_asprintf("%s(%s, %s)",
                                binary_op_map(expr->type),
                                eval_Value(node_get_child(expr, 0)),
                                eval_Value(node_get_child(expr, 1))));

  switch(expr->type){
  case K_TRUE:
    return ee_new("Bool", "VALUE_TRUE");
  case K_FALSE:
    return ee_new("Bool", "VALUE_FALSE");
  case K_NIL:
    return ee_new("Nil", "VALUE_NIL");
  case K_EOF:
    return ee_new("Eof", "VALUE_EOF");
  case ID:
    if (context_block != NULL){
      // If it's a block param, then OK.
      if (var_query_kind(expr->text) == VAR_BLOCK_PARAM)
        return ee_new(var_query_type(expr->text), var_query_c_name(expr->text));
      else 
        return ee_new(var_query_type(expr->text),
                      closure_add(expr->text, var_query_c_name(expr->text)));
    } else return ee_new(var_query_type(expr->text), var_query_c_name(expr->text));
  case SYMBOL:
    return ee_new("Integer", cache_dsym(expr->text + 1));
  case INT:
    return ee_new("Integer", mem_asprintf("int64_to_val(%s)", expr->text));
  case DOUBLE:
    return ee_new("Double", mem_asprintf("double_to_val(%s)", expr->text));
  case STRING:
    {
      const char* str = expr->text;
      return ee_new("String", mem_asprintf("string_to_val(\"%s\")", str));
    }
    break;
  case CHARACTER:
    {
      const char* str = expr->text;
      return ee_new("Integer", mem_asprintf("int64_to_val(%d)", (int) str[1]));
    }
    break;
  case EXPR_ARRAY:
    {
      Node* expr_list = node_get_child(expr, 0);
      return ee_new("Array", mem_asprintf("array1_to_val2(%u %s)",
                                          expr_list->children.size,
                                          eval_expr_list(expr_list, true)));
    }
  case EXPR_MAP:
    {
      Node* m_list = node_get_child(expr, 0);
      bool is_map = false, is_set = false;
      const char* args = "";

      const int num_ms = node_num_children(m_list);
      assert(num_ms > 0);
      for (int i = 0; i < num_ms; i++){
        Node* m = node_get_child(m_list, i);
        switch (node_num_children(m)){
          case 2:
            is_map = true;
            args = mem_asprintf("%s, %s, %s", args,
                                eval_Value(node_get_child(m, 0)),
                                eval_Value(node_get_child(m, 1)));
            break;
          case 1:
            is_set = true;
            args = mem_asprintf("%s, %s", args,
                                eval_Value(node_get_child(m, 0)));
            break;
          default:
            assert_never();
            break;
        }
      }

      if (is_map and is_set){
        fatal_node(expr, "invalid curly braces: is this a set or a map?");
      }
      if (is_map) return ee_new("Map",
                                mem_asprintf("ht_new_map(%d%s)", num_ms, args));
      if (is_set) return ee_new("Set", 
                                mem_asprintf("ht_new_set(%d%s)", num_ms, args));
      assert_never();
    }
    break;
  case EXPR_INDEX:
    return ee_new(UNTYPED, 
                  eval_index(node_get_child(expr, 0), node_get_child(expr, 1), NULL));
  case EXPR_CALL:
    {
      Node* callee = node_get_node(expr, "callee");
      Node* args = node_get_node(expr, "args");
      
      // If callee is a field, then we must check if its a method call.
      if (callee->type == EXPR_FIELD){
        const char* field_name = node_get_string(callee, "name");
        Node* left = node_get_child(callee, 0);
        
        const char* s = eval_expr_as_id(left);
        if (s == NULL or var_query(s))
          return ee_new(UNTYPED, eval_obj_call(left, field_name, args));
      }
      
      const char* s = eval_expr_as_id(callee);
      if (s != NULL){
        // Could be a tuple constructor.
        if (strequal(s, "tuple")){
          return ee_new("Tuple", mem_asprintf("tuple_to_val(%u %s)",
                                              node_num_children(args),
                                              eval_expr_list(args, true)));
        }

        // If all of callee can be evaluated as an id, then it must be a static
        // call.
        return ee_new(UNTYPED, eval_static_call(s, args));
      }
      

      return ee_new(UNTYPED, mem_asprintf("func_call%d(%s %s)", 
                                          node_num_children(args),
                                          eval_Value(callee),
                                          eval_expr_list(args, true)));
    }
  case EXPR_RANGE_BOUNDED:
    {
      Node* left = node_get_child(expr, 0);
      Node* right = node_get_child(expr, 1);
      return ee_new("Range",
                    mem_asprintf("range_to_val(RANGE_BOUNDED, "
                                 "val_to_int64(%s), val_to_int64(%s))",
                                 eval_Value(left),
                                 eval_Value(right)));
    }
  case EXPR_RANGE_BOUNDED_LEFT:
    return ee_new("Range", 
                  mem_asprintf("range_to_val(RANGE_BOUNDED_LEFT, "
                               "val_to_int64(%s), 0)",
                               eval_Value(node_get_child(expr, 0))));
  case EXPR_RANGE_BOUNDED_RIGHT:
    return ee_new("Range",
                  mem_asprintf("range_to_val(RANGE_BOUNDED_RIGHT, "
                               "0, val_to_int64(%s))",
                               eval_Value(node_get_child(expr, 0))));
  case EXPR_RANGE_UNBOUNDED:
    return ee_new("Range", "range_to_val(RANGE_UNBOUNDED, 0, 0)");
  case EXPR_FIELD:
    {
      // Attempt to evaluate this field as a static symbol.
      Node* left = node_get_child(expr, 0);
      const char* s = eval_expr_as_id(left);
      if (s == NULL or var_query(s)){
        // Dynamic field.
        const char* field = node_get_string(expr, "name");

        return ee_new(UNTYPED, 
                      mem_asprintf("field_get(%s, %s)",
                                   eval_Value(left),
                                   cache_dsym(field)));
      } else {
        // Could be a global variable.
        s = eval_expr_as_id(expr);

        if (context_block != NULL){
          return ee_new(var_query_type(s), closure_add(s, var_query_c_name(s)));
        } else return ee_new(var_query_type(s), var_query_c_name(s));
      }
    }
    break;
  case EXPR_AT_VAR:
    {
      const char* name = node_get_string(expr, "name");
      if (context_ci == NULL){
        fatal_node(expr, "'@%s' in something that's not a class", name);
      }
      if (context_ci->type != CLASS_FIELD){
        fatal_node(expr, "'@%s' in a class that's not a field class", name);
      }
      return ee_new(UNTYPED,
                    mem_asprintf("field_get(__self, %s)", cache_dsym(name)));
    }
  case C_CODE:
    {
      const char* str = util_trim_ends(expr->text);
      if (strstr(expr->text, "return")){
        fatal_warn("careless return in C code may disrupt the stack (use RRETURN)");
      }

      if (context_fi != NULL){
        if (context_fi->type == METHOD
             or context_fi->type == CONSTRUCTOR
             or context_fi->type == VIRTUAL_GET
             or context_fi->type == VIRTUAL_SET){
          if (strchr(str, '@') != NULL and context_ci->type != CLASS_CDATA)
            fatal_node(expr, "@ in C code in a class that is not cdata");
          str = util_replace(str, '@', "_c_data->");
        }
      }

      return ee_new(UNTYPED, str);
    }
  case EXPR_IS_TYPE:
    {
      const char* type = eval_type(node_get_child(expr, 1));
      if (var_query(type)){
        fatal_node(expr, "type '%s' in 'is' expression is a variable", type);
      }
      return ee_new("Bool", 
                    mem_asprintf("pack_bool(obj_klass(%s) == %s)",
                    eval_Value(node_get_child(expr, 0)),
                    cache_type(type)));
    }
  case EXPR_BLOCK:
    {
      fatal_push("in anonymous block");
      if (context_block != NULL){
        fatal_node(expr, "nested blocks are not implemented yet");
      }

      // Initialize context_block  
      context_block = mem_new(BlockContext);
      sbuf_init(&(context_block->sbuf_code), "");
      sarray_init(&(context_block->closure_names));
      sarray_init(&(context_block->closure_exprs));
      static int counter = 0; counter++;
      context_block->func_name = mem_asprintf("ripe_blk%d", counter);

      Node* param_list = node_get_node(expr, "param_list");
      Node* stmt_list = node_get_node(expr, "stmt_list");
      var_push();

      // Print out the header of the anonymous function
      sbuf_printf(&(context_block->sbuf_code), "static Value %s(Value __block",
                  context_block->func_name);
      for (int i = 0; i < node_num_children(param_list); i++){
        Node* param = node_get_child(param_list, i);
        const char* name = node_get_string(param, "name");
        const char* c_name = util_c_name(name);
        if (node_has_string(param, "array"))
          fatal_node(expr,
                     "array parameters for blocks are not implemented yet");
        const char* type = "?"; // TODO: Deal with type.
        var_add_local2(name, c_name, type, VAR_BLOCK_PARAM);
        sbuf_printf(&(context_block->sbuf_code), ", Value %s", c_name);
      }
      sbuf_printf(&(context_block->sbuf_code), ")\n");
      
      // Generate block code
      sbuf_printf(&(context_block->sbuf_code), "{\n");
      sbuf_printf(&(context_block->sbuf_code), 
                  "  Func* _c_data = obj_c_data(__block);\n");

      sbuf_printf(&(context_block->sbuf_code), 
                  "  stack_annot_push(\"anonymous function\");\n");
      sbuf_printf(&(context_block->sbuf_code), "%s", gen_block(stmt_list));
      sbuf_printf(&(context_block->sbuf_code), "}\n");

      // Now, print out the block function to WR_HEADER
      wr_print(WR_HEADER, "%s", context_block->sbuf_code.str);
      const char* result = mem_asprintf("block_to_val(%s, %d, %d",
                                        context_block->func_name,
                                        node_num_children(param_list),
                                        context_block->closure_names.size);
      for (uint i = 0; i < context_block->closure_names.size; i++){
        const char* evaluated = sarray_get_ptr(&(context_block->closure_exprs),
                                               i);
        result = mem_asprintf("%s, %s", result, evaluated);
      }
      result = mem_asprintf("%s)", result);

      // End EXPR_BLOCK
      var_pop();
      context_block = NULL;
      fatal_pop();
      return ee_new("Function", result);
    }
  default:
    assert_never();
  }
  return NULL;
}