1 //
2 // Copyright (c) 2006, Brian Frank and Andy Frank
3 // Licensed under the Academic Free License version 3.0
4 //
5 // History:
6 // 15 Sep 05 Brian Frank Creation
7 // 19 Jul 06 Brian Frank Ported from Java to Fan
8 //
9
10 **
11 ** MethodDef models a method definition - it's signature and body.
12 **
13 class MethodDef : SlotDef, CMethod
14 {
15
16 //////////////////////////////////////////////////////////////////////////
17 // Construction
18 //////////////////////////////////////////////////////////////////////////
19
20 public static MethodDef makeStaticInit(Location location, TypeDef parent, Block block)
21 {
22 def := make(location, parent)
23 def.name = "static\$init"
24 def.flags = FConst.Public | FConst.Static | FConst.Synthetic
25 def.ret = parent.ns.voidType
26 def.code = block
27 return def;
28 }
29
30 public static MethodDef makeInstanceInit(Location location, TypeDef parent, Block block)
31 {
32 def := make(location, parent)
33 def.name = "instance\$init";
34 def.flags = FConst.Public | FConst.Synthetic
35 def.ret = parent.ns.voidType
36 def.code = block
37 return def;
38 }
39
40 new make(Location location, TypeDef parent)
41 : super(location, parent)
42 {
43 paramDefs = ParamDef[,]
44 vars = MethodVar[,]
45 needsCvars = false
46 }
47
48 //////////////////////////////////////////////////////////////////////////
49 // Methods
50 //////////////////////////////////////////////////////////////////////////
51
52 **
53 ** Return if this a static initializer block.
54 **
55 Bool isStaticInit() { return name == "static\$init" }
56 static Bool isNameStaticInit(Str name) { return name == "static\$init" }
57
58 **
59 ** Return if this a instance initializer block.
60 **
61 Bool isInstanceInit() { return name == "instance\$init" }
62 static Bool isNameInstanceInit(Str name) { return name == "instance\$init" }
63
64 **
65 ** Return if getter/setter for FieldDef
66 **
67 Bool isFieldAccessor()
68 {
69 return accessorFor != null
70 }
71
72 **
73 ** Make and add a MethodVar for a local variable. If name is
74 ** null then we auto-generate a temporary variable name
75 **
76 MethodVar addLocalVar(CType ctype, Str name, Block scope)
77 {
78 // allocate next register index, implicit this always register 0
79 reg := vars.size
80 if (!isStatic) reg++
81
82 // auto-generate name
83 if (name == null) name = "\$temp" + reg
84
85 // create variable and add it variable list
86 var := MethodVar.make(reg, ctype, name, 0, scope)
87 vars.add(var)
88 return var
89 }
90
91 //////////////////////////////////////////////////////////////////////////
92 // CMethod
93 //////////////////////////////////////////////////////////////////////////
94
95 override Str signature()
96 {
97 return qname + "(" + params.join(",") + ")"
98 }
99
100 override CType returnType()
101 {
102 return ret
103 }
104
105 override CType inheritedReturnType()
106 {
107 if (inheritedRet != null)
108 return inheritedRet
109 else
110 return ret
111 }
112
113 override CParam[] params()
114 {
115 return paramDefs
116 }
117
118 //////////////////////////////////////////////////////////////////////////
119 // Tree
120 //////////////////////////////////////////////////////////////////////////
121
122 override Void walk(Visitor v, VisitDepth depth)
123 {
124 v.enterMethodDef(this)
125 walkFacets(v, depth)
126 if (depth >= VisitDepth.stmt)
127 {
128 if (depth >= VisitDepth.expr)
129 {
130 if (ctorChain != null) ctorChain = (CallExpr)ctorChain.walk(v)
131 paramDefs.each |ParamDef p| { if (p.def != null) p.def = p.def.walk(v) }
132 }
133 if (code != null) code.walk(v, depth)
134 }
135 v.visitMethodDef(this)
136 v.exitMethodDef(this)
137 }
138
139 //////////////////////////////////////////////////////////////////////////
140 // Debug
141 //////////////////////////////////////////////////////////////////////////
142
143 override Str toStr()
144 {
145 return "$ret $name(" + params.join(",") + ")"
146 }
147
148 override Void print(AstWriter out)
149 {
150 printFacets(out)
151 out.flags(flags).w(ret).w(" ").w(name).w("(")
152 paramDefs.each |ParamDef p, Int i|
153 {
154 if (i > 0) out.w(", ")
155 p.print(out)
156 }
157 out.w(")").nl
158
159 if (ctorChain != null) { out.w(" : "); ctorChain.print(out); out.nl }
160
161 if (code != null) code.print(out)
162 out.nl
163 }
164
165 //////////////////////////////////////////////////////////////////////////
166 // Fields
167 //////////////////////////////////////////////////////////////////////////
168
169 CType ret // return type
170 CType inheritedRet // used for original return if covariant
171 ParamDef[] paramDefs // parameter definitions
172 Block code // code block
173 CallExpr ctorChain // constructor chain for this/super ctor
174 MethodVar[] vars // all param/local variables in method
175 FieldDef accessorFor // if accessor method for field
176 Bool needsCvars // does this method have locals used inside closures
177
178 }