[nem-en] [macro] building event member
Kamil Skalski
kamil.skalski at gmail.com
Thu Mar 8 21:01:05 CET 2007
Defining events in quotations is a bit broken (AFAIR there is no bug
report for this, but we definately should have one). In my project I
use following (very workaround-ish) method:
module State {
public mutable definedEventAndTrigger :
Nemerle.Collections.Hashtable[string,bool] =
Nemerle.Collections.Hashtable();
}
[Nemerle.MacroUsage (Nemerle.MacroPhase.BeforeInheritance,
Nemerle.MacroTargets.Class)]
macro GenerateEventAndTrigger (delegat : TypeBuilder, name : string = null)
{
def name = if (name != null) name else delegat.Name + "d";
unless (State.definedEventAndTrigger.Contains (name)) {
def fldname = Macros.UseSiteSymbol (delegat.Name + "_fld");
(delegat.DeclaringType :> TypeBuilder).Define (<[ decl:
public event $(name : usesite) : $(delegat.ParsedName : name)
{
add { lock (this) { this.$(fldname : name) += value } }
remove { lock (this) { this.$(fldname : name) -= value } }
}
]> );
(delegat.DeclaringType :> TypeBuilder).Define (<[ decl:
private mutable $(fldname : name) : $(delegat.ParsedName : name);
]>);
foreach (meth is Parsetree.ClassMember.Function when
meth.header.name.GetIdentifier() == "Invoke" in
delegat.GetParsedMembers()) {
def references = meth.header.parms.Map (fun (p) {
<[ $(p.name.GetName() : name) ]>
});
(delegat.DeclaringType :> TypeBuilder).Define (<[ decl:
private $("trigger" + name : usesite) (..$(meth.header.parms)) : void {
when ($(fldname : name) != null)
$(fldname : name) (..$references);
}
]>);
}
}
State.definedEventAndTrigger[name] = true;
}
The problem is that if you define
<[ decl: event Foo : Delegat; ]>
compiler generates various additional things:
- field to contain added delegated
- add_Foo method
- remove_Foo method
and this is currently broken for events added in quotations
2007/3/8, Sergey Shishmintzev <sergey.shishmintzev at gmail.com>:
> // Code:
> [Nemerle.MacroUsage (Nemerle.MacroPhase.BeforeInheritance,
> Nemerle.MacroTargets.Field,
> Inherited = false, AllowMultiple = true)]
> macro ModelAccessor (current_type : TypeBuilder, pf : ParsedField,
> params _ : list [PExpr])
> {
> mutable attributes = [];
> def propAttrs = Modifiers (NemerleAttributes.None, attributes);
> def x = <[ decl: ..$propAttrs event $(pf.Name+"Changed" : dyn) :
> Handler; ]>;
> x.Attributes = NemerleAttributes.Public;
> current_type.Define(x);
> }
> // Usage:
> public class Model1
> {
> public delegate Handler(_ : object) : void;
> [ModelAccessor]
> private mutable field1 : bool;
> [ModelAccessor]
> private mutable field2 : bool;
> }
>
> Problem:
> // ncc's messages:
> positive/macroprog.n:267:4:267:17: error: field `Model1._N_1790'
> redefined in `Model1'
> positive/macroprog.n:265:4:265:17: error: first definition here as
> field `Model1._N_1790'
> positive/macroprog.n:267:4:267:17: error: redefinition of method
> Model1.add_(value : Model1.Handler) : void
> positive/macroprog.n:267:4:267:17: error: redefinition of method
> Model1.remove_(value : Model1.Handler) : void
>
> I can suggest add Parsetree.Splicable.Combine { names :
> list[Splicable] } (or { n1 : Splicable; n2 : Splicabel }) option and
> use it to build add_*/remove_* names. But I unsure.
>
> --
> Serg
>
> _______________________________________________
> https://nemerle.org/mailman/listinfo/devel-en
>
--
Kamil Skalski
http://nazgul.omega.pl
More information about the devel-en
mailing list