-
Notifications
You must be signed in to change notification settings - Fork 3
/
visitors.d
113 lines (105 loc) · 3.85 KB
/
visitors.d
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
// Written in the D programming language
// Author: Timon Gehr
// License: http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0
template IsNonASTType(T){
enum IsNonASTType =
is(T==Symbol)||
is(T==TemplateInstanceDecl)||
is(T==ExpTuple)||
is(T==TypeTuple)||
is(T==PtrExp)||
is(T==LengthExp);
}
mixin template Visitors(){
// workaround for DMD bug: Interpret goes first
/*static if(is(typeof({mixin Semantic!(typeof(this));})))*/
static if(is(typeof(this):Expression)&&!is(typeof(this):Type)) mixin Interpret!(typeof(this));// TODO: minimize and report bug
static assert(is(TypeTuple==class));
static if(!IsNonASTType!(typeof(this))) mixin Semantic!(typeof(this));
// another workaround for DMD bug, other part is in expression.Node
static if(!is(typeof(this)==Node)){
static if(!is(typeof(this)==AggregateTy)){
mixin Analyze; // wtf?
mixin CTFEInterpret!(typeof(this));
}
static if(!is(typeof(this)==AggregateTy)) mixin DeepDup!(typeof(this));
}
//static if(is(typeof(this)==Node))
}
import expression,declaration,type;
mixin template DeepDup(T) if(is(T: BasicType)){
override @trusted inout(T) sdup()inout{ return this; }
override @trusted inout(T) ddup()inout{ return this; }
}
mixin template DeepDup(T) if(is(T: Node) && !is(T: BasicType)){
mixin((!is(T==Node)?"override ":"")~q{
@trusted inout(T) ddup()inout{
static if(is(T:Type) && !is(T:FunctionTy)){
if(sstate==SemState.completed) return this;
assert(sstate == SemState.begin);
}
auto res=cast(T)sdup();
static if(is(T==VarDecl)){
if(init_)
if(auto tmp=(cast()init_).isTemporaryExp()){
assert(!tmp.tmpVarDecl||tmp.tmpVarDecl is this);
auto otmp = tmp.tmpVarDecl;
tmp.tmpVarDecl = null;
auto n = tmp.ddup();
n.tmpVarDecl = otmp;
res.init_ = n;
}
}
foreach(x;__traits(allMembers, T)){
static if(x.length && (!is(T:Symbol)||x!="meaning" && x!="circ" && x!="clist") && x!="ctfeCallWrapper" && (!is(T==TemplateInstanceExp)||x!="eponymous"&&x!="inst")&&(!is(T==VarDecl)||x!="tupleContext") && (!is(T==TemplateInstanceDecl)||x!="eponymousDecl"&&x!="constraintEponymousFunctionParameters") && (!is(T:TemporaryExp)||x!="tmpVarDecl") && (!is(T:AliasDecl)||x!="set")){ // hack
static if(is(typeof(*mixin("&res."~x)) S) &&
!is(S:immutable(S))){
static if(is(S:const(Node))){
static if(!is(T==FunctionTy)||!is(S==FunctionTy))
mixin("if(res."~x~" !is null) res."~x~"=res."~x~".ddup();");
}else static if(is(typeof(*mixin("&res."~x)):const(Node)[])){
mixin("res."~x~"=res."~x~".dup;");
static if((!is(T==ReferenceAggregateDecl)||x!="parents"))
foreach(ref e;mixin("res."~x)) if(e!is null) e=e.ddup();
}
}
}// else{ import std.stdio; writeln("not copying "~T.stringof,".",x);}
}
static if(is(T==FunctionTy)){
res.clearCaches();// TODO: clearCaches is not good enough
}
return *cast(inout(T)*)&res;
}}~(!is(T==Node)?
q{override @trusted inout(T) sdup()inout{
enum siz = __traits(classInstanceSize,T);
auto data = New!(void[])(siz);
import std.c.string;
memcpy(data.ptr, cast(void*)this, siz);
return cast(inout(T))data.ptr;
}}:""));
}
mixin template DeepDup(T: StaticIfDecl) if(is(T==StaticIfDecl)){
override @trusted inout(T) ddup()inout{
assert(sstate==SemState.begin||sstate==SemState.pre);
enum siz = __traits(classInstanceSize,T);
auto data = New!(void[])(siz);
import std.c.string;
memcpy(data.ptr, cast(void*)this, siz);
auto res = cast(T)data.ptr;
res.lazyDup = true;
res.cond = res.cond.ddup();
return cast(inout)res;
}
}
import semantic;
mixin template DeepDup(T: Symbol) {
override @trusted inout(T) ddup()inout{
enum siz = __traits(classInstanceSize,T);
auto data = New!(void[])(siz);
import std.c.string;
memcpy(data.ptr, cast(void*)this, siz);
auto res = cast(T)data.ptr;
if(isFunctionLiteral) res.meaning = res.meaning.ddup;
return cast(inout)res;
}
}