Example #1
0
/*
 * Return a single tuple containing the contents of the gen'ed tuple chain.
 */
void
gen_flatten(struct value *gen, struct value *dest)
{
    unsigned int dest_size = value_tuple_fetch_integer(gen, GEN_GLOBAL_POS);
    struct value *current = value_tuple_fetch(gen, GEN_ROOT_TUPLE);
    unsigned int j = 0;

    value_tuple_new(dest, value_tuple_get_tag(current), dest_size);

    while (!value_is_null(current)) {
        unsigned int i = 0;
        unsigned int current_size = value_tuple_get_size(current);
        struct value *x;
        for (i = 0; i < (current_size - 1) && i < dest_size; i++) {
            x = value_tuple_fetch(current, i);

#ifdef DEBUG
            process_render(process_err, "(flatten %d/%d -> %d/%d: ", i, current_size, j, dest_size);
            value_portray(process_err, x);
            process_render(process_err, ")\n");
#endif

            value_tuple_store(dest, j, x);
            j++;
        }
        current = value_tuple_fetch(current, (current_size - 1));
    }
}
Example #2
0
File: libs.c Project: clarkok/cript
static Value
_lib_typeof(VMState *vm, Value value)
{
    Hash *args = value_to_ptr(value);
    Value query_val = hash_find(args, 1);

    if (value_is_int(query_val)) {
        return cvm_get_cstring_value(vm, "integer");
    }
    else if (value_is_string(query_val)) {
        return cvm_get_cstring_value(vm, "string");
    }
    else if (value_is_null(query_val)) {
        return cvm_get_cstring_value(vm, "null");
    }
    else if (value_is_undefined(query_val)) {
        return cvm_get_cstring_value(vm, "undefined");
    }
    else {
        Hash *hash = value_to_ptr(query_val);
        while (hash->type == HT_REDIRECT) hash = (Hash*)hash->size;
        assert(hash->type != HT_GC_LEFT);

        switch (hash->type) {
            case HT_OBJECT:         return cvm_get_cstring_value(vm, "object");
            case HT_ARRAY:          return cvm_get_cstring_value(vm, "array");
            case HT_LIGHTFUNC:      return cvm_get_cstring_value(vm, "light_function");
            case HT_CLOSURE:        return cvm_get_cstring_value(vm, "closure");
            case HT_USERDATA:       return cvm_get_cstring_value(vm, "userdata");
            default: assert(0);     return value_undefined();
        }
    }
}
Example #3
0
/*
 * Define a label.  If the label is already allocated, this will
 * cause previously-generated forward references to this label to be
 * backpatched with the now-known location.
 */
int
gen_define_label(struct value *gen, struct value *gen_label)
{
    struct value *tuple = value_tuple_fetch(gen, GEN_CURRENT_TUPLE);
    unsigned int local_pos = value_tuple_fetch_integer(gen, GEN_LOCAL_POS);
    unsigned int global_pos = value_tuple_fetch_integer(gen, GEN_GLOBAL_POS);

    struct value *bp;

    assert(gen_label != NULL);

    if (value_is_null(gen_label)) {
        /* Not yet allocated, so allocate a new undefined one. */
        gen_label_new(gen_label);
    } else {
        /* Fail if we try to redefine a label. */
        if (value_tuple_fetch_integer(gen_label, GEN_LABEL_GLOBAL_POS) != 0) {
            return 0;
        }
    }

    value_tuple_store(gen_label, GEN_LABEL_TUPLE, tuple);
    value_tuple_store_integer(gen_label, GEN_LABEL_LOCAL_POS, local_pos);
    value_tuple_store_integer(gen_label, GEN_LABEL_GLOBAL_POS, global_pos);

    /*
     * Resolve any previous forward references by backpatching.
     */
    bp = value_tuple_fetch(gen_label, GEN_LABEL_NEXT);
    while (!value_is_null(bp)) {
        /*
         * Backpatch, by placing the current global position into
         * the slot named by the bp entry, then remove entry from list.
         */
        value_tuple_store_integer(
            value_tuple_fetch(bp, GEN_LABEL_TUPLE),
            value_tuple_fetch_integer(bp, GEN_LABEL_LOCAL_POS),
            global_pos
        );
        value_tuple_store(gen_label, GEN_LABEL_NEXT,
                          value_tuple_fetch(bp, GEN_LABEL_NEXT));
        bp = value_tuple_fetch(gen_label, GEN_LABEL_NEXT);
    }

    return 1;
}
Example #4
0
/*
 * Generate a reference to a label into the tuple, for instance as the
 * immediate argument of a branch instruction.  If the label parameter
 * is NULL, this will generate and return a forward reference which
 * should be resolved by subsequently passing it to gen_define_label().
 */
