Permalink
Browse files

Eliminate the lexical/let punning horror

  • Loading branch information...
1 parent 0668028 commit 8840f61dd5ba2198f5b0476750ceb26891523249 @sorear committed Feb 19, 2011
Showing with 84 additions and 17 deletions.
  1. +3 −4 TODO
  2. +31 −8 lib/CLRBackend.cs
  3. +1 −0 src/Metamodel.pm6
  4. +2 −0 src/NAMOutput.pm6
  5. +6 −3 src/NieczaPassBegin.pm6
  6. +7 −2 src/NieczaPassBeta.pm6
  7. +34 −0 src/niecza
View
7 TODO
@@ -29,10 +29,9 @@ EASY
Fudge and run your favorite spectest file.
- Stuff spectests are blocking on: "is readonly",
- "Block", "&hash",
- "writable $_", "closure for", "ranges of chars", "gather for",
- "unless", "my regex / <&foo>", "m//",
+ Stuff spectests are blocking on: "Block", "&hash", "writable $_",
+ "closure for", "ranges of chars", "gather for", "unless",
+ "my regex / <&foo>", "m//",
At least parsing Int et al on my-decls would help a lot
View
@@ -2505,6 +2505,7 @@ class NamProcessor {
public readonly CpsBuilder cpb;
Dictionary<string, Type> let_types = new Dictionary<string, Type>();
List<List<ClrEhSpan>> eh_stack = new List<List<ClrEhSpan>>();
+ List<object[]> scope_stack = new List<object[]>();
public NamProcessor(CpsBuilder cpb, StaticSub sub) {
this.sub = sub;
@@ -2516,19 +2517,34 @@ class NamProcessor {
(zyg.Length > 2 ? Scan(zyg[2]) : null) );
}
- CpsOp RawAccessLex(string type, string name, CpsOp set_to) {
- bool core = (type == "corelex");
- bool letonly = (type == "letvar");
-
+ CpsOp AccessLet(object[] zyg) {
+ string name = JScalar.S(zyg[1]);
+ CpsOp set_to = zyg.Length > 2 ? Scan(zyg[2]) : null;
Type t;
- if (!core && let_types.TryGetValue(name, out t)) {
+
+ if (let_types.TryGetValue(name, out t)) {
return (set_to == null) ? CpsOp.PeekLet(name, t) :
CpsOp.PokeLet(name, new CpsOp[1] { set_to });
}
- if (letonly)
- throw new Exception("No such let " + name);
+ throw new Exception("No such let " + name);
+ }
+ CpsOp RawAccessLex(string type, string name, CpsOp set_to) {
+ bool core = type == "corelex";
int uplevel;
+
+ for (int i = (core ? -1 : scope_stack.Count - 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) {
+ string lname = JScalar.S(rec[j+1]);
+ return (set_to == null) ?
+ CpsOp.PeekLet(lname, let_types[lname]) :
+ CpsOp.PokeLet(lname, new CpsOp[1] { set_to });
+ }
+ }
+ }
+
Lexical lex = ResolveLex(name, out uplevel, core);
return CpsOp.LexAccess(lex, uplevel,
@@ -2779,8 +2795,15 @@ class NamProcessor {
throw new NotImplementedException();
return CpsOp.GetSField(m.metaObject);
};
+ handlers["letscope"] = delegate(NamProcessor th, object[] zyg) {
+ th.scope_stack.Add(zyg);
+ CpsOp co = th.Scan(zyg[zyg.Length - 1]);
+ th.scope_stack.RemoveAt(th.scope_stack.Count - 1);
+ return co;
+ };
+ handlers["letvar"] = delegate(NamProcessor th, object[] zyg) {
+ return th.AccessLet(zyg); };
handlers["scopedlex"] =
- handlers["letvar"] =
handlers["corelex"] = delegate(NamProcessor th, object[] zyg) {
return th.AccessLex(zyg); };
handlers["methodcall"] = delegate (NamProcessor th, object[] zyg) {
View
@@ -461,6 +461,7 @@ class StaticSub is RefTarget {
has $.outerx; # Xref
has $.run_once = False; # Bool
has $.spad_exists = False; # Bool
+ has $.transparent = False; # Bool; ignored by OUTER::
has $.lexicals = {};
has $.code; # Op, is rw
has $.signature; # Sig, is rw
View
@@ -128,6 +128,7 @@ augment class Metamodel::StaticSub { #OK exist
$flags +|= 8 if $.strong_used;
$flags +|= 16 if $.returnable;
$flags +|= 32 if $.augmenting;
+ $flags +|= 64 if $.transparent;
[
'sub',
$.name,
@@ -164,6 +165,7 @@ sub sub_from_nam(@block) {
outerx => $outer,
run_once => ?($flags +& 1),
spad_exists => ?($flags +& 2),
+ transparent => ?($flags +& 64),
lexicals => {},
zyg => [],
class => $cls,
View
@@ -41,6 +41,7 @@ my %type2phaser = ( init => 0, end => 1, begin => 2 );
augment class Body { method begin(:$once = False, :$itop, :$body_of, :$cur_pkg, :$augmenting = False, :$prefix = '', :$gather_hack, :$augment_hack) {
my $top = @*opensubs ?? @*opensubs[*-1].xref !! $itop;
my $rtop = $top && $*unit.deref($top);
+ my $istop = !@*opensubs;
my $type = $.type // '';
my $metabody = ::Metamodel::StaticSub.new(
@@ -54,12 +55,13 @@ augment class Body { method begin(:$once = False, :$itop, :$body_of, :$cur_pkg,
augmenting => $augmenting,
name => $prefix ~ $.name,
returnable => $.returnable,
+ transparent=> $.transparent,
gather_hack=> $gather_hack,
augment_hack=> $augment_hack,
is_phaser => %type2phaser{$type},
class => $.class,
ltm => $.ltm,
- run_once => $once && (!@*opensubs || $rtop.run_once));
+ run_once => $once && ($istop || $rtop.run_once));
$*unit.create_stash($metabody.cur_pkg);
@@ -73,8 +75,7 @@ augment class Body { method begin(:$once = False, :$itop, :$body_of, :$cur_pkg,
if $type eq 'regex' {
$metabody.add_my_name('$*/');
}
- $metabody.add_my_name('$_') unless $.transparent ||
- ($metabody.lexicals<$_>:exists);
+ $metabody.add_my_name('$_') if $istop;
pop @*opensubs if $.transparent;
@@ -199,6 +200,7 @@ augment class Op::ConstantDecl { #OK exist
$.init.begin;
my $nb = ::Metamodel::StaticSub.new(
+ transparent=> True,
unit => $*unit,
outerx => @*opensubs[*-1].xref,
name => $.name,
@@ -237,6 +239,7 @@ augment class Op::Attribute { #OK exist
$ns = $*unit.deref($ns);
$ns.add_attribute($.name, +$.accessor, $ibvar, $ibref);
my $nb = ::Metamodel::StaticSub.new(
+ transparent=> True,
unit => $*unit,
outerx => @*opensubs[*-1].xref,
name => $.name,
View
@@ -85,23 +85,28 @@ sub beta_optimize($body, $op, $inv, $cbody) {
@$c = grep { $_ !=== $cbody }, @$c;
}
- my @pos = (map { ::Op::Lexical.new(name => $_[1]) }, @args);
+ my @pos = (map { ::Op::LetVar.new(name => $_[1]) }, @args);
my $nop = ::Op::StatementList.new(children => [
::Op::SigBind.new(signature => $cbody.signature,
positionals => @pos),
$cbody.code]);
+ my @scope;
for sort keys $cbody.lexicals -> $dn {
my $d = $cbody.lexicals{$dn};
+ my $nm = ::GLOBAL::NieczaActions.gensym;
my $to = $d.noinit ?? CgOp.null('var') !!
$d.hash ?? CgOp.newblankhash !!
$d.list ?? CgOp.newblanklist !!
CgOp.newblankrwscalar;
- $nop = ::Op::Let.new(var => $dn,
+ $nop = ::Op::Let.new(var => $nm,
to => ::Op::CgOp.new(op => $to), in => $nop);
+ push @scope, $dn, $nm;
}
+ $nop = ::Op::LetScope.new(names => @scope, inner => $nop,
+ transparent => $cbody.transparent);
for reverse @args -> $a {
$nop = ::Op::Let.new(var => $a.[1], to => $a.[0], in => $nop);
}
View
@@ -211,14 +211,48 @@ method quote_mod:h ($) { }
method quote_mod:f ($) { }
method quote_mod:c ($) { }
method quote_mod:b ($) { }
+my %opshortcut = (
+ '@' => [ 'fetch' ],
+ 'l' => [ 'letvar' ],
+ 'ns' => [ 'newscalar' ],
+ 'nsw' => [ 'newrwscalar' ],
+ 's' => [ 'str' ],
+ 'i' => [ 'int' ],
+ 'b' => [ 'bool' ],
+ 'd' => [ 'double' ],
+ '==' => [ 'compare', '==' ], '!=' => [ 'compare', '!=' ],
+ '>=' => [ 'compare', '>=' ], '<=' => [ 'compare', '<=' ],
+ '<' => [ 'compare', '<' ], '>' => [ 'compare', '>' ],
+ '+' => [ 'arith', '+' ], '-' => [ 'arith', '-' ],
+ '*' => [ 'arith', '*' ], '/' => [ 'arith', '/' ],
+);
+
+method cgexp:op ($/) {
+ my $l = ~$<cgopname>;
+ my @p = @( %opshortcut{$l} // [ $l ] );
+ make [@p, map *.ast, @( $<cgexp> )];
+}
}
augment class CgOp {
+method letscope(*@items) { self._cgop('letscope', @items) }
method xspan(*@items) { self._cgop('xspan', @items) }
method bif_mod($x,$y) { self._cgop('bif_mod', $x, $y) }
}
augment class Op {
+class LetScope is Op {
+ has $.transparent;
+ has $.names;
+ has $.inner;
+
+ method zyg() { $.inner }
+
+ method code($body) {
+ CgOp.letscope(+$.transparent, @($.names), $.inner.cgop($body));
+ }
+}
+
class Control is Op {
has $.payload = die "Control.payload required"; # Op
has $.name = "";

0 comments on commit 8840f61

Please sign in to comment.