RSS 2.0

Personal Info:

Joe Send mail to the author(s) leads the architecture of an experimental OS's developer platform, where he is also chief architect of its programming language. His current mission is to enable writing large-scale software that is reliable, secure, and scalable by-construction. Before this, Joe founded the Parallel Extensions to .NET project. He has been granted 19 patents, with 49 pending. When not working, Joe enjoys travelling with his wife, writing books, writing music, studying music theory & mathematics, and doing anything involving food & wine.

My books

My music

Disclaimer:
The content of this site are my own personal opinions and do not represent my employer's view in anyway.

© 2012, Joe Duffy

 
 Friday, December 24, 2004

I can now compile simple Scheme function calls into IL, such as

(+ 5 10)

As well as lambda applications

((lambda (x)
   (* x x))
 9)

((lambda (x y)
   (* x y))
 9 3)

And I was just able to compile (a workable copy!) of the following function call. It was a little tricky because the first lambda deals with higher-order functions... i.e. it takes a function as its first argument:

((lambda (x y)
   (* (x y) y))
 (lambda (x) (* x 2)) 3)

While it may not be immediately obvious, the correct output for this is 18. Indeed, that is what gets printed. :)

Below is the IL that gets generated by my compiler for this last program. Notice the hideous overuse of boxing. This will change. I already have a bunch of so-called “fast” entry points for all of the standard Scheme functions, and I intend to do some trickery with the lambda closure classes. Since Scheme doesn't have static typing, anything I introduce is just an optimization, and will have to rely solely on the use of literals to infer the type. Everything else has to be run-time type checked, which means objects and boxed value types everywhere. I might be able to get a little clever here, but truthfully haven't spent enough time thinking about it.

Lambdas are represented as Closure objects which have corresponding Function delegates. This is how procedure calls to lambdas occur. You might be able to discern from the IL that evaluation of a lambda generates the new class, instantiates it (passing any free variables to its constructor), and leaves a delegate on the stack. This will not be changing... (Unless I find that performance is poor, of course. From some benchmarking, however, it seems that our Whidbey delegate invocation improvements reduce the overhead versus a straight virtually dispatched call to just under 10%.) One optimization I will certainly be making however, is avoiding the creation of a Closure-derived class altogether for simple lambdas without free variables. In this case, it'll just end up as a static method.

Anyhow, here's the code. Sorry I don't have time to go into great detail right now.

.class public auto ansi Program
       extends [mscorlib]System.Object
{
  .method public hidebysig static void  Main(string[] A_0) cil managed
  {
    .entrypoint
    // Code size       59 (0x3b)
    .maxstack  4
    IL_0000:  newobj     instance void __lambda0::.ctor()
    IL_0005:  dup
    IL_0006:  ldvirtftn  instance object __lambda0::Apply2(object,
                                                           object)
    IL_000c:  newobj     instance void class [SenchaRuntimeLibrary]Sencha.Runtime.'Func2`3'<object,object,object>::.ctor(object,
                                                                                                                         native int)
    IL_0011:  newobj     instance void __lambda1::.ctor()
    IL_0016:  dup
    IL_0017:  ldvirtftn  instance object __lambda1::Apply1(object)
    IL_001d:  newobj     instance void class [SenchaRuntimeLibrary]Sencha.Runtime.'Func1`2'<object,object>::.ctor(object,
                                                                                                                  native int)
    IL_0022:  ldc.r8     3.
    IL_002b:  box        [mscorlib]System.Double
    IL_0030:  call       instance !0 class [SenchaRuntimeLibrary]Sencha.Runtime.'Func2`3'<object,object,object>::Invoke(!1,
                                                                                                                        !2)
    IL_0035:  call       void [mscorlib]System.Console::WriteLine(object)
    IL_003a:  ret
  } // end of method Program::Main

  .method public specialname rtspecialname
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  2
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method Program::.ctor

} // end of class Program

.class public auto ansi sealed __lambda0
       extends class [SenchaRuntimeLibrary]Sencha.Runtime.'Closure2`3'<object,object,object>
{
  .method public hidebysig virtual instance object
          Apply2([in] object x,
                 [in] object y) cil managed
  {
    .override  method instance !0 class [SenchaRuntimeLibrary]Sencha.Runtime.'Closure2`3'<object,object,object>::Apply2(!1,
                                                                                                                        !2)
    // Code size       14 (0xe)
    .maxstack  2
    IL_0000:  ldarg.1
    IL_0001:  ldarg.2
    IL_0002:  call       instance !0 class [SenchaRuntimeLibrary]Sencha.Runtime.'Func1`2'<object,object>::Invoke(!1)
    IL_0007:  ldarg.2
    IL_0008:  call       object [SenchaRuntimeLibrary]Sencha.Runtime.StandardSchemeFunctions::Multiply(object,
                                                                                                       object)
    IL_000d:  ret
  } // end of method __lambda0::Apply2

  .method public specialname rtspecialname
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  2
    IL_0000:  ldarg.0
    IL_0001:  call       instance void class [SenchaRuntimeLibrary]Sencha.Runtime.'Closure2`3'<object,object,object>::.ctor()
    IL_0006:  ret
  } // end of method __lambda0::.ctor

} // end of class __lambda0

.class public auto ansi sealed __lambda1
       extends class [SenchaRuntimeLibrary]Sencha.Runtime.'Closure1`2'<object,object>
{
  .method public hidebysig virtual instance object
          Apply1([in] object x) cil managed
  {
    .override  method instance !0 class [SenchaRuntimeLibrary]Sencha.Runtime.'Closure1`2'<object,object>::Apply1(!1)
    // Code size       21 (0x15)
    .maxstack  2
    IL_0000:  ldarg.1
    IL_0001:  ldc.r8     2.
    IL_000a:  box        [mscorlib]System.Double
    IL_000f:  call       object [SenchaRuntimeLibrary]Sencha.Runtime.StandardSchemeFunctions::Multiply(object,
                                                                                                       object)
    IL_0014:  ret
  } // end of method __lambda1::Apply1

  .method public specialname rtspecialname
          instance void  .ctor() cil managed
  {
    // Code size       7 (0x7)
    .maxstack  2
    IL_0000:  ldarg.0
    IL_0001:  call       instance void class [SenchaRuntimeLibrary]Sencha.Runtime.'Closure1`2'<object,object>::.ctor()
    IL_0006:  ret
  } // end of method __lambda1::.ctor

} // end of class __lambda1

12/24/2004 3:17:01 AM (Pacific Standard Time, UTC-08:00)  #   
Tracked by:
http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=e748f403-94cc-48e4-8e29... [Pingback]

 

Recent Entries:

Search:

Browse by Date:
<February 2012>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

Browse by Category:

Notables: