py: Put all bytecode state (arg count, etc) in bytecode.
diff --git a/py/bc.c b/py/bc.c
index a4ee847..da0ea78 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -31,6 +31,7 @@
 
 #include "py/nlr.h"
 #include "py/objfun.h"
+#include "py/runtime0.h"
 #include "py/bc.h"
 
 #if 0 // print debugging info
@@ -100,6 +101,12 @@
     code_state->prev = NULL;
     #endif
 
+    // get params
+    mp_uint_t scope_flags = *code_state->ip++;
+    mp_uint_t n_pos_args = *code_state->ip++;
+    mp_uint_t n_kwonly_args = *code_state->ip++;
+    mp_uint_t n_def_pos_args = *code_state->ip++;
+
     // align ip
     code_state->ip = MP_ALIGN(code_state->ip, sizeof(mp_uint_t));
 
@@ -112,33 +119,33 @@
     const mp_obj_t *kwargs = args + n_args;
 
     // var_pos_kw_args points to the stack where the var-args tuple, and var-kw dict, should go (if they are needed)
-    mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - self->n_pos_args - self->n_kwonly_args];
+    mp_obj_t *var_pos_kw_args = &code_state->state[n_state - 1 - n_pos_args - n_kwonly_args];
 
     // check positional arguments
 
