  Dynamic languages such as Ruby, Python, and JavaScript have many compelling
benefits, but the lack of static types means subtle errors can remain latent in
code for a long time. While many researchers have developed various systems to
bring some of the benefits of static types to dynamic languages, prior
approaches have trouble dealing with metaprogramming, which generates code as
the program executes. In this paper, we propose Hummingbird, a new system that
uses a novel technique, just-in-time static type checking, to type check Ruby
code even in the presence of metaprogramming. In Hummingbird, method type
signatures are gathered dynamically at run-time, as those methods are created.
When a method is called, Hummingbird statically type checks the method body
against current type signatures. Thus, Hummingbird provides thorough static
checks on a per-method basis, while also allowing arbitrarily complex
metaprogramming. For performance, Hummingbird memoizes the static type checking
pass, invalidating cached checks only if necessary. We formalize Hummingbird
using a core, Ruby-like language and prove it sound. To evaluate Hummingbird,
we applied it to six apps, including three that use Ruby on Rails, a powerful
framework that relies heavily on metaprogramming. We found that all apps
typecheck successfully using Hummingbird, and that Hummingbird's performance
overhead is reasonable. We applied Hummingbird to earlier versions of one Rails
app and found several type errors that had been introduced and then fixed.
Lastly, we demonstrate using Hummingbird in Rails development mode to typecheck
an app as live updates are applied to it.
