Exemple #1
0
STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
    // create the lexer
    mp_lexer_t *lex = mp_lexer_new_from_file(vstr_str(file));

    if (lex == NULL) {
        // we verified the file exists using stat, but lexer could still fail
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "No module named '%s'", vstr_str(file)));
    }

    qstr source_name = mp_lexer_source_name(lex);

    // save the old context
    mp_obj_dict_t *old_locals = mp_locals_get();
    mp_obj_dict_t *old_globals = mp_globals_get();

    // set the new context
    mp_locals_set(mp_obj_module_get_globals(module_obj));
    mp_globals_set(mp_obj_module_get_globals(module_obj));

    // parse the imported script
    mp_parse_error_kind_t parse_error_kind;
    mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind);

    if (pn == MP_PARSE_NODE_NULL) {
        // parse error; clean up and raise exception
        mp_obj_t exc = mp_parse_make_exception(lex, parse_error_kind);
        mp_lexer_free(lex);
        mp_locals_set(old_locals);
        mp_globals_set(old_globals);
        nlr_raise(exc);
    }

    mp_lexer_free(lex);

    // compile the imported script
    mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, false);
    mp_parse_node_free(pn);

    if (module_fun == mp_const_none) {
        // TODO handle compile error correctly
        mp_locals_set(old_locals);
        mp_globals_set(old_globals);
        nlr_raise(mp_obj_new_exception_msg(&mp_type_SyntaxError, "Syntax error in imported module"));
    }

    // complied successfully, execute it
    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
        mp_call_function_0(module_fun);
        nlr_pop();
    } else {
        // exception; restore context and re-raise same exception
        mp_locals_set(old_locals);
        mp_globals_set(old_globals);
        nlr_raise(nlr.ret_val);
    }
    mp_locals_set(old_locals);
    mp_globals_set(old_globals);
}
Exemple #2
0
STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) {
    #if MICROPY_PY___FILE__
    // TODO
    //qstr source_name = lex->source_name;
    //mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
    #endif

    // execute the module in its context
    mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);

    // save context
    mp_obj_dict_t *volatile old_globals = mp_globals_get();
    mp_obj_dict_t *volatile old_locals = mp_locals_get();

    // set new context
    mp_globals_set(mod_globals);
    mp_locals_set(mod_globals);

    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
        mp_obj_t module_fun = mp_make_function_from_raw_code(raw_code, MP_OBJ_NULL, MP_OBJ_NULL);
        mp_call_function_0(module_fun);

        // finish nlr block, restore context
        nlr_pop();
        mp_globals_set(old_globals);
        mp_locals_set(old_locals);
    } else {
        // exception; restore context and re-raise same exception
        mp_globals_set(old_globals);
        mp_locals_set(old_locals);
        nlr_raise(nlr.ret_val);
    }
}
Exemple #3
0
STATIC mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) {
    // TODO make this function more general and less of a hack

    mp_obj_dict_t *dict = NULL;
    if (n_args == 0) {
        // make a list of names in the local name space
        dict = mp_locals_get();
    } else { // n_args == 1
        // make a list of names in the given object
        if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {
            dict = mp_obj_module_get_globals(args[0]);
        } else {
            mp_obj_type_t *type;
            if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
                type = args[0];
            } else {
                type = mp_obj_get_type(args[0]);
            }
            if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
                dict = type->locals_dict;
            }
        }
    }

    mp_obj_t dir = mp_obj_new_list(0, NULL);
    if (dict != NULL) {
        for (uint i = 0; i < dict->map.alloc; i++) {
            if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
                mp_obj_list_append(dir, dict->map.table[i].key);
            }
        }
    }

    return dir;
}
Exemple #4
0
STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
    if (n_args == 0) {
        // print a general help message
        printf("%s", help_text);
    }
    else {
        // try to print something sensible about the given object
        printf("object ");
        mp_obj_print(args[0], PRINT_STR);
        printf(" is of type %s\n", mp_obj_get_type_str(args[0]));

        mp_map_t *map = NULL;
        if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {
            map = mp_obj_dict_get_map(mp_obj_module_get_globals(args[0]));
        } else {
            mp_obj_type_t *type;
            if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
                type = args[0];
            } else {
                type = mp_obj_get_type(args[0]);
            }
            if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
                map = mp_obj_dict_get_map(type->locals_dict);
            }
        }
        if (map != NULL) {
            for (uint i = 0; i < map->alloc; i++) {
                if (map->table[i].key != MP_OBJ_NULL) {
                    pyb_help_print_info_about_object(map->table[i].key, map->table[i].value);
                }
            }
        }
    }
    return mp_const_none;
}
STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex) {
    #if MICROPY_PY___FILE__
    qstr source_name = lex->source_name;
    mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
    #endif

    // parse, compile and execute the module in its context
    mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);
    mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
}
STATIC void mp_help_print_obj(mp_obj_t obj) {
    #if MICROPY_PY_BUILTINS_HELP_MODULES
    if (obj == MP_OBJ_NEW_QSTR(MP_QSTR_modules)) {
        mp_help_print_modules();
        return;
    }
    #endif

    // Extract method from bound method, for better error messages
    if (mp_obj_get_type(obj)->name == MP_QSTR_bound_method) {
        obj = ((mp_obj_t*)obj)[1]; // extract method
    }

    // Hook into platform-specific help for this object
    extern bool mp_plat_specific_help(mp_obj_t obj);
    if (mp_plat_specific_help(obj)) {
        return;
    }

    // try to print something sensible about the given object
    mp_print_str(MP_PYTHON_PRINTER, "object ");
    mp_obj_print(obj, PRINT_STR);
    mp_printf(MP_PYTHON_PRINTER, " is of type %s\n", mp_obj_get_type_str(obj));

    mp_map_t *map = NULL;
    if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {
        map = mp_obj_dict_get_map(mp_obj_module_get_globals(obj));
    } else {
        mp_obj_type_t *type;
        if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {
            type = obj;
        } else {
            type = mp_obj_get_type(obj);
        }
        if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
            map = mp_obj_dict_get_map(type->locals_dict);
        }
    }
    if (map != NULL) {
        for (uint i = 0; i < map->alloc; i++) {
            if (map->table[i].key != MP_OBJ_NULL) {
                mp_help_print_info_about_object(map->table[i].key, map->table[i].value);
            }
        }
    }
}
STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
    // create the lexer
    mp_lexer_t *lex = mp_lexer_new_from_file(vstr_str(file));

    if (lex == NULL) {
        // we verified the file exists using stat, but lexer could still fail
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "No module named '%s'", vstr_str(file)));
    }

    #if MICROPY_PY___FILE__
    qstr source_name = mp_lexer_source_name(lex);
    mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
    #endif

    // parse, compile and execute the module in its context
    mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);
    mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
}
STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex, const char *fname) {

    if (lex == NULL) {
        // we verified the file exists using stat, but lexer could still fail
        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found"));
        } else {
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
                "no module named '%s'", fname));
        }
    }

    #if MICROPY_PY___FILE__
    qstr source_name = lex->source_name;
    mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
    #endif

    // parse, compile and execute the module in its context
    mp_obj_dict_t *mod_globals = mp_obj_module_get_globals(module_obj);
    mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
}
Exemple #9
0
STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
    if (n_args == 0) {
        // print a general help message
        mp_printf(&mp_plat_print, "%s", help_text);

    } else {
        mp_obj_t args0 = args[0];
        mp_obj_type_t *args0_type = mp_obj_get_type(args0);
        if (args0_type->name == MP_QSTR_bound_method) {
            args0 = ((mp_obj_t*)args0)[1]; // extract method
            args0_type = mp_obj_get_type(args0);
        }

        // see if we have specific help info for this instance
        for (size_t i = 0; i < MP_ARRAY_SIZE(help_table_instances); i++) {
            if (args0 == help_table_instances[i].obj) {
                mp_print_str(&mp_plat_print, help_table_instances[i].doc);
                //if (args0_type == &mp_type_module) {
                //TODO here we can list the things inside the module
                //}
                return mp_const_none;
            }
        }

        // see if we have specific help info for this type
        for (size_t i = 0; i < MP_ARRAY_SIZE(help_table_types); i++) {
            if (args0 == help_table_types[i].obj || args0_type == help_table_types[i].obj) {
                mp_print_str(&mp_plat_print, help_table_types[i].doc);
                return mp_const_none;
            }
        }

        // don't have specific help info, try instead to print something sensible

        mp_printf(&mp_plat_print, "object ");
        mp_obj_print(args0, PRINT_STR);
        mp_printf(&mp_plat_print, " is of type %q\n", args0_type->name);

        mp_map_t *map = NULL;
        if (args0_type == &mp_type_module) {
            map = mp_obj_dict_get_map(mp_obj_module_get_globals(args0));
        } else {
            mp_obj_type_t *type;
            if (args0_type == &mp_type_type) {
                type = args0;
            } else {
                type = args0_type;
            }
            if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
                map = mp_obj_dict_get_map(type->locals_dict);
            }
        }
        if (map != NULL) {
            for (uint i = 0; i < map->alloc; i++) {
                if (map->table[i].key != MP_OBJ_NULL) {
                    pyb_help_print_info_about_object(map->table[i].key, map->table[i].value);
                }
            }
        }
    }

    return mp_const_none;
}
Exemple #10
0
mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t *print, const char **compl_str) {
    // scan backwards to find start of "a.b.c" chain
    const char *org_str = str;
    const char *top = str + len;
    for (const char *s = top; --s >= str;) {
        if (!(unichar_isalpha(*s) || unichar_isdigit(*s) || *s == '_' || *s == '.')) {
            ++s;
            str = s;
            break;
        }
    }

    // begin search in locals dict
    mp_obj_dict_t *dict = mp_locals_get();

    for (;;) {
        // get next word in string to complete
        const char *s_start = str;
        while (str < top && *str != '.') {
            ++str;
        }
        mp_uint_t s_len = str - s_start;

        if (str < top) {
            // a complete word, lookup in current dict

            mp_obj_t obj = MP_OBJ_NULL;
            for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
                if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
                    size_t d_len;
                    const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
                    if (s_len == d_len && strncmp(s_start, d_str, d_len) == 0) {
                        obj = dict->map.table[i].value;
                        break;
                    }
                }
            }

            if (obj == MP_OBJ_NULL) {
                // lookup failed
                return 0;
            }

            // found an object of this name; try to get its dict
            if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {
                dict = mp_obj_module_get_globals(obj);
            } else {
                mp_obj_type_t *type;
                if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {
                    type = MP_OBJ_TO_PTR(obj);
                } else {
                    type = mp_obj_get_type(obj);
                }
                if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {
                    dict = type->locals_dict;
                } else {
                    // obj has no dict
                    return 0;
                }
            }

            // skip '.' to move to next word
            ++str;

        } else {
            // end of string, do completion on this partial name

            // look for matches
            int n_found = 0;
            const char *match_str = NULL;
            mp_uint_t match_len = 0;
            for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
                if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
                    size_t d_len;
                    const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
                    if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
                        if (match_str == NULL) {
                            match_str = d_str;
                            match_len = d_len;
                        } else {
                            // search for longest common prefix of match_str and d_str
                            // (assumes these strings are null-terminated)
                            for (mp_uint_t j = s_len; j <= match_len && j <= d_len; ++j) {
                                if (match_str[j] != d_str[j]) {
                                    match_len = j;
                                    break;
                                }
                            }
                        }
                        ++n_found;
                    }
                }
            }

            // nothing found
            if (n_found == 0) {
                // If there're no better alternatives, and if it's first word
                // in the line, try to complete "import".
                if (s_start == org_str) {
                    static const char import_str[] = "import ";
                    if (memcmp(s_start, import_str, s_len) == 0) {
                        *compl_str = import_str + s_len;
                        return sizeof(import_str) - 1 - s_len;
                    }
                }

                return 0;
            }

            // 1 match found, or multiple matches with a common prefix
            if (n_found == 1 || match_len > s_len) {
                *compl_str = match_str + s_len;
                return match_len - s_len;
            }

            // multiple matches found, print them out

            #define WORD_SLOT_LEN (16)
            #define MAX_LINE_LEN  (4 * WORD_SLOT_LEN)

            int line_len = MAX_LINE_LEN; // force a newline for first word
            for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
                if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
                    size_t d_len;
                    const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
                    if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
                        int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len;
                        if (gap < 2) {
                            gap += WORD_SLOT_LEN;
                        }
                        if (line_len + gap + d_len <= MAX_LINE_LEN) {
                            // TODO optimise printing of gap?
                            for (int j = 0; j < gap; ++j) {
                                mp_print_str(print, " ");
                            }
                            mp_print_str(print, d_str);
                            line_len += gap + d_len;
                        } else {
                            mp_printf(print, "\n%s", d_str);
                            line_len = d_len;
                        }
                    }
                }
            }
            mp_print_str(print, "\n");

            return (mp_uint_t)(-1); // indicate many matches
        }
    }
}