Permalink
Browse files

Implement "trusts" and checking thereof

  • Loading branch information...
1 parent c3a0699 commit 0d27950c8159243f217a4119c9201c529a0873fa @sorear committed Jan 11, 2012
Showing with 138 additions and 3 deletions.
  1. +11 −0 lib/CodeGen.cs
  2. +3 −2 lib/ObjModel.cs
  3. +1 −1 lib/Serialize.cs
  4. +122 −0 src/niecza
  5. +1 −0 t/spectest.data
View
@@ -4235,6 +4235,17 @@ public class DowncallReceiver : CallReceiver {
add_to.mo.roleFactory = block.protosub;
return null;
}
+ public static object type_add_trustee(object[] args) {
+ STable st = (STable)Handle.Unbox(args[1]);
+ STable nw = (STable)Handle.Unbox(args[2]);
+ st.mo.trustees.Add(nw);
+ return null;
+ }
+ public static object type_trusts(object[] args) {
+ STable st = (STable)Handle.Unbox(args[1]);
+ STable nw = (STable)Handle.Unbox(args[2]);
+ return st == nw || st.mo.trustees.Contains(nw);
+ }
public static object type_closed(object[] args) {
STable st = (STable)Handle.Unbox(args[1]);
return st.mo.isComposed;
View
@@ -162,6 +162,7 @@ public class P6how: IFreeze, IFixup {
public List<MethodInfo> lmethods = new List<MethodInfo>();
public List<AttrInfo> local_attr = new List<AttrInfo>();
+ public List<STable> trustees = new List<STable>();
public List<STable> superclasses = new List<STable>();
public List<STable> local_roles = new List<STable>();
public List<STable> role_typecheck_list = new List<STable>();
@@ -180,8 +181,6 @@ public class P6how: IFreeze, IFixup {
public HashSet<STable> type_set = new HashSet<STable>();
internal SubscriberSet subclasses = new SubscriberSet();
Subscription[] mro_sub;
- // role type objects have an empty MRO cache so no methods can be
- // called against them; the fallback (NYI) is to pun.
// }}}
// types and constants {{{
@@ -757,6 +756,7 @@ public class DispatchSet {
fb.Refs<STable>(local_roles);
fb.Refs<STable>(role_typecheck_list);
fb.Refs<STable>(mro);
+ fb.Refs<STable>(trustees);
}
internal static P6how Thaw(ThawBuffer tb) {
@@ -808,6 +808,7 @@ public class DispatchSet {
n.local_roles = tb.RefsL<STable>();
n.role_typecheck_list = tb.RefsL<STable>();
n.mro = tb.RefsA<STable>();
+ n.trustees = tb.RefsL<STable>();
tb.PushFixup(n);
return n;
}
View
@@ -64,7 +64,7 @@ struct ObjRef {
internal static HashAlgorithm NewHash() { return new SHA256Managed(); }
static readonly string signature = "Niecza-Serialized-Module";
- static readonly int version = 19;
+ static readonly int version = 20;
// Routines for use by serialization code
public bool CheckWriteObject(SerUnit into, object o,
View
@@ -26,6 +26,128 @@ use STD;
# }
augment class NieczaActions {
+method package_declarator:trusts ($/) {
+ if defined $<module_name>.ast<args> {
+ $/.CURSOR.sorry("Cannot trust a specific role instance");
+ }
+ my ($trustee) = self.process_name($<module_name><longname>);
+ $/.CURSOR.trymop({
+ $*CURLEX<!sub>.cur_pkg.add_trustee($trustee) if $trustee;
+ });
+ make ::Op::StatementList.new;
+}
+
+method do_variable_reference($M, $v) {
+ if $v<term> {
+ return $v<term>;
+ }
+
+ my $tw = $v<twigil>;
+ my $sl = $v<sigil> ~ $tw ~ $v<name>;
+ my $list = $v<sigil> eq '@';
+ my $hash = $v<sigil> eq '%';
+
+ if defined($v<pkg>) && $tw ~~ /<[*=~?^:]>/ {
+ $M.CURSOR.sorry("Twigil $tw cannot be used with qualified names");
+ return ::Op::StatementList.new;
+ }
+
+ if $tw eq '!' {
+ my $pclass;
+ if $v<pkg> {
+ $pclass = $v<pkg>;
+ } elsif $*CURLEX<!sub>.in_class -> $c {
+ $pclass = $c;
+ } else {
+ $M.CURSOR.sorry("Cannot resolve class for private method");
+ }
+ if $pclass && !$pclass.trusts($*CURLEX<!sub>.cur_pkg) {
+ $M.CURSOR.sorry("Cannot call private method '$v<name>' on $pclass.name() because it does not trust $*CURLEX<!sub>.cur_pkg.name()");
+ }
+ self.docontext($M, $v<sigil>, ::Op::CallMethod.new(|node($M),
+ name => $v<name>, private => True, receiver => mklex($M, 'self'),
+ :$pclass));
+ }
+ elsif $tw eq '.' {
+ if defined $v<pkg> {
+ $M.CURSOR.sorry('$.Foo::bar syntax NYI');
+ return ::Op::StatementList.new;
+ }
+
+ self.docontext($M, $v<sigil>, ::Op::CallMethod.new(|node($M),
+ name => $v<name>, receiver => mklex($M, 'self')));
+ }
+ # no twigil in lex name for these
+ elsif $tw eq '^' || $tw eq ':' {
+ mklex($M, $v<sigil> ~ $v<name>, :$hash, :$list);
+ }
+ elsif $tw eq '*' {
+ ::Op::ContextVar.new(|node($M), name => $sl);
+ }
+ elsif $tw eq '' || $tw eq '?' {
+ if defined($v<pkg>) {
+ self.package_var($M, self.gensym, $sl, $v<pkg>);
+ } elsif $tw eq '?' && $sl eq '$?POSITION' {
+ mkcall($M, '&infix:<..^>',
+ ::Op::Num.new(|node($M), value => [10, ~$M.from]),
+ ::Op::Num.new(|node($M), value => [10, ~$M.to]));
+ } elsif $tw eq '?' && $sl eq '$?LINE' {
+ ::Op::Num.new(|node($M), value => [10, ~$M.cursor.lineof($M.from)]);
+ } elsif $tw eq '?' && $sl eq '$?FILE' {
+ ::Op::StringLiteral.new(|node($M), text => $*FILE<name>);
+ } elsif $tw eq '?' && $sl eq '$?ORIG' {
+ ::Op::StringLiteral.new(|node($M), text => $M.orig);
+ } elsif $tw eq '?' && $sl eq '&?BLOCK' {
+ $*CURLEX<!sub>.noninlinable;
+ ::Op::GetBlock.new(|node($M))
+ } elsif $tw eq '?' && $sl eq '&?ROUTINE' {
+ $*CURLEX<!sub>.noninlinable;
+ ::Op::GetBlock.new(|node($M), :routine)
+ } else {
+ mklex($M, $sl, :$hash, :$list);
+ }
+ }
+ else {
+ $M.CURSOR.sorry("Unhandled reference twigil $tw");
+ }
+}
+}
+
+augment class Operator::Method {
+ method with_args($/, *@args) {
+ if $!name eq any(< HOW WHAT WHO VAR >) && !$!private && !$!meta {
+ if $!args {
+ $/.CURSOR.sorry("Interrogative operator $.name does not take arguments");
+ return ::Op::StatementList.new;
+ }
+ ::Op::Interrogative.new(|node($/), receiver => @args[0],
+ name => $.name);
+ } else {
+ $*CURLEX<!sub>.noninlinable if $!name eq 'eval';
+ my $pclass;
+ if $.private {
+ if $.package {
+ $pclass = $.package;
+ } elsif $*CURLEX<!sub>.in_class -> $c {
+ $pclass = $c;
+ } else {
+ $/.CURSOR.sorry("Cannot resolve class for private method");
+ }
+ if $pclass && !$pclass.trusts($*CURLEX<!sub>.cur_pkg) {
+ $/.CURSOR.sorry("Cannot call private method '$.name' on $pclass.name() because it does not trust $*CURLEX<!sub>.cur_pkg.name()");
+ }
+ } else {
+ $pclass = $.package;
+ }
+ ::Op::CallMethod.new(|node($/),
+ receiver => @args[0],
+ ismeta => $.meta,
+ name => $.name,
+ private => $.private,
+ pclass => $pclass,
+ args => [ @$.args ]);
+ }
+ }
}
# remove run_dispatch
View
@@ -360,6 +360,7 @@ S12-methods/indirect_notation.t
S12-methods/lvalue.t
S12-methods/private.t
S12-methods/topic.t
+S12-methods/trusts.t
S12-methods/typed-attributes.t
S12-methods/what.t
S12-subset/multi-dispatch.t

0 comments on commit 0d27950

Please sign in to comment.