void
gen_gen_label_ref(struct value *gen, struct value *gen_label)
{
    struct value *bp;
    struct value next;
    int global_pos;

    assert(gen_label != NULL);

    if (value_is_null(gen_label)) {
        /* Not yet allocated, so allocate a new undefined one. */
        gen_label_new(gen_label);
    }

    global_pos = value_tuple_fetch_integer(gen_label, GEN_LABEL_GLOBAL_POS);
    if (global_pos != 0) {
        /* Already defined, so just use it. */
        gen_integer(gen, global_pos);
        return;
    }

    /*
     * The label is newly allocated, or at least has not been defined
     * yet.  So, we remember that we will need to backpatch here in the
     * future (by adding an entry to the label's backpatch list) and,
     * for now, generate a NULL in its slot.
     */

    value_copy(&next, value_tuple_fetch(gen_label, GEN_LABEL_NEXT));
    bp = value_tuple_fetch(gen_label, GEN_LABEL_NEXT);
    gen_label_new(bp);
    value_tuple_store(bp, GEN_LABEL_TUPLE, value_tuple_fetch(gen, GEN_CURRENT_TUPLE));
    value_tuple_store(bp, GEN_LABEL_LOCAL_POS, value_tuple_fetch(gen, GEN_LOCAL_POS));
    value_tuple_store(bp, GEN_LABEL_GLOBAL_POS, value_tuple_fetch(gen, GEN_GLOBAL_POS));
    value_tuple_store(bp, GEN_LABEL_NEXT, &next);

    gen_value(gen, &VNULL);
}
Example #5
0
int
value_save(struct process *p, struct value *value)
{
	unsigned char squeeze = (unsigned char)value->type;

#ifdef DEBUG
	process_render(process_err, "(save:%s ", type_name_table[(int)squeeze]);
        if (value->type == VALUE_SYMBOL) {
            process_render(process_err, "[%d] ", value_symbol_get_length(value));
        }
	value_portray(process_err, value);
	process_render(process_err, ")\n");
#endif

	stream_write(NULL, p, &squeeze, sizeof(squeeze));

	if ((value->type & VALUE_STRUCTURED) == 0) {
		stream_write(NULL, p, &value->value, sizeof(value->value));
	} else {
		unsigned int length, i;

		switch (value->type) {
		case VALUE_SYMBOL:
		    {
			const char *token = value_symbol_get_token(value);
			length = value_symbol_get_length(value);
			stream_write(NULL, p, &length, sizeof(length));
			stream_write(NULL, p, token, sizeof(char) * length);
			break;
		    }
		case VALUE_TUPLE:
		    {
                        struct value *tag = value_tuple_get_tag(value);
			value_save(p, tag);
                        /* XXX should eventually dispatch to a handler based on tag. */
                        if (value_equal(tag, &tag_dict)) {
                          	struct value dict_iter;
                                struct value *key;

                                value_dict_new_iter(&dict_iter, value);

                                length = value_dict_get_layer_size(value);
                                stream_write(NULL, p, &length, sizeof(length));
                                length = value_dict_get_length(value);
                                stream_write(NULL, p, &length, sizeof(length));
                          
                                key = value_dict_iter_get_current_key(&dict_iter);
                                while (!value_is_null(key)) {
                                        value_save(p, key);
                                        value_save(p, value_dict_fetch(value, key)); /* XXX not so good; use iter */
                                        value_dict_iter_advance(&dict_iter);
                                        key = value_dict_iter_get_current_key(&dict_iter);
                                }
                        } else {
                                length = value_tuple_get_size(value);
                                stream_write(NULL, p, &length, sizeof(length));
                                for (i = 0; i < length; i++) {
                                        value_save(p, value_tuple_fetch(value, i));
                                }
                        }
			break;
		    }
		default:
			assert(value->type == VALUE_SYMBOL ||
			       value->type == VALUE_TUPLE);
			break;
		}
	}

	return 1;
}