Sunday, November 29, 2009

Status update

Lots of work done over the thanksgiving weekend. The biggest news is that reflected methods are now callable. This makes it possible to write a very simple unit tests runner,

Here's how the test runner is invoked:

import tart.reflect.Module;
import tart.testing.TestUtils;


@EntryPoint
def main(args:String[]) -> int {
  return TestUtils.runModuleTests(Module.thisModule());
}

'runModuleTests' simply iterates through all of the global methods defined in the module, and calls any that begin with the letters "test". Here's what the function looks like:


import tart.reflect.Module;


namespace TestUtils {


  /** Simple function to run all of the test functions in a module. */
  def runModuleTests(m:Module) -> int {
    try {
      for method in m.methods {
        if method.name.startsWith("test") {
          Debug.write("Running: ", method.name, "...");
          method.call(m);
          Debug.writeLn("DONE");
        }
      }
    } catch t:Throwable {
      Debug.fail("Unexpected exception: ", t.toString());
      return 1;
    }
  
    return 0;
  }
}


Obviously, there's a lot of room for refinement here, but it demonstrates the basic principle.

The other thing I worked on is finishing up union types - and adding support for unconditional dynamic casting. More sample code:

  var x:int or float; // A union type


  // Integer type
  x = 1;


  // isa tests
  Debug.assertTrue(x isa int);
  Debug.assertFalse(x isa float);
  Debug.assertFalse(x isa String);


  // Type casts
  Debug.assertEq(1, typecast[int](x));
  try {
    Debug.assertEq(1.0, typecast[float](x));
    Debug.fail("union member test failed");
  } catch t:TypecastException {}


  // classify
  classify x as xi:int {
    Debug.assertTrue(xi == 1);
  } else {
    Debug.fail("union member test failed");
  }

The difference between 'classify' and 'typecast' is that the latter throws an exception if it fails, while the former transfers control to a different suite.

No comments:

Post a Comment