Boo

New style generator macros

Details

  • Type: Improvement Improvement
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 0.8.2
  • Fix Version/s: 0.9
  • Component/s: None
  • Labels:
    None
  • Testcase included:
    yes
  • Number of attachments :
    0

Description

*) new style macros:
*) macros are generators for nodes (any kind)
*) type members are added to the enclosing type or module
*) expressions and statements are added to the enclosing block

example:

macro types:
            for typeName in types.Arguments:
                type = [|
                    class $typeName:
                        pass
                |]
                yield type

Activity

Hide
Cedric Vivier added a comment -

Landed in rev. 3055.
Re-assigned it to me as I was very motivated to do it this morning to be able to use this awesomeness in a project I'm currently working on, I hope you do not mind

To be fully backward-compatible the new syntax does not replace completely the old one but is a additional possibility on top of the old one (which was/is just good enough if the consumer is not interested to generated classes/members/etc...)

For the sake of documenting this JIRA issue I post the testcases here :

"""
Foo says hello!
Bar says hello!
Zap says hello!
"""

import Boo.Lang.Compiler

macro helloClasses:
	for typeName in helloClasses.Arguments:
		yield [|
			class $typeName:
				override def ToString() as string:
					return "${$typeName} says hello!"
		|]

helloClasses Foo, Bar, Zap

print Foo()
print Bar()
print Zap()
"""
bonjour
quoi de neuf?
a bientot!
"""

import Boo.Lang.Compiler

macro speak:
	for statement in speak.Block.Statements:
		s = cast(Ast.ExpressionStatement, statement).Expression as Ast.StringLiteralExpression
		if s.Value == "hello":
			yield [| print "bonjour" |]
		if s.Value == "whats up?":
			yield [| print "quoi de neuf?" |]
	yield [| print "a bientot!" |]

speak "french":
	"hello"
	"whats up?"
"""
DO>
<DO
Soviet Russia says hello to EnclosingClass+Foo!
Soviet Russia says hello to EnclosingClass+Bar!
Soviet Russia says hello to EnclosingClass+Zap!
Mission accomplished, nested classes, methods and fields are defeated!
"""

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast

macro mixed:

	yield cast(Field, [| (_i = 100) as int |])
	#expression used to to disambiguate from BinaryExpression/assignment within block.
	#another possibility: yield CodeBuilder.CreateField("_i", TypeSystemServices.IntType)

	for typeName in mixed.Arguments:
		yield [|
			class $typeName:
				_ec as EnclosingClass

				def constructor(ec as EnclosingClass):
					_ec = ec

				override def ToString() as string:
					_ec._i++
					return "Soviet Russia says hello to ${$typeName}!"
		|]

	yield [|
		def MissionAccomplished():
			if _i == 103: #because must have started at 100 if above cast OK
				print "Mission accomplished, nested classes, methods and fields are defeated!"
	|]


class EnclosingClass:
	def Do():
		print "DO>"
		mixed Foo, Bar, Zap
		print "<DO"


ec = EnclosingClass()
ec.Do()
print EnclosingClass.Foo(ec)
print EnclosingClass.Bar(ec)
print EnclosingClass.Zap(ec)
ec.MissionAccomplished()
Show
Cedric Vivier added a comment - Landed in rev. 3055. Re-assigned it to me as I was very motivated to do it this morning to be able to use this awesomeness in a project I'm currently working on, I hope you do not mind To be fully backward-compatible the new syntax does not replace completely the old one but is a additional possibility on top of the old one (which was/is just good enough if the consumer is not interested to generated classes/members/etc...) For the sake of documenting this JIRA issue I post the testcases here :
"""
Foo says hello!
Bar says hello!
Zap says hello!
"""

import Boo.Lang.Compiler

macro helloClasses:
	for typeName in helloClasses.Arguments:
		yield [|
			class $typeName:
				override def ToString() as string:
					return "${$typeName} says hello!"
		|]

helloClasses Foo, Bar, Zap

print Foo()
print Bar()
print Zap()
"""
bonjour
quoi de neuf?
a bientot!
"""

import Boo.Lang.Compiler

macro speak:
	for statement in speak.Block.Statements:
		s = cast(Ast.ExpressionStatement, statement).Expression as Ast.StringLiteralExpression
		if s.Value == "hello":
			yield [| print "bonjour" |]
		if s.Value == "whats up?":
			yield [| print "quoi de neuf?" |]
	yield [| print "a bientot!" |]

speak "french":
	"hello"
	"whats up?"
"""
DO>
<DO
Soviet Russia says hello to EnclosingClass+Foo!
Soviet Russia says hello to EnclosingClass+Bar!
Soviet Russia says hello to EnclosingClass+Zap!
Mission accomplished, nested classes, methods and fields are defeated!
"""

import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast

macro mixed:

	yield cast(Field, [| (_i = 100) as int |])
	#expression used to to disambiguate from BinaryExpression/assignment within block.
	#another possibility: yield CodeBuilder.CreateField("_i", TypeSystemServices.IntType)

	for typeName in mixed.Arguments:
		yield [|
			class $typeName:
				_ec as EnclosingClass

				def constructor(ec as EnclosingClass):
					_ec = ec

				override def ToString() as string:
					_ec._i++
					return "Soviet Russia says hello to ${$typeName}!"
		|]

	yield [|
		def MissionAccomplished():
			if _i == 103: #because must have started at 100 if above cast OK
				print "Mission accomplished, nested classes, methods and fields are defeated!"
	|]


class EnclosingClass:
	def Do():
		print "DO>"
		mixed Foo, Bar, Zap
		print "<DO"


ec = EnclosingClass()
ec.Do()
print EnclosingClass.Foo(ec)
print EnclosingClass.Bar(ec)
print EnclosingClass.Zap(ec)
ec.MissionAccomplished()
Hide
Rodrigo B. de Oliveira added a comment -

AWESOME!

Show
Rodrigo B. de Oliveira added a comment - AWESOME!

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: