Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement method definition, stubbing of packages
  • Loading branch information
sorear committed Oct 1, 2011
1 parent 0a6c198 commit 8579c2d
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 46 deletions.
47 changes: 40 additions & 7 deletions lib/CodeGen.cs
Expand Up @@ -4185,6 +4185,11 @@ class NamProcessor {
}

public class Backend {
public static string LocStr(string fo, int lo, string fn, int ln) {
return fn == fo ? " (see line " + lo + ")" :
" (see " + fo + " line " + lo + ")";
}

// internal AssemblyBuilder ab;
// internal ModuleBuilder mob;
// internal TypeBuilder tb;
Expand Down Expand Up @@ -4759,8 +4764,12 @@ public class DowncallReceiver : CallReceiver {
object Call(object[] args) {
if (TraceDown) {
Console.WriteLine(args.Length);
foreach(object a in args)
Console.WriteLine(a);
foreach(object a in args) {
char ch = (a is int) ? 'i' : (a is Handle) ? 'h' :
(a is string) ? 's' : (a is bool) ? 'b' :
(a == null) ? 'n' : 'X';
Console.WriteLine("{0}:{1}", ch, a);
}
}
string cmd = (string) args[0];
if (cmd == "gettype") {
Expand All @@ -4785,6 +4794,9 @@ public class DowncallReceiver : CallReceiver {
Backend.currentUnit.mainline = (SubInfo)Handle.Unbox(args[1]);
Backend.currentUnit.mainline.special |= RuntimeUnit.SUB_MAINLINE;
return null;
} else if (cmd == "sub_create_static_pad") {
((SubInfo)Handle.Unbox(args[1])).CreateProtopad();
return null;
} else if (cmd == "sub_get_unit") {
return new Handle(((SubInfo)Handle.Unbox(args[1])).unit);
} else if (cmd == "sub_run_once") {
Expand All @@ -4799,7 +4811,7 @@ public class DowncallReceiver : CallReceiver {
} else if (cmd == "sub_outer") {
return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).outer);
} else if (cmd == "sub_class") {
return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).mo.name);
return ((SubInfo)Handle.Unbox(args[1])).mo.name;
} else if (cmd == "sub_body_of") {
return Handle.Wrap(((SubInfo)Handle.Unbox(args[1])).body_of);
} else if (cmd == "sub_in_class") {
Expand Down Expand Up @@ -4918,10 +4930,10 @@ public class DowncallReceiver : CallReceiver {
}
return ret.ToArray();
} else if (cmd == "unit_stub_stash") {
RuntimeUnit u = (RuntimeUnit)Handle.Unbox(args[1]);
int pos = (int)args[2];
STable type = (STable)Handle.Unbox(args[3]);
u.stubbed_stashes.Add(new KeyValuePair<int,STable>(pos,type));
int pos = (int)args[1];
STable type = (STable)Handle.Unbox(args[2]);
Backend.currentUnit.stubbed_stashes.
Add(new KeyValuePair<int,STable>(pos,type));
return null;
} else if (cmd == "unit_get_name") {
return ((RuntimeUnit)Handle.Unbox(args[1])).name;
Expand Down Expand Up @@ -5015,6 +5027,27 @@ public class DowncallReceiver : CallReceiver {
STable su = (STable)Handle.Unbox(args[2]);
st.mo.superclasses.Add(su);
return null;
} else if (cmd == "type_add_method") {
STable add_to = (STable)Handle.Unbox(args[1]);
int mode = (int)args[2];
string name = (string)args[3];
SubInfo sub = (SubInfo)Handle.Unbox(args[4]);
string file = (string)args[5];
int line = (int)args[6];
//int pos = (int)args[7];

if ((mode & P6how.M_MASK) == P6how.M_ONLY) {
foreach (P6how.MethodInfo mi in add_to.mo.lmethods) {
if (mi.Name() == name &&
((mi.flags ^ mode) & P6how.V_MASK) == 0) {
return new Exception("Two definitions of method " +
name + Backend.LocStr(mi.file, mi.line, file, line));
}
}
}

add_to.mo.AddMethodPos(mode, name, sub.protosub, file, line);
return null;
} else if (cmd == "type_closed") {
STable st = (STable)Handle.Unbox(args[1]);
return st.mo.isComposed;
Expand Down
17 changes: 11 additions & 6 deletions lib/ObjModel.cs
Expand Up @@ -188,6 +188,9 @@ public struct MethodInfo {
public P6any impl;

public int flags;

public string file;
public int line;
}

public class DispatchSet {
Expand Down Expand Up @@ -390,16 +393,18 @@ public class DispatchSet {
}

public void AddMethod(int flags, string name, P6any code) {
MethodInfo mi;
AddMethodPos(flags, name, code, "???", 0);
}

public void AddMethodPos(int flags, string name, P6any code, string file, int line) {
MethodInfo mi = new MethodInfo();
//SubInfo si = (SubInfo) code.GetSlot("info");
mi.impl = code;
mi.short_name = name;
mi.long_name = name;
// XXX
if ((flags & M_MASK) == 0 && code.mo.name == "Regex" &&
name.IndexOf(':') >= 0) {
flags |= M_MULTI;
}
mi.file = file;
mi.line = line;

if ((flags & M_MASK) != 0) {
if ((flags & M_MASK) == M_PROTO) {
mi.long_name = mi.long_name + ":(proto)";
Expand Down
29 changes: 7 additions & 22 deletions src/NieczaBackendDotnet.pm6
Expand Up @@ -85,36 +85,16 @@ method post_save($name, :$main) {
}

class StaticSub {
method FALLBACK($name, *@args) { downcall("sub_$name", self, @args) }

method lex_names() { downcall("lex_names", self) }
method lookup_lex($name, $file?, $line?) {
downcall("sub_lookup_lex", self, $name, $file, $line//0);
}
method set_outervar($v) { downcall("sub_set_outervar", self, $v) }
method set_class($n) { downcall("sub_set_class", self, ~$n) }
method set_name($v) { downcall("sub_set_name", self, ~$v) }
method set_methodof($m) { downcall("sub_set_methodof", self, $m) }
method set_in_class($m) { downcall("sub_set_in_class", self, $m) }
method set_cur_pkg($m) { downcall("sub_set_cur_pkg", self, $m) }
method set_body_of($m) { downcall("sub_set_body_of", self, $m) }

method name() { downcall("sub_name", self) }
method outer() { downcall("sub_outer", self) }
method class() { downcall("sub_class", self) }
method run_once() { downcall("sub_run_once", self) }
method cur_pkg() { downcall("sub_cur_pkg", self) }
method in_class() { downcall("sub_in_class", self) }
method body_of() { downcall("sub_body_of", self) }
method outervar() { downcall("sub_outervar", self) }
method methodof() { downcall("sub_methodof", self) }

method unused_lexicals() { downcall("unused_lexicals", self) }
method parameterize_topic() { downcall("sub_parameterize_topic", self) }
method unit() { downcall("sub_get_unit", self) }
method to_unit() { downcall("sub_to_unit", self) }
method is($o) { downcall("equal_handles", self, $o) }
method is_routine() { downcall("sub_is_routine", self) }
method has_lexical($name) { downcall("sub_has_lexical", self, $name) }
method lexical_used($name) { downcall("sub_lexical_used", self, $name) }

method set_signature($sig) {
my @args;
Expand Down Expand Up @@ -276,6 +256,11 @@ class StaticSub {

class Type {
method FALLBACK($name, *@args) { downcall("type_$name", self, @args) }

method add_method($mode, $name, $sub, :$file, :$line, :$pos) {
downcall("type_add_method", self, $mode, $name, $sub,
$file, $line, $pos);
}
}

class Unit {
Expand Down
118 changes: 107 additions & 11 deletions src/niecza
Expand Up @@ -20,6 +20,20 @@ use RxOp;
use Sig;
use STD;

augment grammar STD {
method trymop($f) {
my $*worry = sub ($m) { self.worry($m) };
state $fast = %*ENV<NIECZA_FAIL_FAST>;
if $fast {
$f();
} else {
unless try { $f(); True } {
self.sorry($!)
}
}
}
}

augment grammar STD::P6 {
rule package_def {
:my $longname;
Expand Down Expand Up @@ -319,6 +333,11 @@ method package_var($/, $slot, $name, $path) {
::Op::Lexical.new(|node($/), name => $slot);
}

method method_def ($/) {
$*CURLEX<!sub>.finish($<blockoid>.ast);
make ::Op::Lexical.new(|node($/), name => $*CURLEX<!sub>.outervar);
}

method blockoid($/) {
# XXX horrible cheat, but my data structures aren't up to the task of
# $::UNIT being a class body &c.
Expand Down Expand Up @@ -360,6 +379,72 @@ sub phaser($/, $ph, :$unique, :$topic, :$csp) {
make ::Op::StatementList.new;
}

method signature($/) {
if $<type_constraint> {
# ignore for now
}

if $<param_var> {
my $sig = Sig.new(params => [ ::Sig::Parameter.new(
name => ~$<param_var>, |$<param_var>.ast,
full_parcel => True) ]);
$*CURLEX<!sub>.set_signature($sig) if $*SIGNUM;
make $sig;
return;
}

my @p = map *.ast, @( $<parameter> );
my @ps = @( $<param_sep> );
my $ign = False;
loop (my $i = 0; $i < @p; $i++) {
@p[$i].multi_ignored = $ign;
if $i >= @ps {
} elsif defined @ps[$i].index(':') {
$/.CURSOR.sorry('Only the first parameter may be invocant') if $i;
$*CURLEX<!sub>.add_my_name('self', :noinit, |mnode($/));
@p[$i].invocant = True;
} elsif defined @ps[$i].index(';;') {
$ign = True;
} elsif !defined @ps[$i].index(',') {
$/.CURSOR.sorry("Parameter separator @ps[$i] NYI");
}
}

state %mlike = (:Method, :Submethod, :Regex);
if $*SIGNUM && %mlike{$*CURLEX<!sub>.class} && (!@p || !@p[0].invocant) {
$*CURLEX<!sub>.add_my_name('self', :noinit, |mnode($/));
unshift @p, ::Sig::Parameter.new(name => 'self', :invocant);
}

for @p {
if !defined(.tclass) && $*SIGNUM {
if .invocant && $*CURLEX<!sub>.methodof {
my $cl = $*CURLEX<!sub>.methodof;
# XXX type checking against roles NYI
if $cl.kind eq none <role prole> {
.tclass = $cl;
}
} elsif !$*CURLEX<!sub>.is_routine {
.tclass = $*CURLEX<!sub>.compile_get_pkg('Mu');
}
}
}

my $sig = Sig.new(params => @p);
$*CURLEX<!sub>.set_signature($sig) if $*SIGNUM;
make $sig;
}

method pblock($/) {
#my $rw = $<lambda> && $<lambda> eq '<->'; TODO
$*CURLEX<!sub>.finish($<blockoid>.ast);
make $*CURLEX<!sub>;
}

method block($/) {
$*CURLEX<!sub>.finish($<blockoid>.ast);
make $*CURLEX<!sub>
}

method install_sub($/, $sub, :$multiness is copy, :$scope is copy, :$class,
:$longname, :$method_type is copy, :$contextual is copy) {
Expand Down Expand Up @@ -429,8 +514,8 @@ method install_sub($/, $sub, :$multiness is copy, :$scope is copy, :$class,
$method_type = Str;
}

if $method_targ && !$method_targ.can_add_method {
$/.CURSOR.sorry("A {$method_targ.WHAT} cannot have methods added");
if $method_targ && !$method_targ.CAN('add_method') {
$/.CURSOR.sorry("A {$method_targ.kind} cannot have methods added");
$method_type = Str;
$method_targ = Any;
}
Expand Down Expand Up @@ -496,18 +581,29 @@ method install_sub($/, $sub, :$multiness is copy, :$scope is copy, :$class,
}

if defined($method_type) {
if $sub.outer.augment_hack {
push $sub.outer.augment_hack,
[ $multiness, $method_type, $name, $symbol, $sub.xref ];
my $mode = 0;
given $method_type {
when 'sub' { $mode += 2 }
when 'normal' { $mode += 0 }
when 'private' { $mode += 1 }
default { die "Unimplemented method type $_" }
}
given $multiness {
when 'only' { $mode += 0 }
when 'proto' { $mode += 4 }
when 'multi' { $mode += 8 }
default { die "Unimplemented multiness $_" }
}
if defined $*AUGMENT_BUFFER {
push $*AUGMENT_BUFFER, $mode, $name, $symbol;
} else {
$method_targ.add_method($multiness, $method_type, $name,
$symbol, $sub.xref, |mnode($/));
$method_targ.add_method($mode, $name, $sub, |mnode($/));
}
}

if $scope eq 'our' {
$*unit.bind($pkg // $*unit.deref($sub.outer.cur_pkg),
"&$name", $sub.xref);
$*unit.bind(($pkg // $sub.outer.cur_pkg).who,
"&$name", $sub);
}
});
}
Expand Down Expand Up @@ -645,7 +741,7 @@ method do_new_package($/, :$sub = $*CURLEX<!sub>, :$scope!, :$name!, :$class!,
$/.CURSOR.trymop({
my $old;
if $scope ne 'anon' && !$pkg && $sub.has_lexical($head) {
my @linfo = $sub.lookup_lex(head);
my @linfo = $sub.lookup_lex($head);
die "Cannot resume definition - $head not a packageoid"
unless @linfo[0] eq 'package';
$old = @linfo[4];
Expand All @@ -655,7 +751,7 @@ method do_new_package($/, :$sub = $*CURLEX<!sub>, :$scope!, :$name!, :$class!,

my $lexed_already;

if $old && ($old.?kind // '') eq $class && !$old.closed {
if $old && $old.kind eq $class && !$old.closed {
$npkg = $old;
$lexed_already = True;
} elsif $scope eq 'our' {
Expand Down

0 comments on commit 8579c2d

Please sign in to comment.