blob: ecdd72dc6dd6bad26a5e08616a217ce301992159 [file] [log] [blame]
Damiend99b0522013-12-21 18:17:45 +00001#include <stdlib.h>
2#include <stdint.h>
3#include <string.h>
4#include <assert.h>
5
6#include "nlr.h"
7#include "misc.h"
8#include "mpconfig.h"
9#include "obj.h"
10#include "runtime.h"
11#include "bc.h"
12
13/******************************************************************************/
14/* generator wrapper */
15
16typedef struct _mp_obj_gen_wrap_t {
17 mp_obj_base_t base;
Damien George0ff88392014-01-02 20:57:05 +000018 uint n_state;
Damiend99b0522013-12-21 18:17:45 +000019 mp_obj_t *fun;
20} mp_obj_gen_wrap_t;
21
22// args are in reverse order in the array
23mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
24 mp_obj_gen_wrap_t *self = self_in;
25 mp_obj_t self_fun = self->fun;
26 assert(MP_OBJ_IS_TYPE(self_fun, &fun_bc_type));
27 int bc_n_args;
28 uint bc_n_state;
29 const byte *bc_code;
30 mp_obj_fun_bc_get(self_fun, &bc_n_args, &bc_n_state, &bc_code);
31 if (n_args != bc_n_args) {
32 nlr_jump(mp_obj_new_exception_msg_2_args(rt_q_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args));
33 }
Damien George6baf76e2013-12-30 22:32:17 +000034
Damien George0ff88392014-01-02 20:57:05 +000035 return mp_obj_new_gen_instance(bc_code, self->n_state, n_args, args);
Damiend99b0522013-12-21 18:17:45 +000036}
37
38const mp_obj_type_t gen_wrap_type = {
39 { &mp_const_type },
40 "generator",
41 NULL, // print
42 gen_wrap_call_n, // call_n
43 NULL, // unary_op
44 NULL, // binary_op
45 NULL, // getiter
46 NULL, // iternext
47 {{NULL, NULL},}, // method list
48};
49
Damien George6baf76e2013-12-30 22:32:17 +000050mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun) {
Damiend99b0522013-12-21 18:17:45 +000051 mp_obj_gen_wrap_t *o = m_new_obj(mp_obj_gen_wrap_t);
52 o->base.type = &gen_wrap_type;
53 // we have at least 3 locals so the bc can write back fast[0,1,2] safely; should improve how this is done
Damien George6baf76e2013-12-30 22:32:17 +000054 o->n_state = (n_locals < 3 ? 3 : n_locals) + n_stack;
Damiend99b0522013-12-21 18:17:45 +000055 o->fun = fun;
56 return o;
57}
58
59/******************************************************************************/
60/* generator instance */
61
62typedef struct _mp_obj_gen_instance_t {
63 mp_obj_base_t base;
Damiend99b0522013-12-21 18:17:45 +000064 const byte *ip;
65 mp_obj_t *sp;
Damien George0ff88392014-01-02 20:57:05 +000066 mp_obj_t state[];
Damiend99b0522013-12-21 18:17:45 +000067} mp_obj_gen_instance_t;
68
69void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
70 print(env, "<generator object 'fun-name' at %p>", self_in);
71}
72
73mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
74 return self_in;
75}
76
77mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
78 mp_obj_gen_instance_t *self = self_in;
Damien George0ff88392014-01-02 20:57:05 +000079 bool yield = mp_execute_byte_code_2(&self->ip, &self->state[0], &self->sp);
Damiend99b0522013-12-21 18:17:45 +000080 if (yield) {
81 return *self->sp;
82 } else {
83 if (*self->sp == mp_const_none) {
84 return mp_const_stop_iteration;
85 } else {
86 // TODO return StopIteration with value *self->sp
87 return mp_const_stop_iteration;
88 }
89 }
90}
91
92const mp_obj_type_t gen_instance_type = {
93 { &mp_const_type },
94 "generator",
95 gen_instance_print, // print
96 NULL, // call_n
97 NULL, // unary_op
98 NULL, // binary_op
99 gen_instance_getiter, // getiter
100 gen_instance_iternext, // iternext
101 {{NULL, NULL},}, // method list
102};
103
Damien George0ff88392014-01-02 20:57:05 +0000104// args are in reverse order in the array
105mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {
106 mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, mp_obj_t, n_state);
Damiend99b0522013-12-21 18:17:45 +0000107 o->base.type = &gen_instance_type;
Damien George0ff88392014-01-02 20:57:05 +0000108 o->ip = bytecode;
109 o->sp = o->state + n_state;
110
111 // copy args (which are in reverse order) to start of state array
112 for (int i = 0; i < n_args; i++) {
113 o->state[i] = args[n_args - 1 - i];
114 }
115
116 // TODO
117 // prelude for making cells (closed over variables)
118 // for now we just make sure there are no cells variables
119 // need to work out how to implement closed over variables in generators
120 assert(o->ip[0] == 0);
121 o->ip += 1;
122
Damiend99b0522013-12-21 18:17:45 +0000123 return o;
124}