From: Jean Privat Date: Fri, 10 Apr 2015 15:19:40 +0000 (+0700) Subject: Merge: Sys is top X-Git-Tag: v0.7.4~31 X-Git-Url: http://nitlanguage.org?ds=sidebyside;hp=-c Merge: Sys is top And when I say *top* I mean *great*. But I also mean *top* in fact. The idea is to move the top-level methods (those defined outside classes) from Object to Sys. While this is a cosmetic move, it has a lot of benefits: * top-level methods get a real meaningful receiver: the current system. It is meaningful both on the declaration side and the call side. * no more need to distinguish the concept of top-level methods with their rules and semantic, so this simplify the language with one less thing (almost, see bellow) * self is now usable in top-level methods, not that useful now because it is `sys`, a singleton, but this allow some kind of inheritance if you add super-classes to Sys. * no more name conflicts between a standard class method and a top-level method * no more useless slots in table of classes for crazy methods defined in Object and never redefined * close #461 and close #1081 by making them irrelevant * Let us see a bright future where the singleton Sys become a multiton and allow specific isolation of computation. Specific Sys will then be active objects (threads, computation node, actors, whatever) isolated with their own specific cloud of objects and efficient lock-less concurrency, dedicated memory model (realtime?), and why not transparent distribution There is still two drawbacks * what is the status of `sys` that represent the current `Sys`? I hard-coded it to stay a method in Object. One way to solve the probem is to make it a keyword (like `self`) * when doing `foo(x)`, first this tries `self.foo(x)` then `sys.foo(x)` thus this is some additional rule of the language. Pull-Request: #1249 Reviewed-by: Alexis Laferrière Reviewed-by: Alexandre Terrasa Reviewed-by: Lucas Bajolet --- 2ef74df2c2b1eb3e370b1dc6a59307fae07e1ee0 diff --combined src/interpreter/naive_interpreter.nit index c847b5f,7e1c9db..4cab2e5 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@@ -1001,11 -1001,11 +1001,11 @@@ redef class AMethPropde else if pname == "file_exists" then return v.bool_instance(recvval.to_s.file_exists) else if pname == "file_mkdir" then - recvval.to_s.mkdir - return null + var res = recvval.to_s.mkdir + return v.bool_instance(res == null) else if pname == "file_chdir" then - recvval.to_s.chdir - return null + var res = recvval.to_s.chdir + return v.bool_instance(res == null) else if pname == "file_realpath" then return v.native_string_instance(recvval.to_s.realpath) else if pname == "get_environ" then @@@ -1273,16 -1273,14 +1273,16 @@@ redef class ABlockExp end redef class AVardeclExpr - redef fun stmt(v) + redef fun expr(v) do var ne = self.n_expr if ne != null then var i = v.expr(ne) - if i == null then return + if i == null then return null v.write_variable(self.variable.as(not null), i) + return i end + return null end end @@@ -1323,6 -1321,14 +1323,14 @@@ redef class ASelfExp end end + redef class AImplicitSelfExpr + redef fun expr(v) + do + if not is_sys then return super + return v.mainobj + end + end + redef class AEscapeExpr redef fun stmt(v) do @@@ -1467,19 -1473,6 +1475,19 @@@ redef class AForExp end end +redef class AWithExpr + redef fun stmt(v) + do + var expr = v.expr(self.n_expr) + if expr == null then return + + v.callsite(method_start, [expr]) + v.stmt(self.n_block) + v.is_escape(self.break_mark) # Clear the break + v.callsite(method_finish, [expr]) + end +end + redef class AAssertExpr redef fun stmt(v) do diff --combined src/semantize/typing.nit index cf8bbda,940f67e..e51269f --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@@ -52,6 -52,7 +52,7 @@@ private class TypeVisito # Is `self` use restricted? # * no explicit `self` # * method called on the implicit self must be top-level + # Currently only used for `new` factory since there is no valid receiver inside var is_toplevel_context = false init @@@ -71,7 -72,7 +72,7 @@@ selfvariable.declared_type = mclass.mclass_type var mprop = mpropdef.mproperty - if mprop isa MMethod and (mprop.is_toplevel or mprop.is_new) then + if mprop isa MMethod and mprop.is_new then is_toplevel_context = true end end @@@ -748,7 -749,6 +749,7 @@@ redef class AVardeclExp #debug("var {variable}: {mtype}") + self.mtype = mtype self.is_typed = true end end @@@ -1107,24 -1107,6 +1108,24 @@@ redef class AForExp end end +redef class AWithExpr + var method_start: nullable CallSite + var method_finish: nullable CallSite + + redef fun accept_typing(v: TypeVisitor) + do + var mtype = v.visit_expr(n_expr) + if mtype == null then return + + method_start = v.get_method(self, mtype, "start", n_expr isa ASelfExpr) + method_finish = v.get_method(self, mtype, "finish", n_expr isa ASelfExpr) + + v.visit_stmt(n_block) + self.mtype = n_block.mtype + self.is_typed = true + end +end + redef class AAssertExpr redef fun accept_typing(v) do @@@ -1460,6 -1442,15 +1461,15 @@@ redef class ASelfExp end end + redef class AImplicitSelfExpr + # Is the implicit receiver `sys`? + # + # By default, the implicit receiver is `self`. + # But when there is not method for `self`, `sys` is used as a fall-back. + # Is this case this flag is set to `true`. + var is_sys = false + end + ## MESSAGE SENDING AND PROPERTY redef class ASendExpr @@@ -1468,13 -1459,38 +1478,38 @@@ redef fun accept_typing(v) do - var recvtype = v.visit_expr(self.n_expr) + var nrecv = self.n_expr + var recvtype = v.visit_expr(nrecv) var name = self.property_name if recvtype == null then return # Forward error - var callsite = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr) - if callsite == null then return + var callsite = null + var unsafe_type = v.anchor_to(recvtype) + var mproperty = v.try_get_mproperty_by_name2(self, unsafe_type, name) + if mproperty == null and nrecv isa AImplicitSelfExpr then + # Special fall-back search in `sys` when noting found in the implicit receiver. + var sysclass = v.try_get_mclass(self, "Sys") + if sysclass != null then + var systype = sysclass.mclass_type + mproperty = v.try_get_mproperty_by_name2(self, systype, name) + if mproperty != null then + callsite = v.get_method(self, systype, name, false) + if callsite == null then return # Forward error + # Update information, we are looking at `sys` now, not `self` + nrecv.is_sys = true + nrecv.its_variable = null + nrecv.mtype = systype + recvtype = systype + end + end + end + if callsite == null then + # If still nothing, just exit + callsite = v.get_method(self, recvtype, name, nrecv isa ASelfExpr) + if callsite == null then return + end + self.callsite = callsite var msignature = callsite.msignature diff --combined tests/sav/nitlight_args1.res index 8b7dbb3,c5a6adb..570c986 --- a/tests/sav/nitlight_args1.res +++ b/tests/sav/nitlight_args1.res @@@ -16,52 -16,52 +16,52 @@@ import end -interface Object +interface Object end -enum Bool +enum Bool end -enum Int +enum Int fun output is intern end -class A - init do 5.output - fun run do 6.output +class A + init do 5.output + fun run do 6.output end -class B - var val: Int - init(v: Int) +class B + var val: Int + init(v: Int) do - 7.output - self.val = v + 7.output + self.val = v end - fun run do val.output + fun run do val.output end -class C - var val1: Int - var val2: Int = 10 +class C + var val1: Int + var val2: Int = 10 end - fun foo do 2.output - fun bar(i: Int) do i.output - fun baz: Int do return 4 -fun foo do 2.output -fun bar(i: Int) do i.output -fun baz: Int do return 4 ++fun foo do 2.output ++fun bar(i: Int) do i.output ++fun baz: Int do return 4 -1.output -foo -bar(3) -baz.output +1.output +foo +bar(3) +baz.output -var a = new A -a.run +var a = new A +a.run -var b = new B(8) -b.run +var b = new B(8) +b.run -var c = new C(9) -c.val1.output -c.val2.output +var c = new C(9) +c.val1.output +c.val2.output