TL10
 Jim Hugunin
Partner Architect
Microsoft Corporation
By: public.resource.org
http://flickr.com/photos/publicresourceorg/493955228/
Dynamic
Languages
Static
Languages
Simple and succinct
Robust
Implicitly typed
Performant
Meta-programming
Intelligent tools
No compilation
Better scaling
IronPython
IronRuby
C#
VB.NET
Others…
Dynamic Language Runtime
Expression Trees
Object
Binder
JavaScript
Binder
Dynamic Dispatch
Python
Binder
Call Site Caching
Ruby
Binder
COM
Binder













Higher numbers are better
100K
80K
60K
80K
40K
20K
0K
46K
50K
Python
2.3
Python
2.5
90K
36K
Python
2.1
IronPython IronPython
0.1
1.0
static void
Noddy_dealloc(Noddy* self)
{
Py_XDECREF(self->first);
Py_XDECREF(self->last);
self->ob_type->tp_free((PyObject*)self);
}
static int Noddy_init(Noddy *self, PyObject
*args, PyObject *kwds)
static PyObject *
Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
{
#include <Python.h>
Noddy *self;
PyObject *first=NULL, *last=NULL, *tmp;
typedef struct {
self = (Noddy *)type->tp_alloc(type, 0);
PyObject_HEAD
PyObject *first; /* first name */
PyObject *last; /* last name */
int number;
} Noddy;
if (self != NULL) {
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
static char *kwlist[] = {"first", "last", NULL};
static PyTypeObject noddy_NoddyType = {
PyObject_HEAD_INIT(NULL)
0,
/*ob_size*/
"noddy.Noddy",
/*tp_name*/
sizeof(noddy_NoddyObject), /*tp_basicsize*/
0,
/*tp_itemsize*/
0,
/*tp_dealloc*/
0,
/*tp_print*/
0,
/*tp_getattr*/
0,
/*tp_setattr*/
0,
/*tp_compare*/
0,
/*tp_repr*/
0,
/*tp_as_number*/
0,
/*tp_as_sequence*/
0,
/*tp_as_mapping*/
0,
/*tp_hash */
0,
/*tp_call*/
0,
/*tp_str*/
0,
/*tp_getattro*/
0,
/*tp_setattro*/
0,
/*tp_as_buffer*/
Py_TPFLAGS_DEFAULT,
/*tp_flags*/
"Noddy objects",
/* tp_doc */
};
static PyMethodDef noddy_methods[] = {
{NULL} /* Sentinel */
};
if (! PyArg_ParseTupleAndKeywords(args,
kwds, "|OO", kwlist,
self->last = PyString_FromString("");
if (self->last == NULL)
&first,
&last))
{
Py_DECREF(self);
return NULL;
return -1;
}
if (first) {
tmp = self->first;
Py_INCREF(first);
self->first = first;
Py_XDECREF(tmp);
}
if (last) {
tmp = self->last;
Py_INCREF(last);
self->last = last;
noddy_NoddyType.tp_new = PyType_GenericNew;
Py_XDECREF(tmp);
if (PyType_Ready(&noddy_NoddyType)
< 0)
return;
}
m = Py_InitModule3("noddy", noddy_methods,
self->number = 0;
}
return (PyObject *)self;
}
static int
Noddy_init(Noddy *self, PyObject *args, PyObject *kwds)
{
PyObject *first=NULL, *last=NULL, *tmp;
static char *kwlist[] = {"first", "last", NULL};
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
&first, &last))
return -1;
if (first) {
tmp = self->first;
Py_INCREF(first);
self->first = first;
Py_XDECREF(tmp);
}
#ifndef PyMODINIT_FUNC/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
initnoddy(void)
{
PyObject* m;
"Example module that creates an extension type.");
Py_INCREF(&noddy_NoddyType);
PyModule_AddObject(m, "Noddy", (PyObject *)&noddy_NoddyType);
}
return 0;
}
if (last) {
tmp = self->last;
Py_INCREF(last);
self->last = last;
Py_XDECREF(tmp);
}
return 0;
}
static PyMemberDef Noddy_members[] = {
{"first", T_OBJECT_EX, offsetof(Noddy, first), 0,
"first name"},
{"last", T_OBJECT_EX, offsetof(Noddy, last), 0,
"last name"},
{NULL} /* Sentinel */
};
namespace noddy {
public class Noddy {
public string first, last;
public Noddy(string first, string last) {
this.first = first;
this.last = last;
}
}
}
py1
c2
Python
Objects
C-Based
Objects
py1
c2
.NET Objects











My Own Story











