Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of github.com:bamboo/boo-extensions

  • Loading branch information...
commit eaa6b8f11f660b0098c34b1aaf6a87301d589e5a 2 parents cb9a32a + 6f70d41
@bamboo authored
Showing with 57 additions and 16 deletions.
  1. +21 −2 src/Boo.Adt.Tests/DataMacroTest.boo
  2. +36 −14 src/Boo.Adt/DataMacro.boo
View
23 src/Boo.Adt.Tests/DataMacroTest.boo
@@ -3,6 +3,8 @@ namespace Boo.Adt.Tests
import NUnit.Framework
import Boo.Adt
+# algebraic data types dsl
+# omitted types default to base type (the type to the left of =)
data Expression = Const(value as int) \
| Add(left as Expression, right)
@@ -10,9 +12,11 @@ data ExpressionX < Expression = Mult(left as Expression, right as Expression)
data Result(Value as int) = Success() | Failure(Error as string)
-data Foo(Value as int)
+# data extension dsl
+# omitted types default to object
+data Foo(Value)
-#data Bar(Value as int, Count as int) < Foo(Value)
+data Bar(Value, Count as int) < Foo(Value)
data Struct(Value as int) < System.ValueType
@@ -20,6 +24,21 @@ data Struct(Value as int) < System.ValueType
class DataMacroTest:
[Test]
+ def DataExtensionArguments():
+ bar = Bar(21, 42)
+ foo as Foo = bar
+ Assert.AreEqual(bar.Value, foo.Value)
+ Assert.AreEqual(42, bar.Count)
+
+ [Test]
+ def DataExtensionOmittedParametersDefaultToObject():
+ Assert.AreEqual((object,), ConstructorParameterTypesOf(Foo))
+ Assert.AreEqual((object, int), ConstructorParameterTypesOf(Bar))
+
+ def ConstructorParameterTypesOf(type as System.Type):
+ return array(p.ParameterType for p in type.GetConstructors()[0].GetParameters())
+
+ [Test]
def ValueTypeBaseType():
assert typeof(Struct).IsValueType
View
50 src/Boo.Adt/DataMacro.boo
@@ -1,5 +1,6 @@
namespace Boo.Adt
+import System.Linq
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast
import Boo.Lang.PatternMatching
@@ -29,6 +30,7 @@ class DataMacroExpansion:
_module as TypeDefinition
_superType as TypeDefinition
_superTypeRef as TypeReference
+ _defaultTypeRef as TypeReference
def constructor(node as MacroStatement):
@@ -41,6 +43,12 @@ class DataMacroExpansion:
_superType = createBaseType(left)
expandDataConstructors(right)
+ case [| $(ctor=MethodInvocationExpression()) < $(superCtor=MethodInvocationExpression()) |]:
+ _defaultTypeRef = SimpleTypeReference("object")
+ _superType = ClassDefinition()
+ _superTypeRef = TypeReference.Lift(superCtor.Target)
+ expandDataConstructorWithSuperCtor(ctor, superCtor, node.Body)
+
case [| $(ctor=MethodInvocationExpression()) < $superType |]:
_superTypeRef = TypeReference.Lift(superType)
_superType = ClassDefinition()
@@ -53,9 +61,6 @@ class DataMacroExpansion:
|]
expandDataConstructorWithBody(ctor, node.Body)
- def expandDataConstructorWithBody(ctor as Expression, body as Block):
- expandDataConstructor(ctor).Members.Extend(TypeMember.Lift(body))
-
def createBaseType(node as Expression):
type = superTypeForExpression(node)
type.LexicalInfo = node.LexicalInfo
@@ -114,15 +119,32 @@ class DataMacroExpansion:
case MethodInvocationExpression():
expandDataConstructor(node)
+ def expandDataConstructorWithBody(ctor as Expression, body as Block):
+ expandDataConstructor(ctor).Members.Extend(TypeMember.Lift(body))
+
+ def expandDataConstructorWithSuperCtor(ctor as Expression, superCtor as Expression, body as Block):
+ superFields = fieldsFrom(superCtor)
+ superFieldNames = array(f.Name for f in superFields)
+ ctorFields = fieldsFrom(ctor)
+ fields = array(f for f in ctorFields if f.Name not in superFieldNames)
+ expandDataConstructorWithFields(ctor, ctorFields, fields, superFields).Members.Extend(TypeMember.Lift(body))
+
def expandDataConstructor(node as MethodInvocationExpression):
+ fields = fieldsFrom(node)
+ superFields = fieldsOf(_superType).ToArray()
+ ctorFields = superFields + fields
+ return expandDataConstructorWithFields(node, ctorFields, fields, superFields)
+
+ def expandDataConstructorWithFields(node as MethodInvocationExpression, ctorFields as (Field), fields as (Field), superFields as Field*):
type = dataConstructorTypeForExpression(node.Target)
type.LexicalInfo = node.LexicalInfo
- type.Members.Extend(fields = fieldsFrom(node))
+ type.Members.Extend(fields)
type.Members.Add(toStringForType(type))
type.Members.Add(equalsForType(type))
- ctor = constructorForFields(fields)
- addSuperInvocationTo ctor
+ ctor = constructorDeclarationFor(ctorFields)
+ for field in fields: ctor.Body.Add([| self.$(field.Name) = $field |])
+ addSuperInvocationTo ctor, superFields
type.Members.Add(ctor)
for ctor in constructorsWithDefaultValues(fields):
@@ -131,12 +153,9 @@ class DataMacroExpansion:
registerType(type)
return type
- def addSuperInvocationTo(ctor as Constructor):
+ def addSuperInvocationTo(ctor as Constructor, superFields as Field*):
superInvocation = [| super() |]
- i = 0
- for field as Field in fieldsOf(_superType):
- ctor.Parameters.Insert(i++,
- ParameterDeclaration(Name: field.Name, Type: field.Type))
+ for field in superFields:
superInvocation.Arguments.Add(ReferenceExpression(field.Name))
ctor.Body.Insert(0, superInvocation)
@@ -203,10 +222,10 @@ class DataMacroExpansion:
return [| Boo.Adt.adtFieldToString(self.$(field.Name)) |]
def fieldsIncludingBaseType(type as TypeDefinition):
- return cat(fieldsOf(_superType), fieldsOf(type))
+ return fieldsOf(_superType).Concat(fieldsOf(type))
def fieldsOf(type as TypeDefinition):
- return type.Members.Select(NodeType.Field)
+ return type.Members.OfType of Field()
def constructorForFields(fields as (Field)):
ctor = constructorDeclarationFor(fields)
@@ -261,7 +280,10 @@ class DataMacroExpansion:
f.Annotate("DefaultValue", defaultValue)
return f
case ReferenceExpression(Name: name):
- return fieldWith(name, superTypeRef())
+ return fieldWith(name, defaultTypeRef())
+
+ def defaultTypeRef():
+ return _defaultTypeRef or superTypeRef()
def arrayField(name as string, arrayType as ArrayTypeReference):
field = fieldWith(name, arrayType)
Please sign in to comment.
Something went wrong with that request. Please try again.