Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[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
jnthn committed Oct 30, 2010
1 parent e455223 commit 2ad10c2
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 92 deletions.
14 changes: 7 additions & 7 deletions common/NQP/NQPSetting.pm
Expand Up @@ -152,7 +152,7 @@ knowhow NQPCode is repr('RakudoCodeRef') {
## XXX Need coercive Any fallbacks too.

proto sub &infix:<==>($x, $y) {
nqp::multi_dispatch_over_lexical_candidates("&infix:<==>");
nqp::multi_dispatch_over_lexical_candidates();
}
multi sub &infix:<==>(NQPInt $x, NQPInt $y) {
nqp::equal_ints($x, $y)
Expand All @@ -162,7 +162,7 @@ multi sub &infix:<==>(NQPNum $x, NQPNum $y) {
}

proto sub &infix:<!=>($x, $y) {
nqp::multi_dispatch_over_lexical_candidates("&infix:<!=>");
nqp::multi_dispatch_over_lexical_candidates();
}
multi sub &infix:<!=>(NQPInt $x, NQPInt $y) {
nqp::logical_not_int(nqp::equal_ints($x, $y))
Expand Down Expand Up @@ -200,35 +200,35 @@ sub &prefix:<+>($x) {
}

proto sub &infix:<+>($x, $y) {
nqp::multi_dispatch_over_lexical_candidates("&infix:<+>");
nqp::multi_dispatch_over_lexical_candidates();
}
multi sub &infix:<+>(NQPInt $x, NQPInt $y) {
nqp::add_int($x, $y);
}

proto sub &infix:<->($x, $y) {
nqp::multi_dispatch_over_lexical_candidates("&infix:<->");
nqp::multi_dispatch_over_lexical_candidates();
}
multi sub &infix:<->(NQPInt $x, NQPInt $y) {
nqp::sub_int($x, $y);
}

proto sub &infix:<*>($x, $y) {
nqp::multi_dispatch_over_lexical_candidates("&infix:<*>");
nqp::multi_dispatch_over_lexical_candidates();
}
multi sub &infix:<*>(NQPInt $x, NQPInt $y) {
nqp::mul_int($x, $y);
}

proto sub &infix:</>($x, $y) {
nqp::multi_dispatch_over_lexical_candidates("&infix:</>");
nqp::multi_dispatch_over_lexical_candidates();
}
multi sub &infix:</>(NQPInt $x, NQPInt $y) {
nqp::div_int($x, $y);
}

proto sub &infix:<%>($x, $y) {
nqp::multi_dispatch_over_lexical_candidates("&infix:<%>");
nqp::multi_dispatch_over_lexical_candidates();
}
multi sub &infix:<%>(NQPInt $x, NQPInt $y) {
nqp::mod_int($x, $y);
Expand Down
46 changes: 20 additions & 26 deletions dotnet/compiler/Actions.pm
Expand Up @@ -493,50 +493,44 @@ method routine_def($/) {
$past.name($name);
if $*SCOPE eq '' || $*SCOPE eq 'my' {
if $*MULTINESS eq 'multi' {
my $chname := '!' ~ $name ~ '-candidates';
my $cholder;
# Does the current block have a candidate holder in place?
my %sym := @BLOCK[0].symbol($chname);
if %sym {
my $cholder;
my %sym := @BLOCK[0].symbol($name);
if %sym<cholder> {
$cholder := %sym<cholder>;
}

# Otherwise, no candidate holder, so add one.
else {
# Check we have a proto in scope.
my $found := 0;
for @BLOCK {
my %sym := $_.symbol($name);
if %sym {
if %sym<proto> {
$found := 1;
last;
}
else {
$/.CURSOR.panic("multi cannot be declared when only in scope");
}
}
}
unless $found {
$/.CURSOR.panic("multi cannot be declared without a proto in scope");
# XXX We need to get the proto clone from outer in place
# but for now just handle it being in the same block.
unless %sym<proto> {
$/.CURSOR.panic("Sorry, can only declare multis in the same block as a proto so far");
}

# Valid to add a candidate holder, so do so.
$cholder := PAST::Op.new(
:pasttype('call'), :name('list'),
);
@BLOCK[0][0].push(PAST::Var.new( :name($chname), :isdecl(1),
:viviself($cholder), :scope('lexical') ) );
@BLOCK[0].symbol($chname, :cholder($cholder) );
$cholder := PAST::Op.new( :pasttype('list') );
@BLOCK[0][0].push(PAST::Op.new(
:pasttype('nqpop'), :name('set_dispatchees'),
PAST::Var.new( :name($name) ),
$cholder
));
@BLOCK[0].symbol($name, :cholder($cholder));
}

# Add this candidate to the holder.
$cholder.push($past);
}
elsif $*MULTINESS eq 'proto' {
@BLOCK[0][0].push(PAST::Var.new( :name($name), :isdecl(1),
:viviself($past), :scope('lexical') ) );
@BLOCK[0].symbol($name, :scope('lexical'), :proto(1) );
}
else {
@BLOCK[0][0].push(PAST::Var.new( :name($name), :isdecl(1),
:viviself($past), :scope('lexical') ) );
@BLOCK[0].symbol($name, :scope('lexical'), :proto($*MULTINESS eq 'proto') );
@BLOCK[0].symbol($name, :scope('lexical') );
}
$past := PAST::Var.new( :name($name) );
}
Expand Down
1 change: 0 additions & 1 deletion dotnet/runtime/Rakudo.Net.csproj
Expand Up @@ -74,7 +74,6 @@
<Compile Include="Runtime\CaptureHelper.cs" />
<Compile Include="Runtime\Lexpad.cs" />
<Compile Include="Runtime\MultiDispatch\DispatchCache.cs" />
<Compile Include="Runtime\MultiDispatch\LexicalCandidateFinder.cs" />
<Compile Include="Runtime\MultiDispatch\MultiDispatcher.cs" />
<Compile Include="Runtime\Ops.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
43 changes: 0 additions & 43 deletions dotnet/runtime/Runtime/MultiDispatch/LexicalCandidateFinder.cs

This file was deleted.

8 changes: 4 additions & 4 deletions dotnet/runtime/Runtime/MultiDispatch/MultiDispatcher.cs
Expand Up @@ -20,7 +20,7 @@ public static class MultiDispatcher
/// <param name="Candidates"></param>
/// <param name="Capture"></param>
/// <returns></returns>
public static RakudoCodeRef.Instance FindBestCandidate(List<RakudoCodeRef.Instance> Candidates, RakudoObject Capture)
public static RakudoCodeRef.Instance FindBestCandidate(RakudoObject[] Candidates, RakudoObject Capture)
{
// Sort the candidates.
// XXX Cache this in the future.
Expand All @@ -33,7 +33,7 @@ public static RakudoCodeRef.Instance FindBestCandidate(List<RakudoCodeRef.Instan
// Now go through the sorted candidates and find the first one that
// matches.
var PossiblesList = new List<RakudoCodeRef.Instance>();
foreach (var Candidate in SortedCandidates)
foreach (RakudoCodeRef.Instance Candidate in SortedCandidates)
{
// If we hit a null, we're at the end of a group.
if (Candidate == null)
Expand Down Expand Up @@ -81,9 +81,9 @@ public static RakudoCodeRef.Instance FindBestCandidate(List<RakudoCodeRef.Instan
/// </summary>
/// <param name="Unsorted"></param>
/// <returns></returns>
private static List<RakudoCodeRef.Instance> Sort(List<RakudoCodeRef.Instance> Unsorted)
private static List<RakudoObject> Sort(RakudoObject[] Unsorted)
{
var Sorted = new List<RakudoCodeRef.Instance>(Unsorted);
var Sorted = new List<RakudoObject>(Unsorted);
Sorted.Add(null);
return Sorted;
}
Expand Down
51 changes: 40 additions & 11 deletions dotnet/runtime/Runtime/Ops.cs
Expand Up @@ -516,20 +516,48 @@ public static RakudoObject concat(ThreadContext TC, RakudoObject x, RakudoObject
}

/// <summary>
/// Entry point to multi-dispatch over the candidates in the inner
/// dispatcher.
/// Entry point to multi-dispatch over the current dispatchee list.
/// </summary>
/// <param name="TC"></param>
/// <returns></returns>
public static RakudoObject multi_dispatch_over_lexical_candidates(ThreadContext TC, RakudoObject Name)
public static RakudoObject multi_dispatch_over_lexical_candidates(ThreadContext TC)
{
var Candidate = MultiDispatch.MultiDispatcher.FindBestCandidate(
MultiDispatch.LexicalCandidateFinder.FindCandidates(
TC.CurrentContext.Caller,
TC.CurrentContext.Outer,
"!" + Ops.unbox_str(TC, Name) + "-candidates"),
TC.CurrentContext.Capture);
return Candidate.STable.Invoke(TC, Candidate, TC.CurrentContext.Capture);
var CurOuter = TC.CurrentContext;
while (CurOuter != null)
{
var Dispatchees = CurOuter.StaticCodeObject.Dispatchees;
if (Dispatchees != null)
{
var Candidate = MultiDispatch.MultiDispatcher.FindBestCandidate(
Dispatchees, TC.CurrentContext.Capture);
return Candidate.STable.Invoke(TC, Candidate, TC.CurrentContext.Capture);
}
CurOuter = CurOuter.Outer;
}
throw new Exception("Could not find dispatchee list!");
}

/// <summary>
/// Sets the dispatches of the given code object. Expects something with
/// RakudoCodeRef and P6list representation respectively.
/// </summary>
/// <param name="TC"></param>
/// <param name="CodeObject"></param>
/// <param name="Dispatchees"></param>
/// <returns></returns>
public static RakudoObject set_dispatchees(ThreadContext TC, RakudoObject CodeObject, RakudoObject Dispatchees)
{
var Code = CodeObject as RakudoCodeRef.Instance;
var DispatchList = Dispatchees as P6list.Instance;
if (Code != null && DispatchList != null)
{
Code.Dispatchees = DispatchList.Storage.ToArray();
return Code;
}
else
{
throw new Exception("set_dispatchees must be passed a RakudoCodeRef and a P6list.");
}
}

/// <summary>
Expand Down Expand Up @@ -774,7 +802,8 @@ public static RakudoObject new_closure(ThreadContext TC, RakudoCodeRef.Instance
var NewBlock = new RakudoCodeRef.Instance(Block.STable);
NewBlock.Body = Block.Body;
NewBlock.CurrentContext = Block.CurrentContext;
NewBlock.Handlers = Block.Handlers;
NewBlock.Dispatchees = Block.Dispatchees;
NewBlock.Handlers = Block.Handlers;
NewBlock.OuterBlock = Block.OuterBlock;
NewBlock.Sig = Block.Sig;
NewBlock.StaticLexPad = Block.StaticLexPad;
Expand Down

0 comments on commit 2ad10c2

Please sign in to comment.