TL44: IronRuby: The Right Language for the Right Job
John Lam in Room 515B
Today at 5:15PM – Just after this talk!
DLR2
Script
Hosting
Compiler as
a Service
???
.NET ?.?
DLR
Dynamic
Dispatch
Expression
Trees v2
Call Site
Caching
.NET 4.0
Expression
Trees
Extension
Methods
Silverlight
.NET 3.5
Fast
Delegates
Generics
In Runtime
Dynamic
Methods
.NET 2.0
JIT
GC
Reflection
BCL
Verifier
Sandbox
Dynamic
Codegen
LINQ
.NET 1.0
Calculator calc = GetCalculator();
int sum = calc.Add(10, 20);
object calc = GetCalculator();
Type calcType = calc.GetType();
object res = calcType.InvokeMember("Add",
BindingFlags.InvokeMethod, null,
new object[] { 10, 20 });
ScriptObject calc = GetCalculator();
int sum = Convert.ToInt32(res);
object res = calc.Invoke("Add", 10, 20);
int sum = Convert.ToInt32(res);
Statically typed to
be dynamic
dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);
Dynamic
conversion
Dynamic method
invocation
IronPython
x.Foo
IronRuby
x.Foo
C#
x.Foo
VB.NET
x.Foo
Others…
$x{Foo}, …
Dynamic Language Runtime
GetMember
Name=“Foo”, IgnoreCase=false
Object
Binder
COM
Binder
Python
Binder
Ruby
Binder
Your
Binder
?
Action
Python
Ruby
C#
VB.NET
GetMember
x.Foo
x.Foo
x.Foo
x.Foo
SetMember
x.Foo = y
x.Foo = y
x.Foo = y
x.Foo = y
DeleteMember
del d.Foo
x.send
:remove_instance_variable
:@foo
No syntax
No syntax
UnaryOperation -x
-x
-x
-x
BinaryOperation x + y
x + y
x + y
x + y
Convert
No syntax
No syntax
(Foo)x
CType(x,Foo)
InvokeMember
x.Foo(a,b)2
x.Foo(a,b)
x.Foo(a,b)
x.Foo(a,b)
Invoke
x(a,b)
x.call(a,b)1
x(a,b)
x(a,b)
CreateInstance
X(a,b)
X.new(a,b)
new X(a,b)
Not dynamic
New X(a,b)
Not dynamic
GetIndex
x[a,b]
x[a,b]
x[a,b]
x(a,b)
SetIndex
x[a,b] = y
x[a,b] = y
x[a,b] = y
X(a,b) = y
DeleteIndex
del x[a,b]
No syntax
No syntax
No syntax
1: Calling a proc rather than a method;
2: this is always a GetMember followed by a Invoke
public abstract class DynamicObject : IDynamicObject {
public virtual object GetMember(GetMemberBinder info){…}
public virtual void SetMember(SetMemberBinder info, object value){…}
public virtual void DeleteMember(DeleteMemberBinder info){…}
public virtual object UnaryOperation(UnaryOperationBinder info){…}
public virtual object BinaryOperation(BinaryOperationBinder info, object arg){…}
public virtual object Convert(ConvertBinder info){…}
public virtual object Invoke(InvokeBinder info, object[] args){…}
public virtual object InvokeMember(InvokeMemberBinder info, object[] args){…}
public virtual object CreateInstance(CreateInstanceBinder info, object[] args){…}
public virtual object GetIndex(GetIndexBinder info, object[] indices){…}
public virtual void SetIndex(SetIndexBinder, object[] indices, object value){…}
public virtual void DeleteIndex(DeleteIndexBinder info, object[] indices){…}
public MetaObject IDynamicObject.GetMetaObject() { … }
}





BinaryOp
==
If
Return
Return
static int fact(int n) {
if (n == 0) {
return 1;
} else {
return n * fact(n - 1);
}
}
Parameter
n
Constant
0
Constant
1
BinaryOp
*
Parameter
n
MethodCall
Program.fact
BinaryOp
-
Parameter
n
Constant
1
Dynamic
CSharpOp[==]
If
Return
Return
static dynamic fact(dynamic n) {
if (n == 0) {
return 1;
} else {
return n * fact(n - 1);
}
}
Parameter
n
Constant
0
Constant
1
Dynamic
CSharpOp[*]
Parameter
n
MethodCall
Program.fact
Dynamic
CSharpOp[-]
Parameter
n
Constant
1
Dynamic
PythonOp[==]
If
Return
Return
def fact(n):
if n == 0:
return 1
else:
return n * fact(n - 1)
Parameter
n
Constant
0
Constant
1
Dynamic
PythonOp[*]
Parameter
n
Property
Value
Dynamic
PythonInvoke
Dynamic
PythonOp[-]
Field
$global.fact
Parameter
n
Constant
1
MethodCall
Ruby.IsTrue
If
Dynamic
RubyOp[==]
Parameter
n
Constant
0
Constant
1
Dynamic
RubyOp[*]
Parameter
n
def fact(n)
if n == 0
1
else
n * fact(n - 1)
end
end
Parameter
self
Dynamic
RubyCall[fact]
Dynamic
RubyOp[-]
Parameter
n
Constant
1
x * 2
Assume x = 2,000,000,000
In Python
x * 2 = 4,000,000,000
My 7 year old daughter
x * 2 = 4,000,000,000
In Ruby
x * 2 = 4,000,000,000
In C#
x * 2 = -294,967,296 //typed as int
Or OverflowException //checked
Or 4,000,000,000
//typed as long













