From 7608b1ba6f2c55f3971a30323e9469f19bd4d992 Mon Sep 17 00:00:00 2001 From: Jonathan Worthington Date: Sat, 21 Aug 2010 02:15:31 +0200 Subject: [PATCH] Stop signature binding swamping the profile. At least one lesson to teach Rakudo's from this experience. --- dotnet/compiler/PAST2DNSTCompiler.pm | 10 ++- .../runtime/Runtime/Signatures/Parameter.cs | 10 +++ .../Runtime/Signatures/SignatureBinder.cs | 87 +++++++++++++------ 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/dotnet/compiler/PAST2DNSTCompiler.pm b/dotnet/compiler/PAST2DNSTCompiler.pm index 491754c..dc16f18 100644 --- a/dotnet/compiler/PAST2DNSTCompiler.pm +++ b/dotnet/compiler/PAST2DNSTCompiler.pm @@ -365,10 +365,12 @@ sub compile_signature(@params) { # Flags. $param.push( - $_.viviself ?? 'Parameter.OPTIONAL_FLAG' !! - $_.slurpy && $_.named ?? 'Parameter.NAMED_SLURPY_FLAG' !! - $_.slurpy ?? 'Parameter.POS_SLURPY_FLAG' !! - '0'); + $_.viviself && $_.named ?? 'Parameter.OPTIONAL_FLAG | Parameter.NAMED_FLAG' !! + $_.viviself ?? 'Parameter.OPTIONAL_FLAG' !! + $_.slurpy && $_.named ?? 'Parameter.NAMED_SLURPY_FLAG' !! + $_.slurpy ?? 'Parameter.POS_SLURPY_FLAG' !! + $_.named ?? 'Parameter.NAMED_FLAG' !! + 'Parameter.POS_FLAG'); $params.push($param); } diff --git a/dotnet/runtime/Runtime/Signatures/Parameter.cs b/dotnet/runtime/Runtime/Signatures/Parameter.cs index 0b4142b..5724faa 100644 --- a/dotnet/runtime/Runtime/Signatures/Parameter.cs +++ b/dotnet/runtime/Runtime/Signatures/Parameter.cs @@ -46,6 +46,11 @@ public Parameter(RakudoObject Type, string VariableName, string Name, int Flags) /// public int Flags; + /// + /// (Un-)flag for positional parameters. + /// + public const int POS_FLAG = 0; + /// /// Flag for optional parameters. /// @@ -60,5 +65,10 @@ public Parameter(RakudoObject Type, string VariableName, string Name, int Flags) /// Flag for named slurpy parameters. /// public const int NAMED_SLURPY_FLAG = 4; + + /// + /// Flag for named parameters. + /// + public const int NAMED_FLAG = 8; } } diff --git a/dotnet/runtime/Runtime/Signatures/SignatureBinder.cs b/dotnet/runtime/Runtime/Signatures/SignatureBinder.cs index 29fabea..c6ca862 100644 --- a/dotnet/runtime/Runtime/Signatures/SignatureBinder.cs +++ b/dotnet/runtime/Runtime/Signatures/SignatureBinder.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using Rakudo.Metamodel; +using Rakudo.Metamodel.Representations; namespace Rakudo.Runtime { @@ -11,6 +12,16 @@ namespace Rakudo.Runtime /// public static class SignatureBinder { + /// + /// Singleton empty positionals array. + /// + private static RakudoObject[] EmptyPos = new RakudoObject[0]; + + /// + /// Single empty nameds hash. + /// + private static Dictionary EmptyNamed = new Dictionary(); + /// /// Binds the capture against the given signature and stores the /// bound values into variables in the lexpad. @@ -30,6 +41,14 @@ public static void Bind(Context C, RakudoObject Capture) // The lexpad we'll bind into. var Target = C.LexPad; + // Make sure the object is really a low level capture (don't handle + // otherwise yet) and grab the pieces. + var NativeCapture = Capture as P6capture.Instance; + if (NativeCapture == null) + throw new NotImplementedException("Can only deal with native captures at the moment"); + var Positionals = NativeCapture.Positionals ?? EmptyPos; + var Nameds = NativeCapture.Nameds ?? EmptyNamed; + // Current positional. var CurPositional = 0; @@ -37,8 +56,44 @@ public static void Bind(Context C, RakudoObject Capture) var Params = C.StaticCodeObject.Sig.Parameters; foreach (var Param in Params) { + // Positional required? + if (Param.Flags == Parameter.POS_FLAG) + { + if (CurPositional < Positionals.Length) + { + // We have an argument, just bind it. + Target[Param.VariableName] = Positionals[CurPositional]; + } + else + { + throw new Exception("Not enough positional parameters; got " + + CurPositional.ToString() + " but needed " + + NumRequiredPositionals(C.StaticCodeObject.Sig).ToString()); + } + + // Increment positional counter. + CurPositional++; + } + + // Positonal optional? + else if (Param.Flags == Parameter.OPTIONAL_FLAG) + { + if (CurPositional < Positionals.Length) + { + // We have an argument, just bind it. + Target[Param.VariableName] = Positionals[CurPositional]; + } + else + { + // XXX Default value, vivification. + } + + // Increment positional counter. + CurPositional++; + } + // Named slurpy? - if ((Param.Flags & Parameter.NAMED_SLURPY_FLAG) != 0) + else if ((Param.Flags & Parameter.NAMED_SLURPY_FLAG) != 0) { throw new Exception("Named slurpy parameters are not yet implemented."); } @@ -53,8 +108,8 @@ public static void Bind(Context C, RakudoObject Capture) else if (Param.Name != null) { // Yes, try and get argument. - var Value = CaptureHelper.GetNamed(Capture, Param.Name); - if (Value != null) + RakudoObject Value; + if (Nameds.TryGetValue(Param.Name, out Value)) { // We have an argument, just bind it. Target[Param.VariableName] = Value; @@ -73,37 +128,15 @@ public static void Bind(Context C, RakudoObject Capture) } } - // Otherwise, it's a positional. + // Otherwise, WTF? else { - var Value = CaptureHelper.GetPositional(Capture, CurPositional); - if (Value != null) - { - // We have an argument, just bind it. - Target[Param.VariableName] = Value; - } - else - { - // Optional? - if ((Param.Flags & Parameter.OPTIONAL_FLAG) == 0) - { - throw new Exception("Not enough positional parameters; got " + - CurPositional.ToString() + " but needed " + - NumRequiredPositionals(C.StaticCodeObject.Sig).ToString()); - } - else - { - // XXX Default value, vivification. - } - } - // Increment positional counter. - CurPositional++; } } // Ensure we had enough positionals. - var PossiesInCapture = CaptureHelper.NumPositionals(Capture); + var PossiesInCapture = Positionals.Length; if (CurPositional != PossiesInCapture) throw new Exception("Too many positional arguments passed; expected " + NumRequiredPositionals(C.StaticCodeObject.Sig).ToString() +