Browse files

Change BEGIN to be run immediately instead of an alias for INIT

  • Loading branch information...
1 parent ab36838 commit a1c7d299c9507eede5d9e47bf4044132f8cb56ae @sorear committed Oct 31, 2011
Showing with 49 additions and 1 deletion.
  1. +4 −0 lib/CodeGen.cs
  2. +21 −1 lib/Kernel.cs
  3. +24 −0 src/niecza
View
4 lib/CodeGen.cs
@@ -3732,6 +3732,9 @@ public class DowncallReceiver : CallReceiver {
} else if (cmd == "sub_set_inlined") {
((SubInfo)Handle.Unbox(args[1])).SetInlined();
return null;
+ } else if (cmd == "sub_run_BEGIN") {
+ ((SubInfo)Handle.Unbox(args[1])).RunBEGIN();
+ return null;
} else if (cmd == "sub_get_unit") {
return new Handle(((SubInfo)Handle.Unbox(args[1])).unit);
} else if (cmd == "sub_run_once") {
@@ -4287,6 +4290,7 @@ public class DowncallReceiver : CallReceiver {
s.nam_refs = new object[args.Length - 3];
for (int i = 0; i < s.nam_refs.Length; i++)
s.nam_refs[i] = Handle.Unbox(args[i+3]);
+ s.code = RuntimeUnit.JitCompileSub;
return null;
} else if (cmd == "save_unit") {
RuntimeUnit ru = (RuntimeUnit)Handle.Unbox(args[1]);
View
22 lib/Kernel.cs
@@ -708,6 +708,20 @@ public sealed class RuntimeUnit : IFreeze {
eu.CgSub(z, erase);
}
+ internal static Frame JitCompileSub(Frame th) {
+ if (Config.CGVerbose > 0)
+ Console.WriteLine("Generating code for {0} now because it's about to be run", th.info.name);
+
+ EmitUnit eu = new EmitUnit(null, "Anon." + Interlocked.Increment(
+ ref anon_id), null, false);
+ eu.CgSub(th.info, false);
+ SetConstants(eu.Finish(), eu.constants);
+
+ th.code = th.info.code;
+
+ return th;
+ }
+
[CompartmentGlobal]
internal static ObjectRegistry reg;
@@ -728,7 +742,7 @@ public sealed class RuntimeUnit : IFreeze {
}
internal void SetConstants() { SetConstants(type, constants); }
- void SetConstants(Type ty, Dictionary<object,FieldInfo> consts) {
+ static void SetConstants(Type ty, Dictionary<object,FieldInfo> consts) {
if (ty != null) {
foreach (KeyValuePair<object, FieldInfo> kv in consts)
kv.Value.SetValue(null, kv.Key);
@@ -1843,6 +1857,12 @@ public class UsedInScopeInfo {
}
}
+ internal void RunBEGIN() {
+ Kernel.RunInferior(protosub.Invoke(Kernel.GetInferiorRoot(),
+ Variable.None, null));
+ SetInlined();
+ }
+
internal bool IsTopicalizer() {
if (sig_i == null)
return false;
View
24 src/niecza
@@ -78,6 +78,30 @@ augment class RxOp::Sym {
}
augment class NieczaActions {
+method statement_prefix:BEGIN ($/) {
+ # MAJOR HACK - allows test code like BEGIN { @*INC.push: ... } to work
+ repeat while False {
+ my $c = ($<blast><statement> || $<blast><block><blockoid>).ast;
+
+ last unless $c ~~ Op::StatementList;
+ last unless $c.children == 1;
+ my $d = $c.children.[0];
+ last unless $d ~~ Op::CallMethod;
+ last unless $d.receiver ~~ Op::ContextVar;
+ last unless $d.receiver.name eq '@*INC';
+ last if $d.private || $d.ismeta;
+ last unless $d.name eq any <push unshift>;
+ last unless +$d.getargs == 1;
+ last unless defined my $str = self.trivial_eval($/, $d.getargs.[0]);
+ @*INC."$d.name()"($str);
+ make ::Op::StatementList.new;
+ return;
+ }
+
+ $*CURLEX<!sub>.create_static_pad;
+ $<blast>.ast.run_BEGIN;
+ make ::Op::StatementList.new;
+}
method blockoid($/) {
# XXX horrible cheat, but my data structures aren't up to the task of
# $::UNIT being a class body &c.

0 comments on commit a1c7d29

Please sign in to comment.