1
0
Fork 0

Protected trait methods are now mixed in

perfodd
Mike Gerwitz 2014-01-23 01:15:53 -05:00
parent 3724b1bc0d
commit e44ac3190b
2 changed files with 34 additions and 20 deletions

View File

@ -38,7 +38,7 @@ Trait.extend = function( dfn )
// we need at least one abstract member in order to declare a class as // we need at least one abstract member in order to declare a class as
// abstract (in this case, our trait class), so let's create a dummy one // abstract (in this case, our trait class), so let's create a dummy one
// just in case DFN does not contain any abstract members itself // just in case DFN does not contain any abstract members itself
dfn[ 'abstract protected __$$trait$$' ] = []; dfn[ 'abstract protected ___$$trait$$' ] = [];
function TraitType() function TraitType()
{ {
@ -88,7 +88,7 @@ function createConcrete( acls )
{ {
// start by providing a concrete implementation for our dummy method // start by providing a concrete implementation for our dummy method
var dfn = { var dfn = {
'protected __$$trait$$': function() {}, 'protected ___$$trait$$': function() {},
}; };
// TODO: everything else // TODO: everything else
@ -111,44 +111,59 @@ function mixin( trait, dfn )
{ {
// the abstract class hidden within the trait // the abstract class hidden within the trait
var acls = trait.__acls, var acls = trait.__acls,
methods = acls.___$$methods$$, methods = acls.___$$methods$$;
pub = methods['public'];
// retrieve the private member name that will contain this trait object // retrieve the private member name that will contain this trait object
var iname = addTraitInst( trait.__ccls, dfn ); var iname = addTraitInst( trait.__ccls, dfn );
// TODO: protected; ignore abstract mixMethods( methods['public'], dfn, 'public', iname );
for ( var f in pub ) mixMethods( methods['protected'], dfn, 'protected', iname );
return dfn;
}
/**
* Mix methods from SRC into DEST using proxies
*
* @param {Object} src visibility object to scavenge from
* @param {Object} dest destination definition object
* @param {string} vis visibility modifier
* @param {string} ianem proxy destination (trait instance)
*
* @return {undefined}
*/
function mixMethods( src, dest, vis, iname )
{
// TODO: ignore abstract
for ( var f in src )
{ {
if ( !( Object.hasOwnProperty.call( pub, f ) ) ) if ( !( Object.hasOwnProperty.call( src, f ) ) )
{ {
continue; continue;
} }
// TODO: this is a kluge; we'll use proper reflection eventually, // TODO: this is a kluge; we'll use proper reflection eventually,
// but for now, this is how we determine if this is an actual public // but for now, this is how we determine if this is an actual method
// method vs. something that just happens to be on the public // vs. something that just happens to be on the visibility object
// visibility object if ( !( src[ f ].___$$keywords$$ ) || f === '___$$trait$$' )
if ( !( pub[ f ].___$$keywords$$ ) )
{ {
continue; continue;
} }
var pname = 'public proxy ' + f; var pname = vis + ' proxy ' + f;
// if we have already set up a proxy for a field of this name, then // if we have already set up a proxy for a field of this name, then
// multiple traits have defined the same concrete member // multiple traits have defined the same concrete member
if ( dfn[ pname ] !== undefined ) if ( dest[ pname ] !== undefined )
{ {
// TODO: between what traits? // TODO: between what traits?
throw Error( "Trait member conflict: `" + f + "'" ); throw Error( "Trait member conflict: `" + f + "'" );
} }
// proxy this method to what will be the encapsulated trait object // proxy this method to what will be the encapsulated trait object
dfn[ pname ] = iname; dest[ pname ] = iname;
} }
return dfn;
} }

View File

@ -45,18 +45,17 @@ require( 'common' ).testCase(
], ],
// should (at least for the time being) be picked up by existing // should (at least for the time being) be picked up by existing
// class error checks // class error checks; TODO: but let's provide trait-specific
// error messages to avoid frustration and infuriation
[ 'foo', "varying keywords; same visibility", [ 'foo', "varying keywords; same visibility",
{ 'virtual public foo': function() {} }, { 'virtual public foo': function() {} },
{ 'public virtual foo': function() {} }, { 'public virtual foo': function() {} },
], ],
/* TODO
[ 'foo', "different visibility", [ 'foo', "different visibility",
{ 'public foo': function() {} }, { 'public foo': function() {} },
{ 'protected foo': function() {} }, { 'protected foo': function() {} },
], ],
*/
]; ];
}, },
@ -234,7 +233,7 @@ require( 'common' ).testCase(
// caused the error // caused the error
this.assertOk( this.assertOk(
e.message.match( '\\b' + fname + '\\b' ), e.message.match( '\\b' + fname + '\\b' ),
"Missing field name" "Error message missing field name: " + e.message
); );
// TODO: we can also make less people hate us if we include the // TODO: we can also make less people hate us if we include the