-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathnode.cpp
207 lines (189 loc) · 5.78 KB
/
node.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include "node.h"
#include "type.h"
#include "codegen.h"
void Node::clear_def(){
if (def)
def->remove_ref(this);
def=nullptr;;
}
void Node::set_def(ExprDef *d){
if (!d && !def)
return;
if (!def) {
this->next_of_def=d->refs; d->refs=this;
def=d;
}
else {
if (d==0 && this->def){ ASSERT("use clear_def(), not set_def(0)");}
if (d!=this->def){
dbprintf("WARNING!!-was %d %s:%s now %d %s:%s\n",def->pos.line,def->name_str(),def->kind_str(), d->pos.line,d->name_str(),d->kind_str());
// ASSERT(d==this->def);
}
def->remove_ref(this);
def=d;
}
}
void Node::set_struct_type(ExprDef* sd){
if (!this->type())
this->set_type(new Type(sd->as_struct_def()));
if (!this->def)
this->set_def(sd);
}
void Node::set_type(const Type* t)
{ ::verify(t);
if (this->m_type){
if (this->m_type->is_equal(t))
return ;
if (!t){
ASSERT(0 && "use clear type");
}
#if DEBUG>=2
dbprintf("changing type?\n");
this->m_type->dump(-1);newline(0);
dbprintf("to..\n");
t->dump(-1);
newline(0);
#endif
//ASSERT(this->m_type==0);
}
this->m_type=(Type*)t;
};
ExprStructDef* Node::as_struct_def()const{
return nullptr;
};
const char* Node::get_name_str() const{
if (!this) return "(no_type)";
return getString(this->name);
}
RegisterName Node::get_reg_existing(){ASSERT(reg_name); return reg_name;}
RegisterName Node::get_reg(CodeGen& cg, bool force_new){
// variable might be in a local scope shadowing others, so it still needs a unique name
// names are also modified by writes, for llvm SSA
//ASSERT(!on_stack);
if (!reg_name || force_new){
auto old=reg_name;
auto ret= get_reg_new(cg);
return ret;
} else{
return reg_name;
}
}
RegisterName Node::get_reg_new(CodeGen& cg) {
return this->reg_name=cg.next_reg(name);
}
CgValue Node::compile_if(CodeGen& cg, Scope* sc){
if (this)
return this->compile(cg,sc,CgValue());
else
return CgValueVoid();
}
CgValue Node::compile(CodeGen&, Scope*,CgValue in){
error(this,"compile not implemented for %s",this->kind_str());
return in;
}
CgValue Node::compile(CodeGen& cg, Scope* sc){
// most common case is no input value, input is added for 'match' & 'switch'.
return this->compile(cg,sc,CgValue());
}
CgValue Node::compile_operator_new(CodeGen &cg, Scope *sc,const Type* t,const Expr *lhs){
error(this,"operator new not supported for %s",this->kind_str());
return CgValue();
}
CgValue Node::compile_operator_dot(CodeGen &cg, Scope *sc,const Type* t,const Expr *lhs){
error(this,"operator dot not supported for %s",this->kind_str());
return CgValue();
}
CgValue Node::codegen(CodeGen& cg, bool just_contents) {
dbprintf("TODO refactor codegen to use this virtual. warning codegen not implemented for %s\n",this->kind_str());
return CgValue();
}
const Type* any_not_zero(const Type* a, const Type* b){return a?a:b;}
ResolveResult Node::propogate_type_refs(int flags, Type*& a,Type*& b) {
::verify(a,b);
if (!(a || b))
return resolved|=ResolveResult(INCOMPLETE);
if (!a && b) {
a=b;
return resolved|=ResolveResult(COMPLETE);}
else if (!b && a) {
b=a;
return resolved|=ResolveResult(COMPLETE);
}
return resolved|=infer_and_cmp_types(flags,this, a,b);
}
ResolveResult Node::propogate_type_refs(int flags, Expr *n, Type*& a,Type*& b) {
::verify(a,b);
resolved|=n->propogate_type_refs(flags,a,b);
resolved|=n->propogate_type_refs(flags,n->type_ref(),b);
return resolved|=n->propogate_type_refs(flags,n->type_ref(),a);
}
ResolveResult Node::propogate_type_fwd(int flags,const Type* desired,Type*& b) {
::verify(desired,b);
if (!(desired || b))
return resolved|=ResolveResult(INCOMPLETE);
if (!desired && b){
return resolved|=ResolveResult(INCOMPLETE);
}
if (!b && desired) {
b=(Type*)desired;
return resolved|=ResolveResult(COMPLETE);
}
// 'propogate type forward knows what *output* type is needed, so reverse the order here
// to check if 'b' can coerce to desired.
return resolved|=infer_and_cmp_types_rev(flags,this, b,desired);
return ResolveResult(INCOMPLETE);
}
ResolveResult Node::propogate_type_fwd(int flags,Expr* e, const Type*& a) {
return resolved|=e->propogate_type_fwd(flags, a, e->type_ref());
}
ResolveResult Node::propogate_type_expr_ref(int flags,Expr* e, Type*& a) {
return resolved|=e->propogate_type_refs(flags, a, e->type_ref());
}
ResolveResult Node::propogate_type_refs(int flags,Type*& a,Type*& b,Type*& c) {
::verify(a,b,c);
int ret=COMPLETE;
ret|=this->propogate_type_refs(flags,a,b);
ret|=(c)?this->propogate_type_refs(flags,b,c):INCOMPLETE;
ret|=(c)?this->propogate_type_refs(flags,a,c):INCOMPLETE;
return resolved|=ResolveResult(ret);
}
ResolveResult Node::propogate_type_fwd(int flags,const Type*& a,Type*& b,Type*& c) {
::verify(a,b,c);
int ret=COMPLETE;
ret|=propogate_type_fwd(flags,a,b);
ret|=propogate_type_fwd(flags,a,c);
ret|=propogate_type_refs(flags,b,c);
return resolved|=ResolveResult(ret);
}
void ExprDef::remove_ref(Node* ref){
Node** pp=&refs;
Node* p;
auto dbg=[&](){
for (auto r=refs; r; r=r->next_of_def){
dbprintf("ref by %p %s %s %d\n",r, r->kind_str(), str(r->name),r-> pos.line);
}
};
for (p=*pp; p; pp=&p->next_of_def, p=*pp) {
if (p==ref) *pp=p->next_of_def;
}
ref->def=0;
}
Node*
ExprIdent::clone() const {
auto r=new ExprIdent(this->name,this->pos);
r->set_type(this->get_type()); // this is where given tparams live.
r->clear_def(); // def will need re-resolving.
return r;
}
TypeDef* TypeDef::clone()const{
TypeDef* td = new TypeDef(this->pos, this->name);
// todo - clone tparams
td->type_def = (Type*) this->type_def->clone();// actual ->type() will be translated
return td;
}
void TypeDef::dump(PrinterRef depth) const{
newline(depth); dbprintf("%s %s",this->kind_str() ,this->name_str()); dump_tparams(this->tparams,&this->instanced_types); dbprintf("=");
this->type_def->dump(-1);
if (this->type()){dbprintf(":"); this->type()->dump_if(depth);}
dbprintf(";");
}