py: Add MICROPY_ENABLE_COMPILER and MICROPY_PY_BUILTINS_EVAL_EXEC opts.

MICROPY_ENABLE_COMPILER can be used to enable/disable the entire compiler,
which is useful when only loading of pre-compiled bytecode is supported.
It is enabled by default.

MICROPY_PY_BUILTINS_EVAL_EXEC controls support of eval and exec builtin
functions.  By default they are only included if MICROPY_ENABLE_COMPILER
is enabled.

Disabling both options saves about 40k of code size on 32-bit x86.
diff --git a/py/builtinevex.c b/py/builtinevex.c
index c14869e..cac74e9 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -107,6 +107,8 @@
 
 #endif // MICROPY_PY_BUILTINS_COMPILE
 
+#if MICROPY_PY_BUILTINS_EVAL_EXEC
+
 STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {
     // work out the context
     mp_obj_dict_t *globals = mp_globals_get();
@@ -155,6 +157,8 @@
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec);
 
+#endif // MICROPY_PY_BUILTINS_EVAL_EXEC
+
 #if MICROPY_PY_BUILTINS_EXECFILE
 STATIC mp_obj_t mp_builtin_execfile(mp_uint_t n_args, const mp_obj_t *args) {
     // MP_PARSE_SINGLE_INPUT is used to indicate a file input
diff --git a/py/builtinimport.c b/py/builtinimport.c
index a8d5f06..2560ec1 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -120,6 +120,7 @@
 #endif
 }
 
+#if MICROPY_ENABLE_COMPILER
 STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex, const char *fname) {
 
     if (lex == NULL) {
@@ -141,6 +142,7 @@
     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);
 }
+#endif
 
 #if MICROPY_PERSISTENT_CODE_LOAD
 STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) {
@@ -182,16 +184,24 @@
 STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
     // create the lexer
     char *file_str = vstr_null_terminated_str(file);
+
     #if MICROPY_PERSISTENT_CODE_LOAD
     if (file_str[file->len - 3] == 'm') {
         mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str);
         do_execute_raw_code(module_obj, raw_code);
-    } else
+        return;
+    }
     #endif
+
+    #if MICROPY_ENABLE_COMPILER
     {
         mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
         do_load_from_lexer(module_obj, lex, file_str);
     }
+    #else
+    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
+        "script compilation not supported"));
+    #endif
 }
 
 STATIC void chop_component(const char *start, const char **end) {
diff --git a/py/compile.c b/py/compile.c
index 4b929d5..f349dca 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -35,6 +35,8 @@
 #include "py/compile.h"
 #include "py/runtime.h"
 
+#if MICROPY_ENABLE_COMPILER
+
 // TODO need to mangle __attr names
 
 typedef enum {
@@ -3310,3 +3312,5 @@
     // return function that executes the outer module
     return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);
 }
+
+#endif // MICROPY_ENABLE_COMPILER
diff --git a/py/emitbc.c b/py/emitbc.c
index 7957a21..2f5304d 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -34,6 +34,8 @@
 #include "py/emit.h"
 #include "py/bc0.h"
 
+#if MICROPY_ENABLE_COMPILER
+
 #define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
 #define DUMMY_DATA_SIZE (BYTES_FOR_INT)
 
@@ -1070,3 +1072,5 @@
     mp_emit_bc_delete_global,
 };
 #endif
+
+#endif //MICROPY_ENABLE_COMPILER
diff --git a/py/emitcommon.c b/py/emitcommon.c
index 1fd2bd1..435188f 100644
--- a/py/emitcommon.c
+++ b/py/emitcommon.c
@@ -28,6 +28,8 @@
 
 #include "py/emit.h"
 
+#if MICROPY_ENABLE_COMPILER
+
 void mp_emit_common_get_id_for_load(scope_t *scope, qstr qst) {
     // name adding/lookup
     bool added;
@@ -77,3 +79,5 @@
         emit_method_table->deref(emit, qst, id->local_num);
     }
 }
+
+#endif // MICROPY_ENABLE_COMPILER
diff --git a/py/lexer.c b/py/lexer.c
index 6bacb9f..89ecc38 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -31,6 +31,8 @@
 #include "py/lexer.h"
 #include "py/runtime.h"
 
+#if MICROPY_ENABLE_COMPILER
+
 #define TAB_SIZE (8)
 
 // TODO seems that CPython allows NULL byte in the input stream
@@ -785,3 +787,5 @@
     printf("\n");
 }
 #endif
+
+#endif // MICROPY_ENABLE_COMPILER
diff --git a/py/lexerstr.c b/py/lexerstr.c
index 5481b10..9fdf4c1 100644
--- a/py/lexerstr.c
+++ b/py/lexerstr.c
@@ -26,6 +26,8 @@
 
 #include "py/lexer.h"
 