-    if (n_args > self->n_pos_args) {
+    if (n_args > n_pos_args) {
         // given more than enough arguments
-        if (!self->takes_var_args) {
-            fun_pos_args_mismatch(self, self->n_pos_args, n_args);
+        if ((scope_flags & MP_SCOPE_FLAG_VARARGS) == 0) {
+            fun_pos_args_mismatch(self, n_pos_args, n_args);
         }
         // put extra arguments in varargs tuple
-        *var_pos_kw_args-- = mp_obj_new_tuple(n_args - self->n_pos_args, args + self->n_pos_args);
-        n_args = self->n_pos_args;
+        *var_pos_kw_args-- = mp_obj_new_tuple(n_args - n_pos_args, args + n_pos_args);
+        n_args = n_pos_args;
     } else {
-        if (self->takes_var_args) {
+        if ((scope_flags & MP_SCOPE_FLAG_VARARGS) != 0) {
             DEBUG_printf("passing empty tuple as *args\n");
             *var_pos_kw_args-- = mp_const_empty_tuple;
         }
         // Apply processing and check below only if we don't have kwargs,
         // otherwise, kw handling code below has own extensive checks.
-        if (n_kw == 0 && !self->has_def_kw_args) {
-            if (n_args >= (mp_uint_t)(self->n_pos_args - self->n_def_args)) {
+        if (n_kw == 0 && (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) == 0) {
+            if (n_args >= (mp_uint_t)(n_pos_args - n_def_pos_args)) {
                 // given enough arguments, but may need to use some default arguments
-                for (mp_uint_t i = n_args; i < self->n_pos_args; i++) {
-                    code_state->state[n_state - 1 - i] = self->extra_args[i - (self->n_pos_args - self->n_def_args)];
+                for (mp_uint_t i = n_args; i < n_pos_args; i++) {
+                    code_state->state[n_state - 1 - i] = self->extra_args[i - (n_pos_args - n_def_pos_args)];
                 }
             } else {
-                fun_pos_args_mismatch(self, self->n_pos_args - self->n_def_args, n_args);
+                fun_pos_args_mismatch(self, n_pos_args - n_def_pos_args, n_args);
             }
         }
     }
@@ -150,12 +157,12 @@
 
     // check keyword arguments
 
-    if (n_kw != 0 || self->has_def_kw_args) {
+    if (n_kw != 0 || (scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {
         DEBUG_printf("Initial args: ");
-        dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);
+        dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
 
         mp_obj_t dict = MP_OBJ_NULL;
-        if (self->takes_kw_args) {
+        if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
             dict = mp_obj_new_dict(n_kw); // TODO: better go conservative with 0?
             *var_pos_kw_args = dict;
         }
@@ -165,7 +172,7 @@
 
         for (mp_uint_t i = 0; i < n_kw; i++) {
             mp_obj_t wanted_arg_name = kwargs[2 * i];
-            for (mp_uint_t j = 0; j < self->n_pos_args + self->n_kwonly_args; j++) {
+            for (mp_uint_t j = 0; j < n_pos_args + n_kwonly_args; j++) {
                 if (wanted_arg_name == arg_names[j]) {
                     if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {
                         nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
@@ -176,7 +183,7 @@
                 }
             }
             // Didn't find name match with positional args
-            if (!self->takes_kw_args) {
+            if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) {
                 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
             }
             mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
@@ -184,19 +191,19 @@
         }
 
         DEBUG_printf("Args with kws flattened: ");
-        dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);
+        dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
 
         // fill in defaults for positional args
-        mp_obj_t *d = &code_state->state[n_state - self->n_pos_args];
-        mp_obj_t *s = &self->extra_args[self->n_def_args - 1];
-        for (mp_uint_t i = self->n_def_args; i > 0; i--, d++, s--) {
+        mp_obj_t *d = &code_state->state[n_state - n_pos_args];
+        mp_obj_t *s = &self->extra_args[n_def_pos_args - 1];
+        for (mp_uint_t i = n_def_pos_args; i > 0; i--, d++, s--) {
             if (*d == MP_OBJ_NULL) {
                 *d = *s;
             }
         }
 
         DEBUG_printf("Args after filling default positional: ");
-        dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);
+        dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
 
         // Check that all mandatory positional args are specified
         while (d < &code_state->state[n_state]) {
@@ -208,35 +215,35 @@
 
         // Check that all mandatory keyword args are specified
         // Fill in default kw args if we have them
-        for (mp_uint_t i = 0; i < self->n_kwonly_args; i++) {
-            if (code_state->state[n_state - 1 - self->n_pos_args - i] == MP_OBJ_NULL) {
+        for (mp_uint_t i = 0; i < n_kwonly_args; i++) {
+            if (code_state->state[n_state - 1 - n_pos_args - i] == MP_OBJ_NULL) {
                 mp_map_elem_t *elem = NULL;
-                if (self->has_def_kw_args) {
-                    elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[self->n_def_args])->map, arg_names[self->n_pos_args + i], MP_MAP_LOOKUP);
+                if ((scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {
+                    elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[n_def_pos_args])->map, arg_names[n_pos_args + i], MP_MAP_LOOKUP);
                 }
                 if (elem != NULL) {
-                    code_state->state[n_state - 1 - self->n_pos_args - i] = elem->value;
+                    code_state->state[n_state - 1 - n_pos_args - i] = elem->value;
                 } else {
                     nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
-                        "function missing required keyword argument '%q'", MP_OBJ_QSTR_VALUE(arg_names[self->n_pos_args + i])));
+                        "function missing required keyword argument '%q'", MP_OBJ_QSTR_VALUE(arg_names[n_pos_args + i])));
                 }
             }
         }
 
     } else {
         // no keyword arguments given
-        if (self->n_kwonly_args != 0) {
+        if (n_kwonly_args != 0) {
             nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                 "function missing keyword-only argument"));
         }
-        if (self->takes_kw_args) {
+        if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
             *var_pos_kw_args = mp_obj_new_dict(0);
         }
     }
 
     // get the ip and skip argument names
     const byte *ip = code_state->ip;
-    ip += (self->n_pos_args + self->n_kwonly_args) * sizeof(mp_uint_t);
+    ip += (n_pos_args + n_kwonly_args) * sizeof(mp_uint_t);
 
     // store pointer to code_info and jump over it
     {
@@ -256,7 +263,7 @@
     // now that we skipped over the prelude, set the ip for the VM
     code_state->ip = ip;
 
-    DEBUG_printf("Calling: n_pos_args=%d, n_kwonly_args=%d\n", self->n_pos_args, self->n_kwonly_args);
-    dump_args(code_state->state + n_state - self->n_pos_args - self->n_kwonly_args, self->n_pos_args + self->n_kwonly_args);
+    DEBUG_printf("Calling: n_pos_args=%d, n_kwonly_args=%d\n", n_pos_args, n_kwonly_args);
+    dump_args(code_state->state + n_state - n_pos_args - n_kwonly_args, n_pos_args + n_kwonly_args);
     dump_args(code_state->state, n_state);
 }