Saturday, November 24, 2007

PowerShell DSLs: Using hashtables and scriptblocks together

Previously I presented the use of hashtables and scriptblocks as DSL input formats. You can also convert between them, with processing in between. I tried that out, and I think the result is interesting enough to post. Again, here is the input:

class MyClass {

    field ([string]) S

}

The previous code would use the 'field' function to manipulate the class object as appropriate:

    function field

    {

        param (

            [Type] $type,

            [String] $name

        )

        

        # add the field declaration

        $field = New-Object System.CodeDom.CodeMemberField($type, $name)

        $field.Attributes = [System.CodeDom.MemberAttributes]::Public

        $class.Members.Add( $field )

        

        # add the ctor parameter

        $ctorParameter = New-Object System.CodeDom.CodeParameterDeclarationExpression($type, $name)

        $constructor.Parameters.Add($ctorParameter)


 

        # add the ctor initializer

        $fieldReference = New-Object System.CodeDom.CodeFieldReferenceExpression(

            (New-Object System.CodeDom.CodeThisReferenceExpression),

            $name

        )

        

        $ctorInitializer = New-Object System.CodeDom.CodeAssignStatement(

            $fieldReference,

            (New-Object System.CodeDom.CodeVariableReferenceExpression $name)

        )

        

        $constructor.Statements.Add( $ctorInitializer )

    }

    

    & $memberScriptBlock | Out-Null


 

But another idea is to have the 'field' function produce a collection of CodeDom objects that can be assembled later.

    # return a hash of the CodeDom objects related to

    # this field

    function field

    {

        param (

            [Type] $type,

            [String] $name

        )

        

        @{

            fieldDeclaration = $(

                $field = New-Object System.CodeDom.CodeMemberField($type, $name)

                $field.Attributes = [System.CodeDom.MemberAttributes]::Public

                $field

                )

            parameter = New-Object System.CodeDom.CodeParameterDeclarationExpression($type, $name)

            fieldReference = New-Object System.CodeDom.CodeFieldReferenceExpression(

                (New-Object System.CodeDom.CodeThisReferenceExpression),

                $name

            )

            parameterReference = New-Object System.CodeDom.CodeVariableReferenceExpression $name

        }                

    }

    

    & $memberScriptBlock | foreach {

        $class.Members.Add( $_.fieldDeclaration )

        

        $constructor.Parameters.Add( $_.parameter )


 

        $constructor.Statements.Add(

            $(New-Object System.CodeDom.CodeAssignStatement( $_.fieldReference, $_.parameterReference ))

        )

    } | Out-Null

I suspect that the latter model is a little better because it separates concerns. Consider if I were to add other statements to my language, such as 'property'. The 'foreach' at the end could probably be written in a way that works for both fields and properties. However, the hashtable is slightly concerning, because it's not typed – if I get the key names wrong somewhere, I'm screwed.

I find that I'm spending quite a lot of time on this, but it's important that I find a way to create DSLs quickly. I figured that right now I'm just learning the techniques, and then if I master them, then I can do it more quickly when the time comes.

Friday, November 23, 2007

Immutable data class generator: Skeleton implementation

I've made a little progress on my PowerShell DSL for data classes, and figured it's a good time to show it off.

Here's the input format at this point:

class MyClass {

field ([string]) S

}

