[REBOL] Re: REBOL -> C#
From: AJMartin::orcon::net::nz at: 24-Jan-2004 11:45
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/