Merge: Named arguments
authorJean Privat <jean@pryen.org>
Sat, 25 Apr 2015 02:19:15 +0000 (09:19 +0700)
committerJean Privat <jean@pryen.org>
Sat, 25 Apr 2015 02:19:15 +0000 (09:19 +0700)
Named arguments allows the caller to specify some subset of arguments it wants to call.
This PR introduce a syntax for callers inspired from the Python one (the Ruby one uses columns that clashes with types declaration).

~~~nit
format(linewidth=80, separator=":", indent=true)
~~~

The specification tries to be as simple as possible

* Only default parameters can be passed by name; because the other are mandatory.
  This restriction is also useful to avoid to specify additional rules, like the last parameter of assignment methods, because the ones on default arguments apply.

~~~nit
fun foo(a,b: nullable Int) do ...
foo(b=1)
foo(null,1) # equivalent
~~~

* Named arguments can appear anywhere (not necessarily at the end)

~~~nit
fun foo(a: Int, b: nulable Int)
foo(b=1,2)
foo(2,1) # equivalent
~~~

* The order of evaluation is the order of the arguments (not the order of the parameters).
  I think this is more POLA this way.

* The names to use are the one of the statically designated method declaration (not the introduction).
  This one is problematic because the language permit the name of parameters to change in redefinitions.
  But in case of errors or in a IDE it is often more useful to point the most precise method definition.

The implementation was trivial because the hard work was already done in the previous PR.

This PR was unlocked by #1280

Pull-Request: #1281
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Etienne M. Gagnon <egagnon@j-meg.com>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>

lib/pthreads/README.md
lib/pthreads/examples/threaded_example.nit
lib/pthreads/pthreads.nit
src/frontend/parallelization_phase.nit
tests/sav/threaded_example.res

index 4a117b4..44f3754 100644 (file)
@@ -12,7 +12,12 @@ This group also provides two optional modules with thread-safe collections:
 Theses services are implemented using the POSIX threads.
 
 You can also use the `is threaded` annotation on methods, which makes them run on their own thread.
-Methods with return value or self calls are not supported.
+Methods with self calls are not supported.
+
+A method or function annotated with `is threaded` has its return value changed during compilation.
+You will get a subclass of `Thread`, even if there wasn't a return value before. You can know if the threaded method is done with the `is_done` boolean from `Thread`.
+A call to the `join` method will block the execution until the threaded method is done, or immediatly return if it's already done.
+`join` will return an object typed with the orginial return type, or `null` if there wasn't.
 
 ## Known limitations:
 
@@ -24,3 +29,4 @@ Methods with return value or self calls are not supported.
 
 * See: `man pthreads`
 * See: `examples/concurrent_array_and_barrier.nit`
+* See: ̀ examples/threaded_example.nit`
index 9a0af4b..fb0609b 100644 (file)
@@ -32,7 +32,17 @@ fun bar(i : Int, s : String) is threaded do
        print s
 end
 
+# Parameterized `threaded` method with a return type
+fun baz(i : Int, j : Int): Int is threaded do
+       sys.nanosleep(10, 0)
+       return i + j
+end
+
+print "main"
 foo
 bar(10, "parameterized and threaded")
-print "main"
 sys.nanosleep(5,0)
+var x  = baz(2, 3)
+print "main, waiting for baz"
+var y = x.join
+print("baz result : " + y.to_s)
index 8b8de1f..afb66d6 100644 (file)
@@ -236,19 +236,26 @@ end
 abstract class Thread
        super Finalizable
 
+       # Type returned by `main`
+       type E : nullable Object
+
        private var native: nullable NativePthread = null
 
+       # Is this thread finished ? True when main returned
+       var is_done = false
+
        # Main method of this thread
        #
        # The returned valued is passed to the caller of `join`.
-       fun main: nullable Object do return null
+       fun main: E do return null
 
-       private fun main_intern: nullable Object
+       private fun main_intern: E
        do
                # Register thread local data
                sys.self_thread_key.set self
-
-               return main
+               var r = main
+               self.is_done = true
+               return r
        end
 
        # Start executing this thread
@@ -266,12 +273,12 @@ abstract class Thread
        # `Sys::thread_exit`. Returns the object returned from the other thread.
        #
        # Stats the thread if now already done by a call to `start`.
-       fun join: nullable Object
+       fun join: E
        do
                if native == null then start
                var r = native.join
                native = null
-               return r
+               return r.as(E)
        end
 
        redef fun finalize
index 2d15d82..08583da 100644 (file)
@@ -42,11 +42,6 @@ private class ParallelizationPhase
 
                #TODO: check for self calls
 
-               if nmethdef.n_signature.n_type != null then
-                       toolcontext.error(nat.location, "Error: functions not supported yet.")
-                       return
-               end
-
                # Get the module associated with this method
                var amod = nmethdef.parent.parent
                assert amod isa AModule
@@ -65,6 +60,18 @@ private class ParallelizationPhase
                        classname += nmethdef.n_methid.as(AIdMethid).n_id.text
                end
 
+               # Handle methods with a return value
+               var has_rvalue = nmethdef.n_signature.n_type != null
+               var vtype = ""
+               if has_rvalue then
+                       vtype = "redef type E: " + nmethdef.n_signature.n_type.n_id.text
+               end
+               # create a return type
+               var n_id = new TClassid
+               n_id.text = classname
+               var n_type = new AType
+               n_type.n_id = n_id
+               nmethdef.n_signature.n_type = n_type
 
                var params = new Array[String]
                # case if the method has parameters
@@ -82,6 +89,8 @@ var {{{param.n_id.text}}} : {{{param.n_type.n_id.text}}}
 class {{{classname}}}
        super Thread
 
+       {{{vtype}}}
+
        {{{params.join("\n")}}}
        redef fun main do
        end
@@ -102,11 +111,12 @@ end
                mainfun.n_block = nmethdef.n_block
 
                # Add "return null" to the end of the `main` function
-               var s_nullreturn = "return null"
-               var nullreturn = toolcontext.parse_something(s_nullreturn)
-               assert nullreturn isa AExpr
-               mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
-
+               if not has_rvalue then
+                       var s_nullreturn = "return null"
+                       var nullreturn = toolcontext.parse_something(s_nullreturn)
+                       assert nullreturn isa AExpr
+                       mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
+               end
 
                # Create new body for the annotated fun
                var s_newbody : String
@@ -118,11 +128,13 @@ end
                        s_newbody ="""
 var thread = new {{{classname}}}({{{init_params.join(",")}}})
 thread.start
+return thread
 """
                else
                        s_newbody = """
 var thread = new {{{classname}}}
 thread.start
+return thread
 """
                end
 
index e90aa48..4f1025c 100644 (file)
@@ -2,3 +2,5 @@ main
 threaded
 10
 parameterized and threaded
+main, waiting for baz
+baz result : 5