Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

REBOL -> C# (was: Re: Re: starting to be really late!?)

 [1/2] from: gosbell::myrealbox::com at: 8-Jan-2004 16:26


OK, I'll bite - please tell us more about REBOL -> C#. Thanks, Trevor.

 [2/2] from: AJMartin::orcon::net::nz at: 24-Jan-2004 11:45

Re: REBOL -> C#


Trevor wrote:
> OK, I'll bite - please tell us more about REBOL -> C#.
First I wrote some programs in C# to get to know the language. Then I realised that I was repeating a lot of information in each source file and that I wasn't able to keep all the source files up to date accurately and reliably. So I designed a Rebol dialect and it's associated interpreter in Rebol to generate the C# code for me. As I repeated this process, I discovered I could embed C# inside the Rebol dialect. This then allowed me to automatically generate classes and their associated support classes just from a basic description expressed as Rebol values, along with some specific C# code stored inside a string value. For example, here's my Rebol dialect for expressing a Person class: Person: "Person's details." [ Honourific: Honourific Global/Mesh/Honourifics Forename: string Surname: string Nickname: string Gender: Gender Relations: many Relation Birthday: DateTime Residence: Residence Global/Mesh/Residences Cellphone: Cellphone Global/Mesh/Cellphones Address: Address Global/Mesh/Addresses Email: many Email this: { public string Age { get { if (0 != birthday.Ticks) { int Days, Months, Years; DateTime Now = DateTime.Now; DateTime Birth = Birthday; Days = Now.Day - Birth.Day; if (Days < 0) { Months = Birth.Month + 1; Years = Birth.Year; if (12 < Months) { Months = 1; Years++; } DateTime n = new DateTime (Years, Months, 1); Days = (n - Birth).Days + Now.Day - 1; Birth = n; } Months = Now.Month - Birth.Month; Years = Now.Year - Birth.Year; if (Months < 0) { Months = Months + 12; Years = Years - 1; } return Years + " years, " + Months + " months, " + Days + " days."; } return ""; } } public override string ToString () { return Forename + " " + Surname; } } ] Note that the above class refers to several other classes. After processing by my Rebol dialect interpreter, the above description gets expanded into several C# classes. Like this: [Serializable] [TypeConverter (typeof (PersonConverter))] public class Person { public string DisplayName () { return "Person"; } public string Description () { return "Person's details."; } [Editor (typeof (HonourificEditor), typeof(UITypeEditor))] [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public Honourific Honourific { get {return honourific;} set {honourific = value;} } Honourific honourific; [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public string Forename { get {return forename;} set {forename = value;} } string forename; [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public string Surname { get {return surname;} set {surname = value;} } string surname; [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public string Nickname { get {return nickname;} set {nickname = value;} } string nickname; [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public Gender Gender { get {return gender;} set {gender = value;} } Gender gender; [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public RelationCollection Relations { get {return relations;} set {relations = value;} } RelationCollection relations = new RelationCollection (); [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public DateTime Birthday { get {return birthday;} set {birthday = value;} } DateTime birthday; [Editor (typeof (ResidenceEditor), typeof(UITypeEditor))] [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public Residence Residence { get {return residence;} set {residence = value;} } Residence residence; [Editor (typeof (CellphoneEditor), typeof(UITypeEditor))] [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public Cellphone Cellphone { get {return cellphone;} set {cellphone = value;} } Cellphone cellphone; [Editor (typeof (AddressEditor), typeof(UITypeEditor))] [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public Address Address { get {return address;} set {address = value;} } Address address; [RefreshProperties (RefreshProperties.All)] [NotifyParentProperty (true)] public EmailCollection Email { get {return email;} set {email = value;} } EmailCollection email = new EmailCollection (); public string Age { get { if (0 != birthday.Ticks) { int Days, Months, Years; DateTime Now = DateTime.Now; DateTime Birth = Birthday; Days = Now.Day - Birth.Day; if (Days < 0) { Months = Birth.Month + 1; Years = Birth.Year; if (12 < Months) { Months = 1; Years++; } DateTime n = new DateTime (Years, Months, 1); Days = (n - Birth).Days + Now.Day - 1; Birth = n; } Months = Now.Month - Birth.Month; Years = Now.Year - Birth.Year; if (Months < 0) { Months = Months + 12; Years = Years - 1; } return Years + " years, " + Months + " months, " + Days + " days."; } return ""; } } public override string ToString () { return Forename + " " + Surname; } public Person () { } } [Serializable, TypeConverterAttribute (typeof (PersonCollectionConverter))] public class PersonCollection : CollectionBase, ICustomTypeDescriptor { public int Add (Person s) { return (List.Add (s)); } public int IndexOf (Person s) { return (List.IndexOf (s)); } public void Insert (int Index, Person s) { List.Insert (Index, s); } public void Remove (Person s) { List.Remove (s); } public bool Contains (Person s) { return (List.Contains (s)); } public Person this [int index] { get {return (Person)List[index];} set {List[index] = value;} } public static PersonCollection operator + (PersonCollection p, Person s) { p.Add (s); return p; } public String GetClassName() { return TypeDescriptor.GetClassName(this,true); } public AttributeCollection GetAttributes() { return TypeDescriptor.GetAttributes(this,true); } public String GetComponentName() { return TypeDescriptor.GetComponentName(this, true); } public TypeConverter GetConverter() { return TypeDescriptor.GetConverter(this, true); } public EventDescriptor GetDefaultEvent() { return TypeDescriptor.GetDefaultEvent(this, true); } public PropertyDescriptor GetDefaultProperty() { return TypeDescriptor.GetDefaultProperty(this, true); } public object GetEditor(Type editorBaseType) { return TypeDescriptor.GetEditor(this, editorBaseType, true); } public EventDescriptorCollection GetEvents(Attribute[] attributes) { return TypeDescriptor.GetEvents(this, attributes, true); } public EventDescriptorCollection GetEvents() { return TypeDescriptor.GetEvents(this, true); } public object GetPropertyOwner(PropertyDescriptor pd) { return this; } public PropertyDescriptorCollection GetProperties(Attribute[] attributes) { return GetProperties(); } public PropertyDescriptorCollection GetProperties () { PropertyDescriptorCollection pdc = new PropertyDescriptorCollection (null); for (int i = 0; i < List.Count; i++) { PersonCollectionPropertyDescriptor pd = new PersonCollectionPropertyDescriptor (this, i); pdc.Add (pd); } return pdc; } } public class PersonConverter : ExpandableObjectConverter { public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof (Person)) { return true; } return base.CanConvertTo (context, destinationType); } public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof (System.String) && value is Person) { } return base.ConvertTo (context, culture, value, destinationType); } } public class PersonCollectionConverter : ExpandableObjectConverter { public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType) { if (destinationType == typeof (PersonCollection)) { return true; } return base.CanConvertTo (context, destinationType); } public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType == typeof (System.String) && value is PersonCollection) { } return base.ConvertTo (context, culture, value, destinationType); } } // [Editor (typeof (PersonEditor), typeof(UITypeEditor))] public class PersonEditor : UITypeEditor { public override UITypeEditorEditStyle GetEditStyle (ITypeDescriptorContext context) { if (null != context && null != context.Instance) { return UITypeEditorEditStyle.Modal; } return UITypeEditorEditStyle.None; } public override object EditValue (ITypeDescriptorContext context, IServiceProvider provider, object value) { if (null != context && null != context.Instance && null != provider) { if (0 < Global.Mesh.Persons.Count) { CollectionPicker p = new CollectionPicker (value, Global.Mesh.Persons, Person ); if (DialogResult.OK == p.ShowDialog ()) { return p.Picked; } } else { CollectionEditor ce = new CollectionEditor (Global.Mesh.Persons.GetType ()); return ce.EditValue (context, provider, Global.Mesh.Persons); } } return value; } } public class PersonCollectionPropertyDescriptor : PropertyDescriptor { PersonCollection personcollection = null; int index = -1; public PersonCollectionPropertyDescriptor (PersonCollection PersonCollection, int Index) : base ("#" + Index, null) { personcollection = PersonCollection; index = Index; } public override AttributeCollection Attributes { get {return new AttributeCollection (null);} } public override bool CanResetValue (object component) { return true; } public override Type ComponentType { get {return personcollection.GetType ();} } public override string DisplayName { get {return personcollection[index].DisplayName ();} } public override string Description { get {return personcollection[index].Description ();} } public override object GetValue (object component) { return personcollection[index]; } public override bool IsReadOnly { get {return false;} } public override string Name { get {return "#" + index;} } public override Type PropertyType { get {return personcollection[index].GetType ();} } public override bool ShouldSerializeValue (object component) { return true; } public override void ResetValue (object component) { // Do nothing. } public override void SetValue (object component, object value) { // Do nothing. // personcollection[index] = value; } } Naturally the Rebol description is far easier to expand, maintain, verify and correct than the C# equivalent. Andrew J Martin Speaking in tongues and performing miracles. ICQ: 26227169 http://www.rebol.it/Valley/ http://valley.orcon.net.nz/ http://Valley.150m.com/