blob: 2f0ecac86dcb98367ce8e2afdeca9a2d88dd6c6f [file] [log] [blame]
Damien39cf3282013-10-05 23:18:38 +01001#include <unistd.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6#include <assert.h>
7
8#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
Damien George71c51812014-01-04 20:21:15 +000010#include "mpqstr.h"
Damien39cf3282013-10-05 23:18:38 +010011#include "lexer.h"
Damien39cf3282013-10-05 23:18:38 +010012#include "parse.h"
Damien39cf3282013-10-05 23:18:38 +010013#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000014#include "runtime0.h"
Damien39cf3282013-10-05 23:18:38 +010015#include "emit.h"
16
17struct _emit_t {
18 qstr qstr___class__;
19 scope_t *scope;
20};
21
22emit_t *emit_pass1_new(qstr qstr___class__) {
23 emit_t *emit = m_new(emit_t, 1);
24 emit->qstr___class__ = qstr___class__;
25 return emit;
26}
27
28void emit_pass1_free(emit_t *emit) {
Damien732407f2013-12-29 19:33:23 +000029 m_del_obj(emit_t, emit);
Damien39cf3282013-10-05 23:18:38 +010030}
31
32static void emit_pass1_dummy(emit_t *emit) {
33}
34
35static void emit_pass1_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
36 assert(pass == PASS_1);
37 emit->scope = scope;
38}
39
40static void emit_pass1_end_pass(emit_t *emit) {
41}
42
43static void emit_pass1_load_id(emit_t *emit, qstr qstr) {
44 // name adding/lookup
45 bool added;
46 id_info_t *id = scope_find_or_add_id(emit->scope, qstr, &added);
47 if (added) {
Damien George71c51812014-01-04 20:21:15 +000048 if (qstr == MP_QSTR_AssertionError) {
Damien39cf3282013-10-05 23:18:38 +010049 // TODO how much of a hack is this?
Damien George71c51812014-01-04 20:21:15 +000050 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
Damien39cf3282013-10-05 23:18:38 +010051 } else if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) {
52 // special case, super is a global, and also counts as use of __class__
53 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
54 id_info_t *id2 = scope_find_local_in_parent(emit->scope, emit->qstr___class__);
55 if (id2 != NULL) {
56 id2 = scope_find_or_add_id(emit->scope, emit->qstr___class__, &added);
57 if (added) {
58 id2->kind = ID_INFO_KIND_FREE;
59 scope_close_over_in_parents(emit->scope, emit->qstr___class__);
60 }
61 }
62 } else {
63 id_info_t *id2 = scope_find_local_in_parent(emit->scope, qstr);
64 if (id2 != NULL && (id2->kind == ID_INFO_KIND_LOCAL || id2->kind == ID_INFO_KIND_CELL || id2->kind == ID_INFO_KIND_FREE)) {
65 id->kind = ID_INFO_KIND_FREE;
66 scope_close_over_in_parents(emit->scope, qstr);
67 } else {
68 id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
69 }
70 }
71 }
72}
73
74static id_info_t *get_id_for_modification(scope_t *scope, qstr qstr) {
75 // name adding/lookup
76 bool added;
77 id_info_t *id = scope_find_or_add_id(scope, qstr, &added);
78 if (added) {
79 if (scope->kind == SCOPE_MODULE || scope->kind == SCOPE_CLASS) {
80 id->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
81 } else {
82 id->kind = ID_INFO_KIND_LOCAL;
83 }
84 } else if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
85 // rebind as a local variable
86 id->kind = ID_INFO_KIND_LOCAL;
87 }
88
89 assert(id != NULL); // TODO can this ever fail?
90
91 return id;
92}
93
94static void emit_pass1_store_id(emit_t *emit, qstr qstr) {
95 get_id_for_modification(emit->scope, qstr);
96}
97
98static void emit_pass1_delete_id(emit_t *emit, qstr qstr) {
99 get_id_for_modification(emit->scope, qstr);
100}
101
102const emit_method_table_t emit_pass1_method_table = {
103 (void*)emit_pass1_dummy,
104 emit_pass1_start_pass,
105 emit_pass1_end_pass,
106 (void*)emit_pass1_dummy,
107 (void*)emit_pass1_dummy,
108 (void*)emit_pass1_dummy,
109
110 emit_pass1_load_id,
111 emit_pass1_store_id,
112 emit_pass1_delete_id,
113
114 (void*)emit_pass1_dummy,
115 (void*)emit_pass1_dummy,
116 (void*)emit_pass1_dummy,
117 (void*)emit_pass1_dummy,
118 (void*)emit_pass1_dummy,
119 (void*)emit_pass1_dummy,
120 (void*)emit_pass1_dummy,
121 (void*)emit_pass1_dummy,
122 (void*)emit_pass1_dummy,
123 (void*)emit_pass1_dummy,
124 (void*)emit_pass1_dummy,
125 (void*)emit_pass1_dummy,
126 (void*)emit_pass1_dummy,
127 (void*)emit_pass1_dummy,
128 (void*)emit_pass1_dummy,
129 (void*)emit_pass1_dummy,
130 (void*)emit_pass1_dummy,
131 (void*)emit_pass1_dummy,
132 (void*)emit_pass1_dummy,
133 (void*)emit_pass1_dummy,
134 (void*)emit_pass1_dummy,
135 (void*)emit_pass1_dummy,
136 (void*)emit_pass1_dummy,
137 (void*)emit_pass1_dummy,
138 (void*)emit_pass1_dummy,
139 (void*)emit_pass1_dummy,
140 (void*)emit_pass1_dummy,
141 (void*)emit_pass1_dummy,
142 (void*)emit_pass1_dummy,
143 (void*)emit_pass1_dummy,
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,
Damien39cf3282013-10-05 23:18:38 +0100190};