+#if MICROPY_ENABLE_COMPILER
+
 typedef struct _mp_lexer_str_buf_t {
     mp_uint_t free_len;         // if > 0, src_beg will be freed when done by: m_free(src_beg, free_len)
     const char *src_beg;        // beginning of source
@@ -59,3 +61,5 @@
     sb->src_end = str + len;
     return mp_lexer_new(src_name, sb, (mp_lexer_stream_next_byte_t)str_buf_next_byte, (mp_lexer_stream_close_t)str_buf_free);
 }
+
+#endif // MICROPY_ENABLE_COMPILER
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 2d2dd05..9d1e90f 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -630,8 +630,10 @@
     { MP_ROM_QSTR(MP_QSTR_chr), MP_ROM_PTR(&mp_builtin_chr_obj) },
     { MP_ROM_QSTR(MP_QSTR_dir), MP_ROM_PTR(&mp_builtin_dir_obj) },
     { MP_ROM_QSTR(MP_QSTR_divmod), MP_ROM_PTR(&mp_builtin_divmod_obj) },
+    #if MICROPY_PY_BUILTINS_EVAL_EXEC
     { MP_ROM_QSTR(MP_QSTR_eval), MP_ROM_PTR(&mp_builtin_eval_obj) },
     { MP_ROM_QSTR(MP_QSTR_exec), MP_ROM_PTR(&mp_builtin_exec_obj) },
+    #endif
     #if MICROPY_PY_BUILTINS_EXECFILE
     { MP_ROM_QSTR(MP_QSTR_execfile), MP_ROM_PTR(&mp_builtin_execfile_obj) },
     #endif
diff --git a/py/mpconfig.h b/py/mpconfig.h
index c05f33c..58aa2ce 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -278,6 +278,11 @@
 /*****************************************************************************/
 /* Compiler configuration                                                    */
 
+// Whether to include the compiler
+#ifndef MICROPY_ENABLE_COMPILER
+#define MICROPY_ENABLE_COMPILER (1)
+#endif
+
 // Whether to enable constant folding; eg 1+2 rewritten as 3
 #ifndef MICROPY_COMP_CONST_FOLDING
 #define MICROPY_COMP_CONST_FOLDING (1)
@@ -590,6 +595,12 @@
 #define MICROPY_PY_BUILTINS_ENUMERATE (1)
 #endif
 
+// Whether to support eval and exec functions
+// By default they are supported if the compiler is enabled
+#ifndef MICROPY_PY_BUILTINS_EVAL_EXEC
+#define MICROPY_PY_BUILTINS_EVAL_EXEC (MICROPY_ENABLE_COMPILER)
+#endif
+
 // Whether to support the Python 2 execfile function
 #ifndef MICROPY_PY_BUILTINS_EXECFILE
 #define MICROPY_PY_BUILTINS_EXECFILE (0)
diff --git a/py/parse.c b/py/parse.c
index ae15373..1741757 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -38,6 +38,8 @@
 #include "py/runtime.h"
 #include "py/builtin.h"
 
+#if MICROPY_ENABLE_COMPILER
+
 #define RULE_ACT_ARG_MASK       (0x0f)
 #define RULE_ACT_KIND_MASK      (0x30)
 #define RULE_ACT_ALLOW_IDENT    (0x40)
@@ -1079,3 +1081,5 @@
         chunk = next;
     }
 }
+
+#endif // MICROPY_ENABLE_COMPILER
diff --git a/py/runtime.c b/py/runtime.c
index c9a56f6..3a1f588 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -1304,6 +1304,8 @@
     }
 }
 
+#if MICROPY_ENABLE_COMPILER
+
 // this is implemented in this file so it can optimise access to locals/globals
 mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals) {
     // save context
@@ -1342,6 +1344,8 @@
     }
 }
 
+#endif // MICROPY_ENABLE_COMPILER
+
 void *m_malloc_fail(size_t num_bytes) {
     DEBUG_printf("memory allocation failed, allocating " UINT_FMT " bytes\n", num_bytes);
     if (0) {
diff --git a/py/scope.c b/py/scope.c
index f9b1fb1..632e527 100644
--- a/py/scope.c
+++ b/py/scope.c
@@ -28,6 +28,8 @@
 
 #include "py/scope.h"
 
+#if MICROPY_ENABLE_COMPILER
+
 scope_t *scope_new(scope_kind_t kind, mp_parse_node_t pn, qstr source_file, mp_uint_t emit_options) {
     scope_t *scope = m_new0(scope_t, 1);
     scope->kind = kind;
@@ -149,3 +151,5 @@
     }
     assert(0); // we should have found the variable in one of the parents
 }
+
+#endif // MICROPY_ENABLE_COMPILER