Skip to content

Instantly share code, notes, and snippets.

@aaronpowell
Created March 2, 2011 12:55
Show Gist options
  • Save aaronpowell/850881 to your computer and use it in GitHub Desktop.
Save aaronpowell/850881 to your computer and use it in GitHub Desktop.
A macro to convert a field to a property, also adds c#-esq naming
namespace Boo.Lang.Extensions
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
macro field:
case [| field $name as $type |]:
backingField = ReferenceExpression("_$name")
fn = "$name"[0].ToString().ToUpper() + "$name".Substring(1)
yield [|
private $backingField as $type
|]
yield [|
public $fn as $type:
get: return $backingField
set: $backingField = value
|]
yield [|
public $name as $type:
get: return $backingField
set: $backingField = value
|]
public class FieldMacro : AbstractAstMacro
{
public override Statement Expand(MacroStatement macro)
{
if (macro.Arguments.Count == 1)
{
var tryCastExpression = (TryCastExpression)macro.Arguments.First;
var referenceExpression = (ReferenceExpression)tryCastExpression.Target;
var property = new Property(referenceExpression.Name)
{
LexicalInfo = macro.LexicalInfo,
Getter = new Method(),
Setter = new Method()
};
var field = new Field(
tryCastExpression.Type.LexicalInfo
)
{
Name = "_" + referenceExpression.Name,
Modifiers = TypeMemberModifiers.Private,
Type = tryCastExpression.Type
};
property.Getter.Body.Add(
new ReturnStatement(LexicalInfo.Empty)
{
Expression = Expression.Lift(field)
}
);
property.Setter.Body.Add(
new BinaryExpression(LexicalInfo.Empty)
{
Operator = BinaryOperatorType.Assign,
Left = Expression.Lift(field),
Right = new ReferenceExpression(LexicalInfo.Empty) { Name = "value" }
}
);
var clazz = (ClassDefinition)macro.GetAncestor(NodeType.ClassDefinition);
clazz.Members.Add(field);
clazz.Members.Add(property);
return null;
}
CompilerErrorFactory.CustomError(macro.LexicalInfo,
string.Format("{0} must be used like: '{0} foo as type'",
macro.Name));
return null;
}
}
field Title as string
field Body as Html
field HeroImage as Uri
@mythz
Copy link

mythz commented Mar 2, 2011

Yeah that's very nice, but when would you use this beast?

@aaronpowell
Copy link
Author

Defining types in boo that i want to push into ravendb. You don't need to do the camel-casing, I just wanted it for better .NET API

@mythz
Copy link

mythz commented Mar 2, 2011

yeah makes sense. Note: think you should also provide example code (i.e. in the comments) of how you would use this in anger.
i.e. does it look like?:

class MyType: 
  field intField as int
  field stringField as string

@aaronpowell
Copy link
Author

Yep that's basically it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment