Archive for the ‘Open Source Journaling’ Category
Open Source Journaling: Cornerstone February 11, 2009 | 08:48 am

I did another brief update to Cornerstone last night. When parsing floating point numbers, I was doing a parse of an integer, then the dot, then a series of digits, and gluing it all together afterwards. Fred Medlin at the Java Hack Night pointed out that was silly, and I should should parse the value directly as a regex. I went one step further, and jacked the BigDecimal String constructor’s BNF, but encoded as a regex.

So the number parsing now looks like this:

  def float_number : Parser[BigDecimal] = (rawFloat <~ ("F"|"f"))
 
  def integer_number : Parser[BigInteger] = (rawInteger <~ ("Z"|"z"))
 
  def rational_number : Parser[CSRational] = (
    (rawFloat ^^ { new CSRational(_) }) |
    fraction |
    (rawInteger ^^ { new CSRational(_) })
  )
 
  def fraction : Parser[CSRational] = (
    ((rawInteger <~ "/") ~ rawNonzeroNatural) ^^ {
      case x ~ y => new CSRational(x,y)
    }
  )
 
  def rawInteger: Parser[BigInteger] = (
    ((opt("+") ~> """[01-9]+""".r) |
      """[-]?[01-9]+""".r) ^^ { new BigInteger(_) }
  )
 
  def rawNonzeroNatural : Parser[BigInteger] = (
    (opt("+") ~> """[1-9][01-9]*""".r) ^^ { new BigInteger(_) }
  )
 
  def rawFloat : Parser[BigDecimal] = (
    """[-+]?\d*\.\d+([eE][+-]?\d+)?""".r ^^ { new BigDecimal(_) }
  )

As you can see, Cornerstone has only 3 kinds of numbers: integers, floats, and rationals. Rationals are the default, with integers and floats being signaled by suffixes on the numbers (“Z”/”z” and “F”/”f”, respectively). I’m still trying to decide, but I may go with 5 numeric types at the end of the day: long integers (“z”), BigIntegers (“Z”), double-precision floats (“f”), BigDecimals (“F”), and arbitrary-precision rationals (un-suffixed).

Open Source Journaling: Autobase v0.8.1 February 9, 2009 | 12:12 am

Did a bunch of work on Autobase tonight, culminating in a v0.8.1 release.

  • First, I upgraded to Grails 1.1b3. This wasn’t that big a deal, except they moved the staging directory on me, so I had to shift to using stagingDir on the eventWarStart to populate the war. That was on the to-do list for Autobase anyway, so it’s good it got done.
  • I also added a bit of a short-cut for things that have raw bodies (like the “sql” change) — bare string arguments will be set to the “sql” property. This isn’t the best solution for that, but the best solution involves upstream changes in Liquibase — it needs to somehow signal that a body is expected and what property to set with that body. Or (less OO-y), simply a helper object that takes the change and the string and applies it appropriately. This is probably coming in Liquibase 1.10, so the “sql” stopgap is only temporary.
  • I fought again with the whole column/where problem. The methodMissing dispatching was introducing arrays (instead of ArrayLists), missing existing methods, and other weirdness. I punted over to groovy.util.Proxy, but discovered that a proxy of a proxy fails. So I had to leave the dirty hack in place, because I just can’t get the meta-object magic to work.

Open Source Journaling: Cornerstone February 6, 2009 | 12:53 am

I was a bit fried and looking to escape from work, so I played around with Cornerstone a bit tonight. The key focus right now has been the parser of Cornerstone, which is written in Scala.

In Cornerstone, there are what I’m calling the “mirror operators”[1]. Like OCaml, Haskell, and Scala, the user can define operators. In Cornerstone, one of these operators is “[“, or “[” followed by some arbtirary sequence of symbols. So these are potential operators:
[ foo ]
[| foo |]
[|> foo <|]

I was trying to figure out how to get a the parser combinator library to express that “mirrored” concept, and someone pointed me to the (undocumented) into construct: http://paste.pocoo.org/show/102878/. So I went to town on that.

The resulting code looks like this:

  def mirrorCreate(given:CSParser.~[CSExpression,Operator]):Parser[MirrorExpression] = given match {
    case outr ~ Operator(sym) => {
      val mirrored = StringUtils.replaceChars(StringUtils.reverse(sym), """<>{}[]/""", """><}{][/""")
      return (opt(ws) ~> expression <~ opt(ws) <~ (mirrored + "]") ^^ {
        MirrorExpression(Operator("[" + sym), Operator(mirrored + "]"), outr, _)
      })
    }
  }
 
  def mirror_apply : Parser[MirrorExpression] = positioned(
    ((expression ~ (opt(ws) ~> "[" ~> operator)) into mirrorCreate)
  )

I ran into a problem while writing up this code — I needed to import Commons-Lang, but for reasons that still escape me, Scala was freaking out because there was another package that used the word “lang”. So I ended up having to use the (undocumented) _root_ construct:

import _root_.cstone.lang.CSRational
import java.math.BigInteger
import java.math.BigDecimal
import _root_.org.apache.commons.lang._

Thanks to #scala on FreeNode for tipping me off to both these undocumented features.

The only other interesting thing is that I was a bit bummed to discover case statements need explicit match calls on them. In OCaml, I can write something like the following:

let f = function |1 -> ... |2 -> .... |_ ->  ...

But there’s no such beast in Scala. I tried leaving off the given match in the code above, and the compiler bombed out on me. Bad times.

Next up for Cornerstone is implementing operator precedence in the parser. There’s a kinda half-assed implementation of operators which worked for the moment. I really want to wrap a lot of unit tests around the operator precedence stuff, though, because it’s tricky.

[1]Brian actually came up with this idea, which I think is somewhat brilliant.