if (x == 0) { … }
static CallSite<Func<CallSite, object, int, bool>> _site = …;
if (_site.Target(_site, x, 0)) { … }
static bool _0(Site site, object x, int y) {
return site.Update(site, x, y); //tailcall
}
if (x == 0) { … }
static CallSite<Func<CallSite, object, int, bool>> _site = …;
if (_site.Target(_site, x, 0)) { … }
static bool _1(Site site, object x, int y) {
if (x is int) {
return (int)x == y;
} else {
return site.Update(site, x, y); //tailcall
}
}
if (x == 0) { … }
static CallSite<Func<CallSite, object, int, bool>> _site = …;
if (_site.Target(_site, x, 0)) { … }
static bool _2(Site site, object x, int y) {
if (x is int) {
return (int)x == y;
} else if (x is BigInteger) {
return BigInteger.op_Equality((BigInteger)x, y);
} else {
return site.Update(site, x, y); //tailcall
}
}
TypeIs
int
If
BinaryOp
==
MethodCall
Invoke
Parameter
x
Cast
int
Test
Parameter
x
Parameter
y
Field
Update
Parameter
x
Parameter
site
Parameter
y
Target
Generic
Update
TypeIs
int
BinaryOp
==
If
Parameter
x
Cast
int
Parameter
x
Parameter
y
TypeIs
Parameter
BigInteger
x
If
MethodCall
Op_Equality
MethodCall
Invoke
Cast
BigInteger
Parameter
y
Field
Update
Parameter
x
Parameter
x
Parameter
site
Parameter
y
MetaObject
TypeIs
int
BinaryOp
==
Parameter
x
Cast
int
Parameter
y
Test
Parameter
x
Target
TypeIs
List
Property
Count
Parameter
x
Cast
List
TypeIs
DynamicObject
MethodCall
GetMember
Test
Parameter
x
Parameter
x
Cast
DynamicObject
Target
Test
Parameter
x
Constant
GetMemberBinder(“Count”)
Target
TypeIs
FastBag
Property
Slot0
Parameter
x
Cast
FastBag
Parameter
x
Test
Target
public abstract class MetaObject {
public Restrictions Restrictions { get; }
public Expression Expression { get; }
public virtual MetaObject BindGetMember(GetMemberBinder info){…}
public virtual MetaObject BindSetMember(SetMemberBinder info, MetaObject value){…}
public virtual MetaObject BindDeleteMember(DeleteMemberBinder info){…}
public virtual MetaObject BindUnaryOperation(UnaryOperationBinder info){…}
public virtual MetaObject BindBinaryOperation(BinaryOperationBinder info, MetaObject arg){…}
public virtual MetaObject BindConvert(ConvertBinder info){…}
public virtual MetaObject BindInvoke(InvokeBinder info, MetaObject[] args){…}
public virtual MetaObject BindInvokeMember(InvokeMemberBinder info, MetaObject[] args){…}
public virtual MetaObject BindCreateInstance(CreateInstanceBinder info, MetaObject[] args){…}
public virtual MetaObject BindGetIndex(GetIndexBinder info, MetaObject[] indices){…}
public virtual MetaObject BindSetIndex(SetIndexBinder, MetaObject[] inds, MetaObject value){…}
public virtual MetaObject BindDeleteIndex(DeleteIndexBinder info, MetaObject[] indices){…}
}
BinaryOp
==
map(f, my_ints)
AndAlso
Parameter
x
Constant
Map Function
TypeIs
Parameter
Func<int,object>
y
TypeIs
int[]
Parameter
z
IronPython
IronRuby
C#
VB.NET
Others…
Dynamic Language Runtime
Expression Trees
Object
Binder
JavaScript
Binder
Dynamic Dispatch
Python
Binder
Call Site Caching
Ruby
Binder
COM
Binder



http://codeplex.com/ironpython









http://codeplex.com/ironpython
www.microsoftpdc.com
© 2008 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.
The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market
conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation.
MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.
Descargar

TL10: Dynamic Languages on .NET