Beispiel #1
0
void repl() {
    char str[FG_MAX_INPUT];
    struct context *context = context_new(NULL, true, true);

    for (;;) {
        fflush(stdin);
        str[0] = 0;
        printf("f> ");
        if (!fgets(str, FG_MAX_INPUT, stdin)) {
            if (feof(stdin))
                return;
            if (ferror(stdin)) {
                printf("unknown error reading stdin\n");
                return;
            }
        }

        struct byte_array *input = byte_array_from_string(str);
        struct byte_array *program = build_string(input, NULL);
        if (!setjmp(trying)) {
            run(context, program, NULL, true);
        }
        byte_array_del(input);
        byte_array_del(program);
    }
}
Beispiel #2
0
void interpret_file(struct byte_array *path,
                    struct byte_array *args)
{
    struct byte_array *program;

    if (NULL != args)
    {
        struct byte_array *source = read_file(path, 0, 0);
        if (NULL == source)
            return;

        byte_array_append(args, source);
        program = build_string(args, path);
    }
    else
    {
        program = build_file(path);
    }

#ifdef DEBUG
    //display_program(program);
#endif

    execute(program);
    byte_array_del(program);
}
Beispiel #3
0
static inline struct variable *cfnc_serialize(struct context *context)
{
    struct variable *args = (struct variable*)stack_pop(context->operand_stack);
    struct variable *indexable = (struct variable*)array_get(args->list.ordered, 0);

    struct byte_array *bits = variable_serialize(context, NULL, indexable);
    byte_array_reset(bits);
    struct variable *result = variable_new_str(context, bits);
    byte_array_del(bits);
    return result;
}
Beispiel #4
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;
}
Beispiel #5
0
struct variable *sys_save(struct context *context)
{
    struct variable *args = (struct variable*)stack_pop(context->operand_stack);
    struct variable *v = param_var(args, 1);
    struct variable *path = param_var(args, 2);
    struct byte_array *bytes = byte_array_new();
    variable_serialize(context, bytes, v);
    int w = write_file(path->str, bytes, 0, -1);
    byte_array_del(bytes);
    return variable_new_int(context, w);
}
Beispiel #6
0
int main (int argc, char** argv) {
	struct sigaction act, oact; // for handling ctrl-c
	act.sa_handler = sig_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGINT, &act, &oact);
    
    if (1 == argc) {
        repl();
    } else {
        struct byte_array *args = arg2ba(argc, argv);
        struct byte_array *path = byte_array_from_string(argv[1]);

        interpret_file(path, args);

        if (NULL != args) {
            byte_array_del(args);
        }
        byte_array_del(path);
    }
}
Beispiel #7
0
//    a                b        c
// <sought> <replacement> [<start>]
// <start> <length> <replacement>
static inline struct variable *cfnc_replace(struct context *context)
{
    struct variable *args = (struct variable*)stack_pop(context->operand_stack);
    struct variable *self = (struct variable*)array_get(args->list.ordered, 0);
    struct variable *a = (struct variable*)array_get(args->list.ordered, 1);
    struct variable *b = (struct variable*)array_get(args->list.ordered, 2);
    struct variable *c = args->list.ordered->length > 3 ?
        (struct variable*)array_get(args->list.ordered, 3) : NULL;

    null_check(self);
    null_check(b);
    assert_message(self->type == VAR_STR, "searching in a non-string");

    struct byte_array *replaced = NULL;

    if (a->type == VAR_STR) { // find a, replace with b

        assert_message(b->type == VAR_STR, "non-string replacement");
        int32_t where = 0;

        if (c) { // replace first match after index c

            assert_message(c->type == VAR_INT, "non-integer index");
            if (((where = byte_array_find(self->str, a->str, c->integer)) >= 0))
                replaced = byte_array_replace(self->str, b->str, where, b->str->length);

        } else {

            replaced = byte_array_replace_all(self->str, a->str, b->str);
        }

    } else if (a->type == VAR_INT ) { // replace at index a, length b, insert c

        assert_message(a || a->type == VAR_INT, "non-integer count");
        assert_message(b || b->type == VAR_INT, "non-integer start");
        replaced = byte_array_replace(self->str, c->str, a->integer, b->integer);

    } else exit_message("replacement is not a string");

    null_check(replaced);
    struct variable *result = variable_new_str(context, replaced);
    byte_array_del(replaced);

    return result;
}
Beispiel #8
0
struct byte_array *byte_array_replace_all(struct byte_array *original, struct byte_array *a, struct byte_array *b)
{
    /*DEBUGPRINT("replace in %s: %s -> %s\n",
               byte_array_to_string(original),
               byte_array_to_string(a),
               byte_array_to_string(b));*/

    struct byte_array *replaced = byte_array_copy(original);
    int32_t where = 0;

    for(;;) { // replace all

        if ((where = byte_array_find(replaced, a, where)) < 0)
            break;
        struct byte_array *replaced2 = byte_array_replace(replaced, b, where++, a->length);
        byte_array_del(replaced);
        replaced = replaced2;
    }
    return replaced;
}
Beispiel #9
0
static inline struct variable *cfnc_insert(struct context *context) // todo: test
{
    struct variable *args = (struct variable*)stack_pop(context->operand_stack);
    struct variable *self = (struct variable*)array_get(args->list.ordered, 0);
    struct variable *insertion = (struct variable*)array_get(args->list.ordered, 1);
    struct variable *start = args->list.ordered->length > 2 ?
        (struct variable*)array_get(args->list.ordered, 2) : NULL;
    null_check(self);
    null_check(insertion);
    assert_message(!start || start->type == VAR_INT, "non-integer index");

    int32_t position = 0;
    switch (self->type) {
        case VAR_LST: {
            struct array *list = array_new_size(1);
            array_set(list, 0, insertion);
            insertion = variable_new_list(context, list);
            position = self->list.ordered->length;
            array_del(list);
        } break;
        case VAR_STR:
            assert_message(insertion->type == VAR_STR, "insertion doesn't match destination");
            position = self->str->length;
            break;
        default:
            exit_message("bad insertion destination");
            break;
    }

    struct variable *first = variable_part(context, variable_copy(context, self), 0, position);
    struct variable *second = variable_part(context, variable_copy(context, self), position, -1);
    struct variable *joined = variable_concatenate(context, 3, first, insertion, second);
    
    if (self->type == VAR_LST) {
        array_del(self->list.ordered);
        self->list.ordered = array_copy(joined->list.ordered);
    } else {
        byte_array_del(self->str);
        self->str = byte_array_copy(joined->str);
    } return joined;
}
Beispiel #10
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;
}
Beispiel #11
0
void interpret_string(struct context *context, struct byte_array *script) {
    struct byte_array *program = build_string(script, NULL);
    execute_with(context, program, true);
    byte_array_del(program);
}
Beispiel #12
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;
}