[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