Skip to content

Instantly share code, notes, and snippets.

@clhodapp
Created April 6, 2012 09:10
Show Gist options
  • Save clhodapp/2318356 to your computer and use it in GitHub Desktop.
Save clhodapp/2318356 to your computer and use it in GitHub Desktop.
SOC 2012 Proposal
Name: Christopher Hodapp
Institution: The University of Alabama
Program: Computer Science
Graduation: May 2012
Proposal Title: Dynamic Scala
Email: [email protected]
Phone: +19372199307
About me: I am a 4th (final) year undergraduate Computer Science
student at the University of Alabama. I plan to resume my studies at
the same university next fall with the goal of eventually getting a
Master's degree in Computer Science. I have had courses in
Programming Languages, Data Structures, and Algorithms. While I was
taking Programming Languages, I created an interpreter for a simple
dynamic language of my own design (http://bit.ly/IaBRuR). It's been a
very long time since I've done anything with it. I am currently in a
Formal Languages Course (Pushdown Automata, Turing Machines, etc.).
I'm currently doing independent study work for two professors. In the
first independent study work with two professors. First, I'm working
with another student to port a source code feature extraction program
that is currently written in Python to Java. The code for that project
will be put online when it's done, but it's not available now. Second,
I'm finishing an automated (Android) App Inventor to Java
(libsimpleandroidruntime) porting tool. The project was started by
another student, but he left in a very rough (nonfunctional) state.
That project is not fully working yet, but you can see its current
state at http://bit.ly/I0UMtg. I am also paid to develop Android apps
to collect laboratory by another professor.
I learned Scala from "Programming In Scala" last year and I thoroughly
enjoy the language.
I am also familiar with the following langauges: Java, C, C++, Scheme,
Python
I've done a tiny bit of Ruby and I'm working through Learn You A
Haskell.
======================================================================
Scala is a language grounded in principles of pragmatism. It allows
the developer to write code in many styles and paradigms. It also
allows code written in different paradigms to seamlessly interact. The
classic example of this is the way that Scala allows the developer to
use a blend of functional and object-oriented programming techniques.
I propose that I spend this summer working to allow Scala to support a
new paradigm: Dynamic typing.
The way I envision it, dynamically typed code would look like this:
"""
import language.Dynamic
class Foo {
def double(x) = x * 2
}
object Main extends App {
val a = 3
val b = "abc"
val f = new foo
println(f.double(a))
println(f.double(b))
}
"""
This code would print 6 and "abcabc" on lines.
As with the example functional/Object Oriented case given earlier,
static and dynamic code would need to be able to interact seamlessly.
I do have a partial strategy for making this happen. The first phase
of my implementation idea builds on top of the Dynamic marker trait
described in SIP 17. I want to create a type hierarchy rooted on this
trait and prototyped below:
"""
trait DynamicRef {
val referenced: Any = this
private[this] val rt = mirror.typeOfInstance(referenced)
import DynamicBox._
private[this] def convertVal(sym: mirror.Symbol) = {
sym match {
case s if s == mirror.classToSymbol(classOf[Int]) =>
mirror.classToSymbol(classOf[java.lang.Integer])
case s if s == mirror.classToSymbol(classOf[Long]) =>
mirror.classToSymbol(classOf[java.lang.Long])
case s if s == mirror.classToSymbol(classOf[Byte]) =>
mirror.classToSymbol(classOf[java.lang.Byte])
case s if s == mirror.classToSymbol(classOf[Char]) =>
mirror.classToSymbol(classOf[java.lang.Character])
case s if s == mirror.classToSymbol(classOf[Boolean]) =>
mirror.classToSymbol(classOf[java.lang.Boolean])
case s if s == mirror.classToSymbol(classOf[Short]) =>
mirror.classToSymbol(classOf[java.lang.Short])
case s if s == mirror.classToSymbol(classOf[Float]) =>
mirror.classToSymbol(classOf[java.lang.Float])
case s if s == mirror.classToSymbol(classOf[Double]) =>
mirror.classToSymbol(classOf[java.lang.Double])
case _ =>
sym
}
}
def applyDynamic(name: String)(args: Any*): DynamicRef = {
val argSymbols = args.map(arg => mirror.symbolOfInstance(arg))
val namesMatch = rt.members.filter(_.name == mirror.newTermName(name))
val exactMatch = namesMatch.filter( method =>
method.typeSignature match {
case mirror.MethodType(params, _) =>
params.map(p => convertVal(p.asType.typeSymbol)).toList == argSymbols.toList
case _ =>
false
}
)
if (exactMatch.size == 1)
mirror.invoke(referenced.asInstanceOf[AnyRef], exactMatch.head)(args: _*).toDynamic
else
// try upcasting arguments
// else
sys.error("not found")
}
def is[T](implicit t: ClassManifest[T]) = rt.baseClasses.contains(t.symbol)
def as[T] = referenced.asInstanceOf[T]
override def toString = referenced.toString
}
class DynamicBox private(underlying: Any) extends DynamicRef {
override val referenced = underlying
}
object DynamicBox {
def apply(underlying: Any) =
if (underlying.isInstanceOf[DynamicRef] underlying
else new DynamicBox(underlying)
implicit def anyRef2boxWithMethod(underlying: AnyRef) = new BoxWithMethod(underlying)
}
class BoxWithMethod(underlying: AnyRef) {
def toDynamic = DynamicBox(underlying)
}
"""
The idea is to have a dynamic reference type with generic
implementations of the applyDynamic, applyNamedDynamic, updateDynamic,
and selectDynamic (henceforth this list will be called "*Dynamic")
methods that use reflection to call through to the
properly-named/properly-parametered methods. This allows you to call
method on an object of this type even if you only have a reference of
type DynamicRef. Alternately, you could say that method binding for
references of type DynamicRef is delayed until runtime. There must
also be a dynamic box class which can wrap a non-dynamic object and
make it dynamic in order to serve as the return type of the *Dynamic
methods. Note that the type of a DynamicRef can be checked against a
specified static type with the is method and the referenced object can
be retrieved as a specified static type with the as method.
This prototype actually works for simple cases, but it has some
issues: It will not upcast in order to make a call work. It does not
support type parameters or multiple parameter lists. Also, it does not
support implicits (it should check for implicits defined at the call
site and at the definition site of both argument and parameter types).
Christopher Vogt, an engineer at EPFL, has create an implementation of
DynamicRef at http://bit.ly/HiR1mn that uses the Toolbox reflective
compiler and works with implicits in some circumstances (we haven't
figured out exactly what rules govern when it does and doesn't work
yet). Christopher and I have also discussed DynamicRef Skype. That
discussion actually forms the basis of this proposal. At the end of
our discussion, we could not figure out how to write *Dynamic methods
that accept an unbounded number of type parameters and curried
parameter lists. I still have not been able to figure out a way to do
this. It is likely that new language features would be necessary if
this functionality is deemed necessary.
The second part of my implementation plan requires modifications to
the compiler and the Scala language specification. The actual features
are simple: when the feature flag language.Dynamic is in scope, the
compiler silently behaves as if all declared classes mix in and all
traits extend the DynamicRef trait. It also behaves as if all vals,
var, and method parameters without a programmer-specified type are of
type DynamicRef and as if all methods without a programmer-specified
return type return DynmaicRef. That is to say, it behaves as if
"""
class Foo {
def double(x) = x * 2
}
"""
were
"""
class Foo extends DynamicRef {
def double(x: DynamicRef): DynamicRef = x * 2
}
"""
That's it. Implementing this type hierarchy and these compiler
features should be all that is necessary to get to the point where
Scala is not just functional and object oriented, it's also static and
dynamic.
Here is the timeline that I envision for this project:
Now - 21 May : Get more familiar with the Scala codebase
: Read/post to mailing lists a lot
: Figure how to add compiler/lang features I will need
21 MAY - 4 JUL : Implement the 1st part of proposal (DynamicRef)
4 JUL - 9 JUL : Review methods / find bugs / buffer
9 JUL - 11 JUL : Midterm Evaluation
11 JUL - 13 AUG : Implement 2nd part of proposal (compiler features)
13 Aug - 20 AUG : Buffer / Documentation
20 AUG - 24 AUG : Final Evaluation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment