Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[dotnet] This does the core of the multi-dispatch switch. Rip out the…

… old separate candidate list storage. Store multi candidates in the dispatch routine's dispatchees slot (instantiations for nested scopes NYI, though). Use nearest outer dispatch list when entering the multi dispatcher, tossing all the slow and failure-prone named lookup stuff. Update NQPSetting to not pass the name along to the dispatcher entry call. This passes all tests we did before. \o/
  • Loading branch information...
commit 2ad10c2d03b518868ef03d9ad7101d368da68285 1 parent e455223
Jonathan Worthington authored October 30, 2010
14  common/NQP/NQPSetting.pm
@@ -152,7 +152,7 @@ knowhow NQPCode is repr('RakudoCodeRef') {
152 152
 ## XXX Need coercive Any fallbacks too.
153 153
 
154 154
 proto sub &infix:<==>($x, $y) {
155  
-    nqp::multi_dispatch_over_lexical_candidates("&infix:<==>");
  155
+    nqp::multi_dispatch_over_lexical_candidates();
156 156
 }
157 157
 multi sub &infix:<==>(NQPInt $x, NQPInt $y) {
158 158
     nqp::equal_ints($x, $y)
@@ -162,7 +162,7 @@ multi sub &infix:<==>(NQPNum $x, NQPNum $y) {
162 162
 }
163 163
 
164 164
 proto sub &infix:<!=>($x, $y) {
165  
-    nqp::multi_dispatch_over_lexical_candidates("&infix:<!=>");
  165
+    nqp::multi_dispatch_over_lexical_candidates();
166 166
 }
167 167
 multi sub &infix:<!=>(NQPInt $x, NQPInt $y) {
168 168
     nqp::logical_not_int(nqp::equal_ints($x, $y))
@@ -200,35 +200,35 @@ sub &prefix:<+>($x) {
200 200
 }
201 201
 
202 202
 proto sub &infix:<+>($x, $y) {
203  
-    nqp::multi_dispatch_over_lexical_candidates("&infix:<+>");
  203
+    nqp::multi_dispatch_over_lexical_candidates();
204 204
 }
205 205
 multi sub &infix:<+>(NQPInt $x, NQPInt $y) {
206 206
     nqp::add_int($x, $y);
207 207
 }
208 208
 
209 209
 proto sub &infix:<->($x, $y) {
210  
-    nqp::multi_dispatch_over_lexical_candidates("&infix:<->");
  210
+    nqp::multi_dispatch_over_lexical_candidates();
211 211
 }
212 212
 multi sub &infix:<->(NQPInt $x, NQPInt $y) {
213 213
     nqp::sub_int($x, $y);
214 214
 }
215 215
 
216 216
 proto sub &infix:<*>($x, $y) {
217  
-    nqp::multi_dispatch_over_lexical_candidates("&infix:<*>");
  217
+    nqp::multi_dispatch_over_lexical_candidates();
218 218
 }
219 219
 multi sub &infix:<*>(NQPInt $x, NQPInt $y) {
220 220
     nqp::mul_int($x, $y);
221 221
 }
222 222
 
223 223
 proto sub &infix:</>($x, $y) {
224  
-    nqp::multi_dispatch_over_lexical_candidates("&infix:</>");
  224
+    nqp::multi_dispatch_over_lexical_candidates();
225 225
 }
226 226
 multi sub &infix:</>(NQPInt $x, NQPInt $y) {
227 227
     nqp::div_int($x, $y);
228 228
 }
229 229
 
230 230
 proto sub &infix:<%>($x, $y) {
231  
-    nqp::multi_dispatch_over_lexical_candidates("&infix:<%>");
  231
+    nqp::multi_dispatch_over_lexical_candidates();
232 232
 }
233 233
 multi sub &infix:<%>(NQPInt $x, NQPInt $y) {
234 234
     nqp::mod_int($x, $y);
46  dotnet/compiler/Actions.pm
@@ -493,50 +493,44 @@ method routine_def($/) {
493 493
         $past.name($name);
494 494
         if $*SCOPE eq '' || $*SCOPE eq 'my' {
495 495
             if $*MULTINESS eq 'multi' {
496  
-                my $chname := '!' ~ $name ~ '-candidates';
497  
-                my $cholder;
498 496
                 # Does the current block have a candidate holder in place?
499  
-                my %sym := @BLOCK[0].symbol($chname);
500  
-                if %sym {
  497
+                my $cholder;
  498
+                my %sym := @BLOCK[0].symbol($name);
  499
+                if %sym<cholder> {
501 500
                     $cholder := %sym<cholder>;
502 501
                 }
503 502
                 
504 503
                 # Otherwise, no candidate holder, so add one.
505 504
                 else {
506 505
                     # Check we have a proto in scope.
507  
-                    my $found := 0;
508  
-                    for @BLOCK {
509  
-                        my %sym := $_.symbol($name);
510  
-                        if %sym {
511  
-                            if %sym<proto> {
512  
-                                $found := 1;
513  
-                                last;
514  
-                            }
515  
-                            else {
516  
-                                $/.CURSOR.panic("multi cannot be declared when only in scope");
517  
-                            }
518  
-                        }
519  
-                    }
520  
-                    unless $found {
521  
-                        $/.CURSOR.panic("multi cannot be declared without a proto in scope");
  506
+                    # XXX We need to get the proto clone from outer in place
  507
+                    # but for now just handle it being in the same block.
  508
+                    unless %sym<proto> {
  509
+                        $/.CURSOR.panic("Sorry, can only declare multis in the same block as a proto so far");
522 510
                     }
523 511
 
524 512
                     # Valid to add a candidate holder, so do so.
525  
-                    $cholder := PAST::Op.new(
526  
-                        :pasttype('call'), :name('list'),
527  
-                    );
528  
-                    @BLOCK[0][0].push(PAST::Var.new( :name($chname), :isdecl(1),
529  
-                                      :viviself($cholder), :scope('lexical') ) );
530  
-                    @BLOCK[0].symbol($chname, :cholder($cholder) );
  513
+                    $cholder := PAST::Op.new( :pasttype('list') );
  514
+                    @BLOCK[0][0].push(PAST::Op.new(
  515
+                        :pasttype('nqpop'), :name('set_dispatchees'),
  516
+                        PAST::Var.new( :name($name) ),
  517
+                        $cholder
  518
+                    ));
  519
+                    @BLOCK[0].symbol($name, :cholder($cholder));
531 520
                 }
532 521
 
533 522
                 # Add this candidate to the holder.
534 523
                 $cholder.push($past);
535 524
             }
  525
+            elsif $*MULTINESS eq 'proto' {
  526
+                @BLOCK[0][0].push(PAST::Var.new( :name($name), :isdecl(1),
  527
+                                      :viviself($past), :scope('lexical') ) );
  528
+                @BLOCK[0].symbol($name, :scope('lexical'), :proto(1) );
  529
+            }
536 530
             else {
537 531
                 @BLOCK[0][0].push(PAST::Var.new( :name($name), :isdecl(1),
538 532
                                       :viviself($past), :scope('lexical') ) );
539  
-                @BLOCK[0].symbol($name, :scope('lexical'), :proto($*MULTINESS eq 'proto') );
  533
+                @BLOCK[0].symbol($name, :scope('lexical') );
540 534
             }
541 535
             $past := PAST::Var.new( :name($name) );
542 536
         }
1  dotnet/runtime/Rakudo.Net.csproj
@@ -74,7 +74,6 @@
74 74
     <Compile Include="Runtime\CaptureHelper.cs" />
75 75
     <Compile Include="Runtime\Lexpad.cs" />
76 76
     <Compile Include="Runtime\MultiDispatch\DispatchCache.cs" />
77  
-    <Compile Include="Runtime\MultiDispatch\LexicalCandidateFinder.cs" />
78 77
     <Compile Include="Runtime\MultiDispatch\MultiDispatcher.cs" />
79 78
     <Compile Include="Runtime\Ops.cs" />
80 79
     <Compile Include="Properties\AssemblyInfo.cs" />
43  dotnet/runtime/Runtime/MultiDispatch/LexicalCandidateFinder.cs
... ...
@@ -1,43 +0,0 @@
1  
-using System;
2  
-using System.Collections.Generic;
3  
-using System.Linq;
4  
-using System.Text;
5  
-using Rakudo.Metamodel;
6  
-using Rakudo.Metamodel.Representations;
7  
-
8  
-namespace Rakudo.Runtime.MultiDispatch
9  
-{
10  
-    /// <summary>
11  
-    /// Finds all candidates that we may dispatch to.
12  
-    /// </summary>
13  
-    public static class LexicalCandidateFinder
14  
-    {
15  
-        /// <summary>
16  
-        /// Locates all matching candidates between the two scopes.
17  
-        /// </summary>
18  
-        /// <param name="FromScope"></param>
19  
-        /// <param name="ToScope"></param>
20  
-        /// <param name="Name"></param>
21  
-        /// <returns></returns>
22  
-        public static List<RakudoCodeRef.Instance> FindCandidates(Context CallerScope, Context ProtoScope, string CandidateHolderName)
23  
-        {
24  
-            var Result = new List<RakudoCodeRef.Instance>();
25  
-            Context CurScope = null;
26  
-            do
27  
-            {
28  
-                // Get the next outer scope, or alternatively start off with the
29  
-                // caller scope.
30  
-                CurScope = CurScope == null ? CallerScope : CurScope.Outer;
31  
-                if (CurScope == null)
32  
-                    break;
33  
-
34  
-                // Any candidates here?
35  
-                int Index;
36  
-                if (CurScope.LexPad.SlotMapping != null && CurScope.LexPad.SlotMapping.TryGetValue(CandidateHolderName, out Index))
37  
-                    foreach (var Candidate in (CurScope.LexPad.Storage[Index] as P6list.Instance).Storage)
38  
-                        Result.Add(Candidate as RakudoCodeRef.Instance);
39  
-            } while (CurScope != ProtoScope);
40  
-            return Result;
41  
-        }
42  
-    }
43  
-}
8  dotnet/runtime/Runtime/MultiDispatch/MultiDispatcher.cs
@@ -20,7 +20,7 @@ public static class MultiDispatcher
20 20
         /// <param name="Candidates"></param>
21 21
         /// <param name="Capture"></param>
22 22
         /// <returns></returns>
23  
-        public static RakudoCodeRef.Instance FindBestCandidate(List<RakudoCodeRef.Instance> Candidates, RakudoObject Capture)
  23
+        public static RakudoCodeRef.Instance FindBestCandidate(RakudoObject[] Candidates, RakudoObject Capture)
24 24
         {
25 25
             // Sort the candidates.
26 26
             // XXX Cache this in the future.
@@ -33,7 +33,7 @@ public static RakudoCodeRef.Instance FindBestCandidate(List<RakudoCodeRef.Instan
33 33
             // Now go through the sorted candidates and find the first one that
34 34
             // matches.
35 35
             var PossiblesList = new List<RakudoCodeRef.Instance>();
36  
-            foreach (var Candidate in SortedCandidates)
  36
+            foreach (RakudoCodeRef.Instance Candidate in SortedCandidates)
37 37
             {
38 38
                 // If we hit a null, we're at the end of a group.
39 39
                 if (Candidate == null)
@@ -81,9 +81,9 @@ public static RakudoCodeRef.Instance FindBestCandidate(List<RakudoCodeRef.Instan
81 81
         /// </summary>
82 82
         /// <param name="Unsorted"></param>
83 83
         /// <returns></returns>
84  
-        private static List<RakudoCodeRef.Instance> Sort(List<RakudoCodeRef.Instance> Unsorted)
  84
+        private static List<RakudoObject> Sort(RakudoObject[] Unsorted)
85 85
         {
86  
-            var Sorted = new List<RakudoCodeRef.Instance>(Unsorted);
  86
+            var Sorted = new List<RakudoObject>(Unsorted);
87 87
             Sorted.Add(null);
88 88
             return Sorted;
89 89
         }
51  dotnet/runtime/Runtime/Ops.cs
@@ -516,20 +516,48 @@ public static RakudoObject concat(ThreadContext TC, RakudoObject x, RakudoObject
516 516
         }
517 517
 
518 518
         /// <summary>
519  
-        /// Entry point to multi-dispatch over the candidates in the inner
520  
-        /// dispatcher.
  519
+        /// Entry point to multi-dispatch over the current dispatchee list.
521 520
         /// </summary>
522 521
         /// <param name="TC"></param>
523 522
         /// <returns></returns>
524  
-        public static RakudoObject multi_dispatch_over_lexical_candidates(ThreadContext TC, RakudoObject Name)
  523
+        public static RakudoObject multi_dispatch_over_lexical_candidates(ThreadContext TC)
525 524
         {
526  
-            var Candidate = MultiDispatch.MultiDispatcher.FindBestCandidate(
527  
-                MultiDispatch.LexicalCandidateFinder.FindCandidates(
528  
-                    TC.CurrentContext.Caller,
529  
-                    TC.CurrentContext.Outer,
530  
-                    "!" + Ops.unbox_str(TC, Name) + "-candidates"),
531  
-                TC.CurrentContext.Capture);
532  
-            return Candidate.STable.Invoke(TC, Candidate, TC.CurrentContext.Capture);
  525
+            var CurOuter = TC.CurrentContext;
  526
+            while (CurOuter != null)
  527
+            {
  528
+                var Dispatchees = CurOuter.StaticCodeObject.Dispatchees;
  529
+                if (Dispatchees != null)
  530
+                {
  531
+                    var Candidate = MultiDispatch.MultiDispatcher.FindBestCandidate(
  532
+                        Dispatchees, TC.CurrentContext.Capture);
  533
+                    return Candidate.STable.Invoke(TC, Candidate, TC.CurrentContext.Capture);
  534
+                }
  535
+                CurOuter = CurOuter.Outer;
  536
+            }
  537
+            throw new Exception("Could not find dispatchee list!");
  538
+        }
  539
+
  540
+        /// <summary>
  541
+        /// Sets the dispatches of the given code object. Expects something with
  542
+        /// RakudoCodeRef and P6list representation respectively.
  543
+        /// </summary>
  544
+        /// <param name="TC"></param>
  545
+        /// <param name="CodeObject"></param>
  546
+        /// <param name="Dispatchees"></param>
  547
+        /// <returns></returns>
  548
+        public static RakudoObject set_dispatchees(ThreadContext TC, RakudoObject CodeObject, RakudoObject Dispatchees)
  549
+        {
  550
+            var Code = CodeObject as RakudoCodeRef.Instance;
  551
+            var DispatchList = Dispatchees as P6list.Instance;
  552
+            if (Code != null && DispatchList != null)
  553
+            {
  554
+                Code.Dispatchees = DispatchList.Storage.ToArray();
  555
+                return Code;
  556
+            }
  557
+            else
  558
+            {
  559
+                throw new Exception("set_dispatchees must be passed a RakudoCodeRef and a P6list.");
  560
+            }
533 561
         }
534 562
 
535 563
         /// <summary>
@@ -774,7 +802,8 @@ public static RakudoObject new_closure(ThreadContext TC, RakudoCodeRef.Instance
774 802
             var NewBlock = new RakudoCodeRef.Instance(Block.STable);
775 803
             NewBlock.Body = Block.Body;
776 804
             NewBlock.CurrentContext = Block.CurrentContext;
777  
-            NewBlock.Handlers = Block.Handlers;
  805
+            NewBlock.Dispatchees = Block.Dispatchees;
  806
+            NewBlock.Handlers = Block.Handlers;            
778 807
             NewBlock.OuterBlock = Block.OuterBlock;
779 808
             NewBlock.Sig = Block.Sig;
780 809
             NewBlock.StaticLexPad = Block.StaticLexPad;

0 notes on commit 2ad10c2

Please sign in to comment.
Something went wrong with that request. Please try again.