Exemple #1
0
// get the indexed item and push on operand stack
void lookup(struct context *context, struct variable *indexable, struct variable *index, bool really)
{
    if (!really && custom_method(context, RESERVED_GET, indexable, index, NULL)) {
        return;
    }

    struct variable *item=0;

    switch (index->type) {
        case VAR_INT:
            item = list_get_int(context, indexable, index->integer);
            break;
        case VAR_STR:
            if (indexable->map)
                item = (struct variable*)map_get(indexable->map, index->str);
            if (!item)
                item = builtin_method(context, indexable, index);
            if (!item)
                item = variable_new_nil(context);
            break;
        case VAR_NIL:
            item = variable_new_nil(context);
            break;
        default:
            vm_exit_message(context, "bad index type");
            break;
    }
    //    DEBUGPRINT(" found %s\n", variable_value_str(context, item));
    variable_push(context, item);
}
Exemple #2
0
static inline struct variable *cfnc_chop(struct context *context, bool snip)
{
    int32_t beginning, foraslongas;

    struct variable *args = (struct variable*)stack_pop(context->operand_stack);
    struct variable *self = (struct variable*)array_get(args->list.ordered, 0);

    enum VarType type = self->type;
    if (type == VAR_NIL)
        return variable_new_nil(context);
    assert_message(self->type == VAR_LST || self->type == VAR_STR, "can't chop");
    
    if (args->list.ordered->length > 1) {
        struct variable *start = (struct variable*)array_get(args->list.ordered, 1);
        assert_message(start->type == VAR_INT, "non-integer index");
        beginning = start->integer;
    }
    else beginning = 0;

    if (args->list.ordered->length > 2) {
        struct variable *length = (struct variable*)array_get(args->list.ordered, 2);
        assert_message(length->type == VAR_INT, "non-integer length");
        foraslongas = length->integer;
    } else
        foraslongas = snip ? 1 : self->str->length - beginning;

    struct variable *result = variable_part(context, self, beginning, foraslongas);
    if (snip)
        variable_remove(self, beginning, foraslongas);
    return result;
}
Exemple #3
0
struct variable *sys_load(struct context *context)
{
    struct variable *value = (struct variable*)stack_pop(context->operand_stack);
    struct variable *path = (struct variable*)array_get(value->list.ordered, 1);
    struct byte_array *file_bytes = read_file(path->str, 0, 0);
    if (NULL == file_bytes)
        return variable_new_nil(context);
    struct variable *v = variable_deserialize(context, file_bytes);
    byte_array_del(file_bytes);
    return v;
}
Exemple #4
0
static void unary_op(struct context *context, enum Opcode op)
{
    if (!context->runtime)
        VM_DEBUGPRINT("%s\n", NUM_TO_STRING(opcodes, op));

    struct variable *v = (struct variable*)variable_pop(context);
    struct variable *result = NULL;

    switch (v->type) {
        case VAR_NIL:
        {
            switch (op) {
                case VM_NEG:    result = variable_new_nil(context);              break;
                case VM_NOT:    result = variable_new_bool(context, true);       break;
                default:        vm_exit_message(context, "bad math operator");   break;
            }
        } break;
        case VAR_INT: {
            int32_t n = v->integer;
            switch (op) {
                case VM_NEG:    result = variable_new_int(context, -n);          break;
                case VM_NOT:    result = variable_new_bool(context, !n);         break;
                case VM_INV:    result = variable_new_int(context, ~n);          break;
                default:        vm_exit_message(context, "bad math operator");   break;
            }
        } break;
        case VAR_FLT: {
            float n = v->floater;
            switch (op) {
                case VM_NEG:    result = variable_new_float(context, -n);        break;
                case VM_NOT:    result = variable_new_bool(context, !n);         break;
                default:        vm_exit_message(context, "bad math operator");   break;
            }
        } break;
        default:
            if (op == VM_NOT)
                result = variable_new_bool(context, false);
            else
                vm_exit_message(context, "bad math type");
            break;
    }

    variable_push(context, result);

    DEBUGPRINT("%s(%s) = %s\n",
               NUM_TO_STRING(opcodes, op),
               variable_value_str(context, v),
               variable_value_str(context, result));
}
Exemple #5
0
static struct variable *get_value(struct context *context, enum Opcode op)
{
    bool interim = op == VM_STX || op == VM_PTX;
    struct variable *value = stack_peek(context->operand_stack, 0);
    null_check(value);

    if (value->type == VAR_SRC) {
        struct array *values = value->list;
        if (values->length > values->current)
            value = (struct variable*)array_get(values, values->current++);
        else
            value = variable_new_nil(context);
        if (interim)
            values->current = 0;
    }
    else if (!interim)
        variable_pop(context);

    return value;
}
Exemple #6
0
void func_call(struct context *context, enum Opcode op, struct byte_array *program, struct variable *indexable)
{
    struct variable *func = context->runtime ? (struct variable*)variable_pop(context): NULL;

    struct variable *s = src(context, op, program);
    if (!context->runtime)
        return;

    if (indexable)
        array_insert(s->list, 0, indexable); // self

    vm_call_src(context, func);

    struct variable *result = (struct variable*)stack_peek(context->operand_stack, 0);
    bool resulted = (result && result->type == VAR_SRC);

    if (!resulted) { // need a result for an expression, so pretend it returned nil
        struct variable *v = variable_new_src(context, 0);
        array_add(v->list, variable_new_nil(context));
        stack_push(context->operand_stack, v);
    }
}
Exemple #7
0
// returns contents and modification time of file
struct variable *sys_read(struct context *context)
{
    struct variable *args = (struct variable*)stack_pop(context->operand_stack);
    struct variable *path = param_var(args, 1);
    uint32_t offset = param_int(args, 2);
    uint32_t length = param_int(args, 3);