(I'm using the ScriptBlock approach.) I generally like the syntax, except for the need to add parentheses around the type. The alternative is to use a fully-qualified string:

class MyClass {

field System.String S

}

I'm not sure which is better, but I'm going with the first one for now, because it allows a more specific type than string.

The basis of the implementation is to write methods named 'class' and 'field'. 'class' is simple; here's an excerpt of the important bits:

$class = New-Object System.CodeDom.CodeTypeDeclaration $name

$class.TypeAttributes = [System.Reflection.TypeAttributes]::NotPublic

$class.IsPartial = $true

$constructor = New-Object System.CodeDom.CodeConstructor

$class.Members.Add( $constructor ) Out-Null

$class

The implementation of 'field' could go in several different ways. For now, I've written it to manipulate the class as appropriate, e.g.:

$field = New-Object System.CodeDom.CodeMemberField($type, $name)

$class.Members.Add( $field )


$ctorParameter = New-Object System.CodeDom.CodeParameterDeclarationExpression($type, $name)

$constructor.Parameters.Add($ctorParameter)


$fieldReference = New-Object System.CodeDom.CodeFieldReferenceExpression(

(New-Object System.CodeDom.CodeThisReferenceExpression),

$name

)


$ctorInitializer = New-Object System.CodeDom.CodeAssignStatement(

$fieldReference,

(New-Object System.CodeDom.CodeVariableReferenceExpression $name)

)


$constructor.Statements.Add( $ctorInitializer )


(I'd like to attach the full script, but I don't see a way to do that in blogspot). It generates this output:

internal partial class MyClass

{

public string S;

private MyClass(string S)

{

this.S = S;

}

}



EDIT: See PowerShell DSLs: Using hashtables and scriptblocks together for a different view of this code.

Immutable data class generator

I'm working on a DSL implementation for defining "data classes" with certain properties in C# (see http://blogs.gotdotnet.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx for an example of the output).

Table of Contents

  1. Goals
  2. Skeleton implementation
  3. ???

PowerShell DSLs: Script block input

As an alternative to using a hashtable for input, you can use a script block. Here's a script-block-way of doing the same thing as before:

class MyClass -accessibilty:public {

member string S

}


and here's one of many ways of handling it

function class {

param (

[String] $name = $( throw
"name is required" ),

[String] $accessibilty,

[ScriptBlock] $memberScriptBlock = $( throw
"member script block is require" )

)


" $accessibilty class $name {"


& $memberScriptBlock % { " public $($_.declaration)" }


" }"

}


function member {

param (

[String] $type = $( throw
"type is required" ),

[String] $name = $( throw
"name is required" )

)


@{

declaration = "$type $name;"


}

}


What's happening here is that the first word on any line becomes a function, and the remaining words are parameters to that function. So, you're now creating an "internal DSL" in PowerShell. This lets you work in a more idoimatic PowerShell manner.


PowerShell DSLs: Hash table input

lassOne way to take PowerShell DSL input is in the form of a hash table. Taking from the Data Type with Builder example, you could write input as:

@{
kind = 'class'
name = 'MyClass'
accessibilty = 'public'
members = @{
type = 'string'
name = 'S'
}
}


How do you consume this input? Here's an example. (Note that the code generation side is not the focal point here -- the way that we interpet the input is what matters.)


if ($input.kind = 'class') {
" $($input.accessibilty) class $($input.name) {"

$input.members | foreach {
" public $($_.type) $($_.name);"
}

" }"

}


Which generates this output:


public class MyClass {
public System.String S;
}


This approach seems most effective when you need to express a lot of attributes on a single element. The downside is that the input seems a bit verbose and unnatural in some cases.

PowerShell DSLs

I've written before about my attraction to Domain-Specific Languages and my curiosity about using PowerShell to handle them, but I only recently got any time to think about it more. I'm working on a DSL implementation for defining "data classes" with certain properties in C# (see http://blogs.gotdotnet.com/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx#comments for an example).

I have only 3 examples of PowerShell DSLs to work from, and I don't see any guidance in this area, so I figured I'd write about what I find.

Table of Contents

  1. Prior art
  2. Why PowerShell?
  3. Custom invocation w/ a library
  4. DSL tool invocation
  5. Hash table input
  6. Script block input
  7. Using hashtables and scriptblocks together

Warning: technical content ahead

While working at Microsoft, I had a blog for work-related issues at blogs.msdn.com. Now I need a new place to write these things, so this blog will now include technical content, along with the food, politics, family, etc. that have come before.

Friday, November 09, 2007

Reid's Journal Entry: Making Apple Crisp

Today Reid made apple crisp. I wanted to know more about it, so I asked him some questions.

J: How many oranges did you use?
R: Zero oranges. It only takes apples and a few other ingredients, which are kind of like spices. Butter,

J: Oranges?
R: No... I mean, yes

J: What else?
R: Weeds. Then we milk and cereal. This is going to be so funny! Don't write that.

J: After you mixed it up, what did you do?
R: I baked it for 2000 hours. What zee doh.

J: How did it taste?
R: It's not ready for that part yet. We added 2000 drops of stevia in. Time for what it tasted like. It tasted like... stevia. Of course it would.

Friday, October 19, 2007

A new adventure

Today I announced broadly that I'm leaving Microsoft.

I sent 3 emails. Two went to the discussion groups of tools that I own, to announce the change of ownership of these tools. Strictly for business reasons, but then the news started flowing, and I was starting to get questions. So I sent out the third - to basically every person I've worked with in the last 11 years.

What's next?

I'm going to be a stay-at-home dad. The twins are 20 months old. Reid is 6. We want to homeschool Reid, and eventually the twins.

Living off savings will require that we spend a lot less. We currently live 1.9 miles from Microsoft campus, which is a damn expensive place to be. With me not working there, it doesn't make sense to live here, so we're moving away.

We've picked Port Townsend as our new home. It's such a cool city. 8000 people. 25mph speed limits. Hopefully we can bike & walk just about everywhere.

It's also a good choice because I love old, wooden boats, and PT has plenty of them. But that's for the future - right now, our attention will be on the family. Catching up on rest, taking good care of ourselves, being together.

I'm trying to leave Microsoft on good terms, and that includes trying to wrap things up on my current project so that it will succeed when I'm gone.

There's also a lot of work to do to get the house ready, purge our stuff some more, find a new home, pack, and move. Whew!

Thursday, September 06, 2007

Great music you haven't heard before: Mindless Self Induglence

Electronic punk. Real punk - they actually step outside of what's acceptable. Good for them.

They're starting to get known, it seems. I wonder how that will change them?

The track that got me was Panty Shot. Somehow this live verson is so much better than the studio recording.

Great music you haven't heard before: Emergency Broadcast Network

Here are some bits of music that I think are really great, but that aren't widely known. Maybe I'll do a few posts.

Emergency Broadcast Network

Industrial + electronica + video. I found these by accident. I was in the record shop, flipping through the industrial section, and picked out Telecommunication Breakdown because it had an interesting cover.

3:7:8 is particularly catchy.


Sunday, July 01, 2007

Tuesday, May 29, 2007

The difficulty of purging toys

My friend over at Confessions of a Hoarder talks about her difficulty decluttering kids' toys.

I have a hard, hard time dealing with toys, too.

I have been able to purge just about every group of things I call "mine": my hair, my computers, my motorcycles, my tools, my clothes, my books.

Once my wife got the bug, she started purging her stuff, too. That has been going well, and we work on it together.

One of the reasons I find toys difficult is that I'm making the decision for someone else. I know that, by getting rid of 1/2 of my books, I lose something (the opportunity to read that book at a moment's notice, the status symbol of books that define "me" to visitors) and gain something in return (space on the shelf, ease of managing my stuff, order in my home, money that I don't have to spend on more storage). I can decide if that trade-off is the right choice for me.

However, with the kids toys, I know that most of the gain is the parents' (for it is our feet that hurt when we step on a marble; we are the ones that separate the blocks, trains, wedgits, and legos) and most of the loss is kids' (they don't have access to a toy that they might enjoy).

What I remind myself of is how much the kids gain, too:

- Their parents are slightly less cranky.

- Their parents have more free time to spend with the kids, to cook nutritious meals, to take care of themselves so they can take care of the kids.

- Kids, too, like a clear, open space to engage in play.

- Clear, open spaces are particularly good for wrestling with Dad.

- Being able to clearly see a small number of toys works better than being surrounded by a plethora. It gives kids a chance to really focus their play in one area, and to not be overwhelmed when considering what play to do next.

- Kids play with non-toy things as often as toy things. Wooden spoons and sofa cushions are current favorites. Those items serve double-duty (yes, you can stir with a wooden spoon), thereby increasing their "density" in the home.

I've noticed recently that even the babies (16 months on Saturday) will often not think of playing with something until someone points it out to them. So, providing them with bucket upon bucket of toys won't really help them find fun. Having just 1 toy can meet their needs, if there's someone to help them get engaged.

In January I put a bunch of kids' toys in storage. It was a really good choice -- the kids haven't missed the toys, and life has been a bit easier since.

Saturday, May 26, 2007

Date Night



As parents of 3 small children, it's rare that Julie & I get to spend time together, just the two of us. Luckily for us, we found someone who was willing to babysit all 3, and we went out on a date.



We went for sushi.

As you can see, this is a happy thing.

Tuesday, May 15, 2007

How little do we really need?

Reading http://confessionsofahoarder.blogspot.com/2007/04/off-topic-guest-post-over-at-happy-jet.html got me thinking.

Every Thanksgiving my extended family rents a large house at the beach. There are usually about 16 people there, of which I contribute 5. For those 5, we only bring 2 suitcases, 2 backpacks, and carseats. There are only a few toys, unlike the hundreds of overflowing toys at home.

There are clearly some things missing, like clothes for the other weather, but still, we do very well with very little.

One important factor is the help we get. For example, with other adults around, we have time to keep up on laundry, washing every day, so we only need 3 days worth of clothes.

It's something we think about often when working on decluttering and pondering how much we really need for our happiness.

-Jay on a Pocket PC phone

Saturday, May 12, 2007

This just seen

It fills my heart with corporate pride.

-Jay on a Pocket PC phone

Board games on the computer

It's nice to sit down at a table to play a board game. You get some real human interaction that is missing from, say, television. But when it's time for dinner, you have to end the game. Or the peices get distributed -- under the sofa, behind the dresser, into a baby's digestive tract.

These problems go away when you play on a PC. No losing virtual chess peices. Go works well on the computer, too. Dominoes doesn't as well, since you can't hide your peices from your opponent, but having two PCs can do the trick.

But I'm still trying to figure how to get an online version of Twister.

Tuesday, May 01, 2007

How dumb do phishers think I am?

I just got a mail with this contents:

Dear Customer, jbasuki.

You are receiving this message, due to you protection, Our Online Technical Security Service Foreign IP Spy recently detected that your online account was recently logged on from am 88.30.167.175 without am International Access Code (I.A.C) and from an unregistered computer, which was not verified by the Our Online Service Department.

If you last logged in you online account on Thursday April 5th 2007, by the time 6:45 pm from an Foreign Ip their is no need for you to panic, but if you did log in your account on the above Date and Time, kindly take 2-3 minute of your online
banking experince to verify and register your computer now to avoid identity
theft, your protection is our future medal.


Verification Link
(removed)

Notice: You can acess your account from a foreign IP or
country by getting am (I.A.C) International Access Code, by contacting our local
brances close to you.

Do people really fall for such badd speling and gramer?

Thursday, April 26, 2007

Twins spin me around

My first youtube upload. The camera was upside-down, and I don't know how to flip the video. *sigh*.

Monday, April 16, 2007

Plant walk

On Sunday Reid & I went on a plant walk in Discovery Park. It turned out we were the only people who showed (besides the leader).


I met a lot of plants that I hope to meet again, including Stinging nettle, Plantain, and Horsetail. I'm pretty sure I've seen plantain around my neighboorhood; I am looking forward to finding it & adding it to my local snacking menu, which currently includes chickweed, dandelion, and blackberries.


I'd like to find something close to home that will make a tasty tea.

At the right is a snap of horsetail that I took.
 
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.