Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
$_ defaults to $OUTER::_
  • Loading branch information
sorear committed May 16, 2011
1 parent ddee5a5 commit a2b2f37
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 33 deletions.
7 changes: 2 additions & 5 deletions TODO
Expand Up @@ -7,8 +7,6 @@ EASY

+ $*PROGRAM_NAME

+ when {} shouldn't disrupt flow of $_

+ $*OUT

Rename at-key, at-pos to "postcircumfix:<[ ]>" etc.
Expand All @@ -28,9 +26,8 @@ EASY

Fudge and run your favorite spectest file.

Stuff spectests are blocking on: "Block", "&hash", "writable $_",
"closure for", "ranges of chars", "gather for", constants in signatures,
::T, Int, ...
Stuff spectests are blocking on: "Block", "&hash", "closure for",
"ranges of chars", "gather for", constants in signatures, ::T, Int, ...

MEDIUM

Expand Down
19 changes: 14 additions & 5 deletions lib/CLRBackend.cs
Expand Up @@ -2559,9 +2559,11 @@ class NamProcessor {

CpsOp RawAccessLex(string type, string name, CpsOp set_to) {
bool core = type == "corelex";
bool uplex = type == "outerlex";
bool upscope = uplex && (scope_stack.Count > 0);
int uplevel;

for (int i = (core ? -1 : scope_stack.Count - 1); i >= 0; i--) {
for (int i = (core ? -1 : scope_stack.Count - (upscope ? 2 : 1)); i >= 0; i--) {
object[] rec = scope_stack[i];
for (int j = 2; j < rec.Length - 2; j += 2) {
if (JScalar.S(rec[j]) == name) {
Expand All @@ -2573,16 +2575,21 @@ class NamProcessor {
}
}

Lexical lex = ResolveLex(name, out uplevel, core);
Lexical lex = ResolveLex(name, uplex&& !upscope, out uplevel, core);

return CpsOp.LexAccess(lex, uplevel,
set_to == null ? new CpsOp[0] : new CpsOp[] { set_to });
}

Lexical ResolveLex(string name, out int uplevel, bool core) {
Lexical ResolveLex(string name, bool upf, out int uplevel, bool core) {
uplevel = 0;
StaticSub csr = sub;

if (upf) {
csr = csr.outer.Resolve<StaticSub>();
uplevel++;
}

while (true) {
Lexical r;
if ((!core || csr.IsCore()) &&
Expand Down Expand Up @@ -2749,6 +2756,7 @@ class NamProcessor {
handlers["letvar"] = delegate(NamProcessor th, object[] zyg) {
return th.AccessLet(zyg); };
handlers["scopedlex"] =
handlers["outerlex"] =
handlers["corelex"] = delegate(NamProcessor th, object[] zyg) {
return th.AccessLex(zyg); };
handlers["compare"] = handlers["arith"] =
Expand Down Expand Up @@ -2888,7 +2896,7 @@ class NamProcessor {
return th.SubyCall(false, zyg); };
handlers["_hintset"] = delegate (NamProcessor th, object[] zyg) {
int d;
Lexical lx = th.ResolveLex(JScalar.S(zyg[1]), out d, false);
Lexical lx = th.ResolveLex(JScalar.S(zyg[1]),false,out d,false);
FieldInfo peer = (lx is LexCommon) ? ((LexCommon)lx).stg :
((LexHint)lx).stg;
return CpsOp.SetField(Tokens.BValue_v, CpsOp.GetSField(peer),
Expand Down Expand Up @@ -3697,9 +3705,10 @@ public class CLRBackend {
sig_r.Add(CpsOp.StringLiteral(n));
int ufl = 0;
if ((flags & 4) != 0) ufl |= SubInfo.SIG_F_RWTRANS;
else if ((flags & 64) == 0) ufl |= SubInfo.SIG_F_READWRITE;
else if ((flags & 64) != 0) ufl |= SubInfo.SIG_F_READWRITE;

if ((flags & 384) != 0) ufl |= SubInfo.SIG_F_BINDLIST;
if ((flags & 512) != 0) ufl |= SubInfo.SIG_F_DEFOUTER;
if (deflt != null) {
ufl |= SubInfo.SIG_F_HASDEFAULT;
sig_r.Add(CpsOp.GetSField(deflt.Resolve<StaticSub>().subinfo));
Expand Down
53 changes: 41 additions & 12 deletions lib/Kernel.cs
Expand Up @@ -213,6 +213,9 @@ public class SubInfo {
// maybe should be a hint
public LAD ltm;

public int outer_topic_rank;
public int outer_topic_key;

// Used for closing runtime-generated SubInfo over values used
// For vtable wrappers: 0 = unboxed, 1 = boxed
// For dispatch routines, 0 = parameter list
Expand Down Expand Up @@ -240,6 +243,7 @@ public class SubInfo {
// Value source
public const int SIG_F_HASDEFAULT = 32;
public const int SIG_F_OPTIONAL = 64;
public const int SIG_F_DEFOUTER = 4096;
public const int SIG_F_POSITIONAL = 128;
public const int SIG_F_SLURPY_POS = 256;
public const int SIG_F_SLURPY_NAM = 512;
Expand Down Expand Up @@ -381,6 +385,16 @@ public class SubInfo {
throw new Exception("Improper null return from sub default for " + PName(rbase));
goto gotit;
}
if ((flags & SIG_F_DEFOUTER) != 0) {
Frame f = th;
if (outer_topic_key < 0) {
src = Kernel.NewROScalar(Kernel.AnyP);
goto gotit;
}
for (int i = 0; i < outer_topic_rank; i++) f = f.outer;
src = (Variable)f.GetDynamic(outer_topic_key);
goto gotit;
}
if ((flags & SIG_F_OPTIONAL) != 0) {
src = Kernel.NewROScalar(type.typeObject);
goto gotit;
Expand Down Expand Up @@ -498,6 +512,17 @@ public class SubInfo {
for (int i = 0; i < edata.Length; i += 5)
if (edata[i+2] == ON_VARLOOKUP && edata[i+4] >= 0)
dylex_filter |= FilterForName(label_names[edata[i+4]]);

SubInfo sc = outer;
for (outer_topic_rank = 1; sc != null; sc = sc.outer) {
if (sc.dylex != null &&
sc.dylex.TryGetValue("$_", out outer_topic_key))
break;
outer_topic_rank++;
}
if (sc == null)
outer_topic_key = -1;
//Console.WriteLine("{0} {1} {2}", name, outer_topic_rank, outer_topic_key);
}

public SubInfo(string name, DynBlockDelegate code) :
Expand Down Expand Up @@ -662,20 +687,24 @@ public class Frame: P6any {
if (!info.dylex.TryGetValue(name, out ix))
return false;
}
v = GetDynamic(ix);
return true;
}

public object GetDynamic(int ix) {
switch(ix) {
case 0: v = lex0; break;
case 1: v = lex1; break;
case 2: v = lex2; break;
case 3: v = lex3; break;
case 4: v = lex4; break;
case 5: v = lex5; break;
case 6: v = lex6; break;
case 7: v = lex7; break;
case 8: v = lex8; break;
case 9: v = lex9; break;
default: v = lexn[ix-10]; break;
case 0: return lex0;
case 1: return lex1;
case 2: return lex2;
case 3: return lex3;
case 4: return lex4;
case 5: return lex5;
case 6: return lex6;
case 7: return lex7;
case 8: return lex8;
case 9: return lex9;
default: return lexn[ix-10];
}
return true;
}

public Variable LexicalFind(string name) {
Expand Down
7 changes: 4 additions & 3 deletions src/NAMOutput.pm6
Expand Up @@ -272,9 +272,10 @@ augment class Sig::Parameter { #OK exist
$flags = $flags +| 8 if $.full_parcel;
$flags = $flags +| 16 if $.optional;
$flags = $flags +| 32 if $.positional;
$flags = $flags +| 64 if $.readonly;
$flags = $flags +| 64 if $.rw;
$flags = $flags +| 128 if $.list;
$flags = $flags +| 256 if $.hash;
$flags = $flags +| 512 if $.defouter;

[
$.name,
Expand All @@ -293,8 +294,8 @@ sub parm_from_nam(@block) {
slurpy => ?($flags +& 1), slurpycap => ?($flags +& 2),
rwtrans => ?($flags +& 4), full_parcel => ?($flags +& 8),
optional => ?($flags +& 16), positional => ?($flags +& 32),
readonly => ?($flags +& 64), list => ?($flags +& 128),
hash => ?($flags +& 256),
rw => ?($flags +& 64), list => ?($flags +& 128),
hash => ?($flags +& 256), defouter => ?($flags +& 512),
name => $name, slot => $slot, names => $names, :$tclass);
}

Expand Down
8 changes: 4 additions & 4 deletions src/NieczaActions.pm6
Expand Up @@ -313,10 +313,10 @@ method encapsulate_regex($/, $rxop, :$goal, :$passcut = False,
my $lad = $rxop.lad;
my ($nrxop, $mb) = OptRxSimple.run($rxop);
# XXX do this in the signature so it won't be affected by transparent
my @parm = ::Sig::Parameter.new(slot => 'self', name => 'self', readonly => True);
my @parm = ::Sig::Parameter.new(slot => 'self', name => 'self');
if defined $goal {
push @parm, ::Sig::Parameter.new(slot => '$*GOAL', name => '$*GOAL',
readonly => True, positional => False, optional => True);
positional => False, optional => True);
unshift @lift, ::Op::Bind.new(|node($/), readonly => True,
lhs => ::Op::Lexical.new(name => '$*GOAL'),
rhs => ::Op::StringLiteral.new(text => $goal));
Expand Down Expand Up @@ -1797,7 +1797,7 @@ method parameter($/) {
my $p = $<param_var> // $<named_param>;

make ::Sig::Parameter.new(name => ~$/, :$default,
:$optional, :$slurpy, readonly => !$rw, type => ($type // 'Any'),
:$optional, :$slurpy, :$rw, type => ($type // 'Any'),
:$slurpycap, rwtrans => $rwt, |$p.ast);
}

Expand Down Expand Up @@ -2550,7 +2550,7 @@ method get_placeholder_sig($/) {
my @parms;
for @things -> $t {
if substr($t, 0, 9) eq '$_ is ref' {
push @parms, ::Sig::Parameter.new(optional => True,
push @parms, ::Sig::Parameter.new(defouter => True, rwtrans => True,
slot => '$_', name => '$_');
} elsif $t eq '*@_' {
push @parms, ::Sig::Parameter.new(slurpy => True, slot => '@_',
Expand Down
10 changes: 6 additions & 4 deletions src/Sig.pm6
Expand Up @@ -12,11 +12,11 @@ class Parameter {
has $.rwtrans = False; # Bool
has $.full_parcel = False; # Bool
has $.optional = False; # Bool
has $.defouter = False; # Bool
has $.positional = True;
has $.default; # Body
has $.mdefault; # Xref; filled in by begin (rw)
# not 'is rw' (how meta).
has $.readonly = False;
has $.rw = False;
has $.names = []; # Array of Str
has $.name; # Str
has $.list = False; # Bool
Expand All @@ -27,6 +27,8 @@ class Parameter {
method !default_get($body) {
if defined $!mdefault {
CgOp.call_uncloned_sub(@$!mdefault);
} elsif $!defouter {
CgOp.outerlex($!slot);
} elsif $!optional {
CgOp.scopedlex($!type);
} else {
Expand All @@ -50,13 +52,13 @@ class Parameter {

if (defined $!slot) {
CgOp.scopedlex($!slot, $!rwtrans ?? $get !!
CgOp.newboundvar(+$!readonly, +$!list, $get));
CgOp.newboundvar(+(!$!rw), +$!list, $get));
} else {
CgOp.sink($get);
}
}

method simple($n) { self.new(name => $n, slot => $n, readonly => True) }
method simple($n) { self.new(name => $n, slot => $n) }
}

has $.params = die "Sig.params required"; # Array of Sig::Parameter
Expand Down
1 change: 1 addition & 0 deletions src/niecza
Expand Up @@ -230,6 +230,7 @@ class RxOp::CutBrack is RxOp {
}

augment class CgOp {
method outerlex ($n) { self._cgop("outerlex", $n) }
method bif_rand () { self._cgop("bif_rand") }
}

Expand Down
25 changes: 25 additions & 0 deletions test2.pl
Expand Up @@ -134,6 +134,31 @@
is $(1,2,3).perl, '$(1, 2, 3)', '.perl: $(1,2,3)';
}

{
$_ := 5;
if True {
is $_, 5, '$_ passes into ifs';
}

if False {
} else {
is $_, 5, '$_ passes into elses';
}

my $i = 1;
while $i-- {
is $_, 5, '$_ passes into whiles';
}
given 8 {
default {
is $_, 8, '$_ passes into whens/defaults';
}
}
{
is $_, 5, '$_ passes into bare blocks';
}
}

#is $?FILE, 'test.pl', '$?FILE works';
#is $?ORIG.substr(0,5), '# vim', '$?ORIG works';

Expand Down

0 comments on commit a2b2f37

Please sign in to comment.