Thread overview
Make D a dynamic language.
Feb 05, 2008
sclytrack
Feb 05, 2008
Christopher Wright
Feb 05, 2008
Russell Lewis
Feb 06, 2008
Daniel Lewis
February 05, 2008
Make D a dynamic language.

struct, class, dynamic.

Introduce a dynamic type in D. Where you can add methods to it at runtime. Speed should be less of an issue. Provide a simple syntax in D to make the method calls.

var obj = new CustomDynamicObject();

obj.doStuff();
//not checked at compile time since it is dynamic. doStuff might not exist,
but it still compiles.

obj[x] = 10;   //Support for the usual syntax.


/me hides
February 05, 2008
sclytrack wrote:
> Make D a dynamic language.
> 
> struct, class, dynamic.
> 
> Introduce a dynamic type in D. Where you can add methods to it at runtime.
> Speed should be less of an issue. Provide a simple syntax in D to make the
> method calls.
> 
> var obj = new CustomDynamicObject();
> 
> obj.doStuff();
> //not checked at compile time since it is dynamic. doStuff might not exist,
> but it still compiles.
> 
> obj[x] = 10;   //Support for the usual syntax.
> 
> 
> /me hides

No.

You could do something similar, but using strings and it'd be a lot more obvious what you were doing. Make a method that accepts a string and varargs and dispatches to a stored delegate based on the args. The stored delegates would have to be generated at compile time, of course.

Ugly, but it works. Or just use MiniD.
February 05, 2008
Although it wouldn't be as elegant as a native language solution, you could accomplish (somewhat) the same with an associative-array of varargs delegates.  To make it work with member variables as well as methods would be a bit harder, but it could be done.  Maybe something like:

WARNING UNTESTED CODE

struct Dynamic {
  void delegate(...)[char[]] fields;
}

void AddDynamicMethod(Dynamic *dyn,
                      char[] name, void delegate(...) dg)
{
  dyn.fields[name] = dg;
}

void AddDynamicMethod(Dynamic *dyn,
                      char[] name, void function(Dynamic*,...) func)
{
  // this requires that you have some curry() template function.
  // Various people have written 'em.
  dyn.fields[name] = curry(func, dyn);
}

void AddDynamicVariable(T)(Dynamic *dyn,
                           char[] name, T val)
{
  // this works on 2.0 because 2.0 now has automatic closures
  dyn.fields[name] = delegate void(...)
                    {
                      // confirm that the varargs parameters are correct
                      assert(_arguments.length == 1);
                      assert(_arguments[0] == typeid(T*));
                      T *retval = va_arg!(T*)(_argptr);
                      *retval = val;
                    };
}

void Call(TPL...)(Dynamic *dyn, char[] name,TPL args)
{
  assert(name in dyn.fields);
  dyn.fields[name](args);
}

// this requires explicit template instantiation, as GetVar!(type)()
R CallWithRetval(R,TPL...)(Dynamic *dyn, char[] name, TPL args)
{
  // this uses the convention, for simplicity, that delegates that have
  // retvals will pass them using pointers as their first argument.

  R retval;
  assert(name in dyn.fields);
  dyn.fields[name](&R, args);
  return retval;
}

// this also requires explicit instantiation.  This is identical to
// CallWithRetval...it's just syntax sugar to make things clear.
R GetVar(R)()(Dynamic *dyn, char[] name)
{
  return CallWithRetval!(R)(dyn,name);
}



sclytrack wrote:
> Make D a dynamic language.
> 
> struct, class, dynamic.
> 
> Introduce a dynamic type in D. Where you can add methods to it at runtime.
> Speed should be less of an issue. Provide a simple syntax in D to make the
> method calls.
> 
> var obj = new CustomDynamicObject();
> 
> obj.doStuff();
> //not checked at compile time since it is dynamic. doStuff might not exist,
> but it still compiles.
> 
> obj[x] = 10;   //Support for the usual syntax.
> 
> 
> /me hides
February 06, 2008
Russell Lewis Wrote:

> Although it wouldn't be as elegant as a native language solution, you could accomplish (somewhat) the same with an associative-array of varargs delegates.

That's easy:

PSEUDOCODE

struct Value {
   union {
     Value[char] o;
     Value function(Value self, Value cc, Value[] arguments) f;
  }
  opIndex...
  opIndexAssign...
  opCall...
}

Optimize and extend from there.

PSEUDOCODE

Value x;
x['bob'](x, x, [x,x]);

Regards,
Dan