blob: fea3e7ff077341ea223011ecf8032b3cc6341145 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
Damien39cf3282013-10-05 23:18:38 +010027#include <stdlib.h>
28#include <stdint.h>
Damien39cf3282013-10-05 23:18:38 +010029#include <assert.h>
30
Damiend99b0522013-12-21 18:17:45 +000031#include "mpconfig.h"
Paul Sokolovsky59c675a2014-06-21 22:43:22 +030032#include "misc.h"
Damien George55baff42014-01-21 21:40:13 +000033#include "qstr.h"
Damien39cf3282013-10-05 23:18:38 +010034#include "lexer.h"
Damien39cf3282013-10-05 23:18:38 +010035#include "parse.h"
Damien Georgedf8127a2014-04-13 11:04:33 +010036#include "obj.h"
37#include "emitglue.h"
Damien39cf3282013-10-05 23:18:38 +010038#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000039#include "runtime0.h"
Damien39cf3282013-10-05 23:18:38 +010040#include "emit.h"
41
42struct _emit_t {
Damien39cf3282013-10-05 23:18:38 +010043 scope_t *scope;
44};
45
Damien George35e2a4e2014-02-05 00:51:47 +000046emit_t *emit_pass1_new(void) {
Damien39cf3282013-10-05 23:18:38 +010047 emit_t *emit = m_new(emit_t, 1);
Damien39cf3282013-10-05 23:18:38 +010048 return emit;
49}
50
51void emit_pass1_free(emit_t *emit) {
Damien732407f2013-12-29 19:33:23 +000052 m_del_obj(emit_t, emit);
Damien39cf3282013-10-05 23:18:38 +010053}
54
Paul Sokolovsky520e2f52014-02-12 18:31:30 +020055STATIC void emit_pass1_dummy(emit_t *emit) {
Damien39cf3282013-10-05 23:18:38 +010056}
57
Paul Sokolovsky520e2f52014-02-12 18:31:30 +020058STATIC void emit_pass1_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien George36db6bc2014-05-07 17:24:22 +010059 assert(pass == MP_PASS_SCOPE);
Damien39cf3282013-10-05 23:18:38 +010060 emit->scope = scope;
61}
62
Paul Sokolovsky520e2f52014-02-12 18:31:30 +020063STATIC void emit_pass1_end_pass(emit_t *emit) {
Damien39cf3282013-10-05 23:18:38 +010064}
65
Damien Georgec90717a2014-04-10 15:40:38 +000066STATIC bool emit_pass1_last_emit_was_return_value(emit_t *emit) {
67 return false;
68}
69
Damien George7ff996c2014-09-08 23:05:16 +010070STATIC void emit_pass1_load_id(emit_t *emit, qstr qst) {
Damien39cf3282013-10-05 23:18:38 +010071 // name adding/lookup
72 bool added;
Damien George7ff996c2014-09-08 23:05:16 +010073 id_info_t *id = scope_find_or_add_id(emit->scope, qst, &added);
Damien39cf3282013-10-05 23:18:38 +010074 if (added) {
Damien George35e2a4e2014-02-05 00:51:47 +000075#if MICROPY_EMIT_CPYTHON
Damien George7ff996c2014-09-08 23:05:16 +010076 if (qst == MP_QSTR_super && emit->scope->kind == SCOPE_FUNCTION) {
Damien39cf3282013-10-05 23:18:38 +010077 // special case, super is a global, and also counts as use of __class__
78 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
Damien George35e2a4e2014-02-05 00:51:47 +000079 id_info_t *id2 = scope_find_local_in_parent(emit->scope, MP_QSTR___class__);
Damien39cf3282013-10-05 23:18:38 +010080 if (id2 != NULL) {
Damien George35e2a4e2014-02-05 00:51:47 +000081 id2 = scope_find_or_add_id(emit->scope, MP_QSTR___class__, &added);
Damien39cf3282013-10-05 23:18:38 +010082 if (added) {
83 id2->kind = ID_INFO_KIND_FREE;
Damien George35e2a4e2014-02-05 00:51:47 +000084 scope_close_over_in_parents(emit->scope, MP_QSTR___class__);
Damien39cf3282013-10-05 23:18:38 +010085 }
86 }
Damien George35e2a4e2014-02-05 00:51:47 +000087 } else
88#endif
89 {
Damien George7ff996c2014-09-08 23:05:16 +010090 id_info_t *id2 = scope_find_local_in_parent(emit->scope, qst);
Damien39cf3282013-10-05 23:18:38 +010091 if (id2 != NULL && (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE)) {
92 id->kind = ID_INFO_KIND_FREE;
Damien George7ff996c2014-09-08 23:05:16 +010093 scope_close_over_in_parents(emit->scope, qst);
Damien39cf3282013-10-05 23:18:38 +010094 } else {
95 id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
96 }
97 }
98 }
99}
100
Damien George7ff996c2014-09-08 23:05:16 +0100101STATIC id_info_t *get_id_for_modification(scope_t *scope, qstr qst) {
Damien39cf3282013-10-05 23:18:38 +0100102 // name adding/lookup
103 bool added;
Damien George7ff996c2014-09-08 23:05:16 +0100104 id_info_t *id = scope_find_or_add_id(scope, qst, &added);
Damien39cf3282013-10-05 23:18:38 +0100105 if (added) {
106 if (scope->kind == SCOPE_MODULE || scope->kind == SCOPE_CLASS) {
107 id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
108 } else {
109 id->kind = ID_INFO_KIND_LOCAL;
110 }
111 } else if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
112 // rebind as a local variable
113 id->kind = ID_INFO_KIND_LOCAL;
114 }
115
116 assert(id != NULL); // TODO can this ever fail?
117
118 return id;
119}
120
Damien George7ff996c2014-09-08 23:05:16 +0100121STATIC void emit_pass1_store_id(emit_t *emit, qstr qst) {
122 get_id_for_modification(emit->scope, qst);
Damien39cf3282013-10-05 23:18:38 +0100123}
124
Damien George7ff996c2014-09-08 23:05:16 +0100125STATIC void emit_pass1_delete_id(emit_t *emit, qstr qst) {
126 id_info_t *id = get_id_for_modification(emit->scope, qst);
Damien George6ce42772014-04-12 18:20:40 +0100127 // this flag is unused
128 //id->flags |= ID_FLAG_IS_DELETED;
129 (void)id; // suppress compiler warning
Damien39cf3282013-10-05 23:18:38 +0100130}
131
132const emit_method_table_t emit_pass1_method_table = {
133 (void*)emit_pass1_dummy,
134 emit_pass1_start_pass,
135 emit_pass1_end_pass,
Damien Georgec90717a2014-04-10 15:40:38 +0000136 emit_pass1_last_emit_was_return_value,
Damien39cf3282013-10-05 23:18:38 +0100137 (void*)emit_pass1_dummy,
Damien George08335002014-01-18 23:24:36 +0000138 (void*)emit_pass1_dummy,
Damien39cf3282013-10-05 23:18:38 +0100139
140 emit_pass1_load_id,
141 emit_pass1_store_id,
142 emit_pass1_delete_id,
143
144 (void*)emit_pass1_dummy,
145 (void*)emit_pass1_dummy,
146 (void*)emit_pass1_dummy,
147 (void*)emit_pass1_dummy,
148 (void*)emit_pass1_dummy,
149 (void*)emit_pass1_dummy,
150 (void*)emit_pass1_dummy,
151 (void*)emit_pass1_dummy,
152 (void*)emit_pass1_dummy,
153 (void*)emit_pass1_dummy,
154 (void*)emit_pass1_dummy,
155 (void*)emit_pass1_dummy,
156 (void*)emit_pass1_dummy,
157 (void*)emit_pass1_dummy,
158 (void*)emit_pass1_dummy,
159 (void*)emit_pass1_dummy,
160 (void*)emit_pass1_dummy,
161 (void*)emit_pass1_dummy,
162 (void*)emit_pass1_dummy,
163 (void*)emit_pass1_dummy,
164 (void*)emit_pass1_dummy,
165 (void*)emit_pass1_dummy,
166 (void*)emit_pass1_dummy,
167 (void*)emit_pass1_dummy,
168 (void*)emit_pass1_dummy,
169 (void*)emit_pass1_dummy,
170 (void*)emit_pass1_dummy,
171 (void*)emit_pass1_dummy,
172 (void*)emit_pass1_dummy,
173 (void*)emit_pass1_dummy,
174 (void*)emit_pass1_dummy,
175 (void*)emit_pass1_dummy,
176 (void*)emit_pass1_dummy,
177 (void*)emit_pass1_dummy,
178 (void*)emit_pass1_dummy,
179 (void*)emit_pass1_dummy,
180 (void*)emit_pass1_dummy,
181 (void*)emit_pass1_dummy,
182 (void*)emit_pass1_dummy,
183 (void*)emit_pass1_dummy,
184 (void*)emit_pass1_dummy,
185 (void*)emit_pass1_dummy,
186 (void*)emit_pass1_dummy,
187 (void*)emit_pass1_dummy,
188 (void*)emit_pass1_dummy,
189 (void*)emit_pass1_dummy,
190 (void*)emit_pass1_dummy,
191 (void*)emit_pass1_dummy,
192 (void*)emit_pass1_dummy,
193 (void*)emit_pass1_dummy,
194 (void*)emit_pass1_dummy,
195 (void*)emit_pass1_dummy,
196 (void*)emit_pass1_dummy,
197 (void*)emit_pass1_dummy,
198 (void*)emit_pass1_dummy,
199 (void*)emit_pass1_dummy,
200 (void*)emit_pass1_dummy,
201 (void*)emit_pass1_dummy,
202 (void*)emit_pass1_dummy,
203 (void*)emit_pass1_dummy,
Damien Georgee37dcaa2014-12-27 17:07:16 +0000204 #if MICROPY_PY_BUILTINS_SET
Damien39cf3282013-10-05 23:18:38 +0100205 (void*)emit_pass1_dummy,
206 (void*)emit_pass1_dummy,
Damien Georgee37dcaa2014-12-27 17:07:16 +0000207 #endif
Damien39cf3282013-10-05 23:18:38 +0100208 (void*)emit_pass1_dummy,
209 (void*)emit_pass1_dummy,
210 (void*)emit_pass1_dummy,
211 (void*)emit_pass1_dummy,
212 (void*)emit_pass1_dummy,
213 (void*)emit_pass1_dummy,
214 (void*)emit_pass1_dummy,
215 (void*)emit_pass1_dummy,
216 (void*)emit_pass1_dummy,
217 (void*)emit_pass1_dummy,
218 (void*)emit_pass1_dummy,
Damien Georgeb601d952014-06-30 05:17:25 +0100219
220 (void*)emit_pass1_dummy,
221 (void*)emit_pass1_dummy,
222
Damien George5f6a25f2014-04-20 18:02:27 +0100223#if MICROPY_EMIT_CPYTHON
Damien39cf3282013-10-05 23:18:38 +0100224 (void*)emit_pass1_dummy,
Damien George729f7b42014-04-17 22:10:53 +0100225 (void*)emit_pass1_dummy,
Damien George3558f622014-04-20 17:50:40 +0100226 (void*)emit_pass1_dummy,
Damien George5f6a25f2014-04-20 18:02:27 +0100227#endif
Damien39cf3282013-10-05 23:18:38 +0100228};