    struct byte_array *bytes = read_file(path->str, offset, length);
    DEBUGPRINT("read %d bytes\n", bytes ? bytes->length : 0);

    struct variable *content = NULL;
    if (NULL != bytes)
    {
        content = variable_new_str(context, bytes);
        byte_array_del(bytes);
    }
    else
    {
        context->error = variable_new_str_chars(context, "could not load file");
        content = variable_new_nil(context);
    }
    return content;
}
Exemple #8
0
static struct variable *list_get_int(struct context *context,
                                     const struct variable *indexable,
                                     uint32_t index)
{
    null_check(indexable);

    enum VarType it = (enum VarType)indexable->type;
    switch (it) {
        case VAR_INT: return variable_new_int(context, index);
        case VAR_LST:
            if (index < indexable->list->length)
                return (struct variable*)array_get(indexable->list, index);
            return variable_new_nil(context);
        case VAR_STR: {
            vm_assert(context, index < indexable->str->length, "index out of bounds");
            char *str = (char*)malloc(2);
            sprintf(str, "%c", indexable->str->data[index]);
            return variable_new_str(context, byte_array_from_string(str));
        }
        default:
            vm_exit_message(context, "indexing non-indexable");
            return NULL;
    }
}
Exemple #9
0
static void push_nil(struct context *context)
{
    struct variable* var = variable_new_nil(context);
    VM_DEBUGPRINT("NIL\n");
    variable_push(context, var);
}
Exemple #10
0
struct variable *builtin_method(struct context *context,
                                struct variable *indexable,
                                const struct variable *index)
{
    enum VarType it = indexable->type;
    char *idxstr = byte_array_to_string(index->str);
    struct variable *result = NULL;

    if (!strcmp(idxstr, FNC_LENGTH)) {
        int n;
        switch (indexable->type) {
            case VAR_LST: n = indexable->list.ordered->length;  break;
            case VAR_STR: n = indexable->str->length;           break;
            case VAR_NIL: n = 0;                                break;
            default:
                free(idxstr);
                exit_message("no length for non-indexable");
                return NULL;
        }
        result = variable_new_int(context, n);
    }
    else if (!strcmp(idxstr, FNC_TYPE)) {
        const char *typestr = var_type_str(it);
        result = variable_new_str_chars(context, typestr);
    }

    else if (!strcmp(idxstr, FNC_STRING)) {
        switch (indexable->type) {
            case VAR_STR:
            case VAR_BYT:
            case VAR_FNC:
                result = variable_copy(context, indexable);
                break;
            default: {
                struct byte_array *vv = variable_value(context, indexable);
                result = variable_new_str(context, vv);
                byte_array_del(vv);
                break;
            }
        }
    }

    else if (!strcmp(idxstr, FNC_LIST))
        result = variable_new_list(context, indexable->list.ordered);

    else if (!strcmp(idxstr, FNC_KEY)) {
        if (indexable->type == VAR_KVP)
            result = indexable->kvp.key;
        else
            result = variable_new_nil(context);
    }

    else if (!strcmp(idxstr, FNC_VAL)) {
        if (indexable->type == VAR_KVP)
            result = indexable->kvp.val;
        else
            result = variable_new_nil(context);
    }

    else if (!strcmp(idxstr, FNC_KEYS))
        result = variable_map_list(context, indexable, &map_keys);

    else if (!strcmp(idxstr, FNC_VALS))
        result = variable_map_list(context, indexable, &map_vals);

    else if (!strcmp(idxstr, FNC_PACK))
        result = variable_new_cfnc(context, &cfnc_pack);

    else if (!strcmp(idxstr, FNC_SERIALIZE))
        result = variable_new_cfnc(context, &cfnc_serialize);
    
    else if (!strcmp(idxstr, FNC_DESERIALIZE))
        result = variable_new_cfnc(context, &cfnc_deserialize);

    else if (!strcmp(idxstr, FNC_SORT)) {
        assert_message(indexable->type == VAR_LST, "sorting non-list");
        result = variable_new_cfnc(context, &cfnc_sort);
    }

    else if (!strcmp(idxstr, FNC_CHAR))
        result = variable_new_cfnc(context, &cfnc_char);

    else if (!strcmp(idxstr, FNC_HAS))
        result = variable_new_cfnc(context, &cfnc_has);

    else if (!strcmp(idxstr, FNC_FIND))
        result = variable_new_cfnc(context, &cfnc_find);

    else if (!strcmp(idxstr, FNC_PART))
        result = variable_new_cfnc(context, &cfnc_part);

    else if (!strcmp(idxstr, FNC_REMOVE))
        result = variable_new_cfnc(context, &cfnc_remove);

    else if (!strcmp(idxstr, FNC_INSERT))
        result = variable_new_cfnc(context, &cfnc_insert);

    else if (!strcmp(idxstr, FNC_REPLACE))
        result = variable_new_cfnc(context, &cfnc_replace);

    free(idxstr);
    return result;
}