A small short PR that enables a `new`-factory to instantiate itself.
previously there was no way to do that. The following code will stack-overflow:
~~~nit
class A
new do
var res = new A
res.do_thigns
return res
end
end
var a = new A # infinite recursion of `new A`
~~~
Note: this is a very bad example as what is done in the previous `new` should be done in an `init` instead since it is related to the initialization of the object. A `new` factory should be exclusively used for some factory-concern like returning a more specialized object or returning an already existing object.
With this PR, the primitive constructor is available and is called `intern`, as the annotation that indicates things that cannot be programmed in Nit but are provided by the execution engine.
So in the previous example, just use this primitive constructor instead of doing a recursive call:
~~~
var res = new A.intern
~~~
This intern constructor just do the allocation and the initialization of attributes with default values.
`init` is not called.
Maybe it should not do the initialization of attributes neither but if I skip them, there is no way for the programmer to ask for them manually. whereas `init` in not automatically called but can be called manually.
note: this PR is a small step toward the conclusion of the constructor saga, more will come soon (I hope)
Pull-Request: #1252
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
var recv = v.init_instance_or_extern(mtype)
- var callsite = self.callsite.as(not null)
+ var callsite = self.callsite
+ if callsite == null then return recv
+
var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
var res2 = v.compile_callsite(callsite, args)
if res2 != null then
var mtype = v.unanchor_type(self.recvtype.as(not null))
var recv: Instance = new MutableInstance(mtype)
v.init_instance(recv)
+ var callsite = self.callsite
+ if callsite == null then return recv
+
var args = v.varargize(callsite.mpropdef, recv, self.n_args.n_exprs)
if args == null then return null
var res2 = v.callsite(callsite, args)
end
self.recvtype = recvtype
+ var kind = recvtype.mclass.kind
var name: String
var nid = self.n_id
else
name = "new"
end
+ if name == "intern" then
+ if kind != concrete_kind then
+ v.error(self, "Type Error: Cannot instantiate {kind} {recvtype}.")
+ return
+ end
+ if n_args.n_exprs.not_empty then
+ v.error(n_args, "Type Error: the intern constructor expects no arguments.")
+ return
+ end
+ # Our job is done
+ self.mtype = recvtype
+ return
+ end
+
var callsite = v.get_method(self, recvtype, name, false)
if callsite == null then return
if not callsite.mproperty.is_new then
- var kind = recvtype.mclass.kind
if kind != concrete_kind then
v.error(self, "Type Error: Cannot instantiate {kind} {recvtype}.")
return
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+ var i: Int
+ new do
+ var res = new A.intern
+ res.i = 1
+ return res
+ end
+ init do
+ 0.output # not called
+ end
+end
+
+var a = new A
+a.i.output