Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
September 16, 2005 Expose D Objects as DMDScript Objects | ||||
---|---|---|---|---|
| ||||
How? :-) |
September 16, 2005 Re: Expose D Objects as DMDScript Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kyle Furlong | Kyle Furlong escribió: > How? :-) I think this belongs to the DMDScript newsgroup. Anyway, this should give you an idea of what you need. I haven't tested in a while, but it might just work ;) /* Digital Mars DMDScript source code. * Copyright (c) 2000-2002 by Chromium Communications * D version Copyright (c) 2004-2005 by Digital Mars * All Rights Reserved * written by Walter Bright * www.digitalmars.com * Use at your own risk. There is no warranty, express or implied. * License for redistribution is by the GNU General Public License in gpl.txt. * * A binary, non-exclusive license for commercial use can be * purchased from www.digitalmars.com/dscript/buy.html. * * DMDScript is implemented in the D Programming Language, * www.digitalmars.com/d/ * * For a C++ implementation of DMDScript, including COM support, * see www.digitalmars.com/dscript/cpp.html. */ module testscript; import std.conv; import std.path; import std.file; import std.stdio; import dmdscript.script; enum { EXITCODE_INIT_ERROR = 1, EXITCODE_INVALID_ARGS = 2, EXITCODE_RUNTIME_ERROR = 3, } class C:Dobject { int _p; int _q; this(ThreadContext *tc) { super(tc.Dobject_prototype); Put("p",0,0); Put("1",0,0); } int opIndex(int idx) { if (idx==1) return _q; throw new Exception( format("[opIndex] index out of bounds: ",idx)); } void opIndexAssign(int v,int idx) { if (idx==1) { _q=v; Put("1",_q,0); } else throw new Exception(format("[opIndexAssign] index out of bounds: ",idx)); } void p(int newP) { _p=newP; Put("p",newP,0); } int p() { return _p; } Value* Put(d_string PropertyName, Value* value, uint attributes) { if (PropertyName=="p") { _p=cast(int)value.toNumber(); writefln("[0: c.p changed to ",_p,"]"); } else if (PropertyName=="1") { _q=cast(int)value.toNumber(); writefln("[0: c.q changed to ",_q,"]"); } return super.Put(PropertyName,value,attributes); } Value* Put(Identifier* key, Value* value, uint attributes) { if (key.toString=="p") { _p=cast(int)value.toNumber(); writefln("[1: c.p changed to ",_p,"]"); } else if (key.toString=="1") { _q=cast(int)value.toNumber(); writefln("[1: c.q changed to ",_q,"]"); } return super.Put(key,value,attributes); } Value* Put(d_string PropertyName, Dobject o, uint attributes) { if (PropertyName=="p") { _p=cast(int)o.value.toNumber(); writefln("[2: c.p changed to ",_p,"]"); } else if (PropertyName=="1") { _q=cast(int)o.value.toNumber(); writefln("[2: c.q changed to ",_q,"]"); } return super.Put(PropertyName,o,attributes); } Value* Put(d_string PropertyName, d_number n, uint attributes) { if (PropertyName=="p") { _p=cast(int)n; writefln("[3: c.p changed to ",_p,"]"); } else if (PropertyName=="1") { _q=cast(int)n; writefln("[3: c.q changed to ",_q,"]"); } return super.Put(PropertyName,n,attributes); } Value* Put(d_string PropertyName, d_string s, uint attributes) { if (PropertyName=="p") { _p=toInt(s); writefln("[4: c.p changed to ",_p,"]"); } else if (PropertyName=="1") { _q=toInt(s); writefln("[4: c.q changed to ",_q,"]"); } return super.Put(PropertyName,s,attributes); } Value* Put(d_uint32 index, Value* vindex, Value* value, uint attributes) { if (index==1) { _q=cast(int)value.toNumber(); writefln("[5: c.q changed to ",_q,"]"); } return super.Put(index,vindex,value,attributes); } Value* Put(d_uint32 index, Value* value, uint attributes) { if (index==1) { _q=cast(int)value.toNumber(); writefln("[5: c.q changed to ",_q,"]"); } return super.Put(index,value,attributes); } /* Value* Get(d_string PropertyName) { return Get(PropertyName, Value.calcHash(PropertyName)); } Value* Get(Identifier* id) { Value* v; //writefln("Dobject.Get(this = %x, '%s', hash = %x)", cast(uint)cast(void*)this, PropertyName, hash); //writef("\tinternal_prototype = %p\n", this.internal_prototype); //writef("\tDfunction.getPrototype() = %p\n", Dfunction.getPrototype()); v = proptable.get(&id.value, id.value.hash); //if (v) writef("found it %p\n", v.object); return v; } Value* Get(d_string PropertyName, uint hash) { Value* v; //writefln("Dobject.Get(this = %x, '%s', hash = %x)", cast(uint)cast(void*)this, PropertyName, hash); //writef("\tinternal_prototype = %p\n", this.internal_prototype); //writef("\tDfunction.getPrototype() = %p\n", Dfunction.getPrototype()); v = proptable.get(PropertyName, hash); //if (v) writef("found it %p\n", v.object); return v; } Value* Get(d_uint32 index) { Value* v; v = proptable.get(index); // if (!v) // v = &vundefined; return v; } Value* Get(d_uint32 index, Value* vindex) { return proptable.get(vindex, Value.calcHash(index)); } */ } C c; int main(char[][] args) { char [][] src; do { writef(">"); fflush(stdout); char * buf = new char[80]; gets(buf); char [] tmp = std.string.toString(buf); if (tmp.length>0 && tmp[0]=='#') { delete buf; break; } src ~= tmp.dup; } while (true) SrcFile f=new SrcFile(std.string.join(src,"\r\n")); f.compile(); ThreadContext *tc; tc = ThreadContext.getThreadContext(); assert(tc != null); c=new C(tc); c.p=4; c[1]=9; PutValue(f.program.callcontext,"c",&c.value); writefln("[c.p=",c.p,"]"); writefln("[c[1]=",c[1],"]"); f.execute(); writefln("[c.p=",c.p,"]"); writefln("[c[1]=",c[1],"]"); return EXIT_SUCCESS; } class SrcFile { char[] srcfile; char[][] includes; Program program; char[] buffer; this (char [] src) { buffer = /*"var c=new Object();c.p="~format(c.p)~" ;" ~*/ src.dup ~ ";"; } this(char[] srcfilename, char[][] includes) { /* DMDScript source files default to a '.ds' extension */ srcfile = std.path.defaultExt(srcfilename, "ds"); this.includes = includes; } void read() { /* Read the source file, prepend the include files, * and put it all in buffer[]. Allocate an extra byte * to buffer[] and terminate it with a 0x1A. * (If the 0x1A isn't at the end, the lexer will put * one there, forcing an extra copy to be made of the * source text.) */ //writef("read file '%s'\n",srcfile); // Read the includes[] files uint i; void[] buf; ulong len; len = std.file.getSize(srcfile); foreach (char[] filename; includes) { len += std.file.getSize(filename); } len++; // leave room for sentinal assert(len < uint.max); // Prefix the includes[] files buffer = new tchar[len]; foreach (char[] filename; includes) { buf = std.file.read(filename); buffer[i .. i + buf.length] = cast(char[])buf[]; i += buf.length; } buf = std.file.read(srcfile); buffer[i .. i + buf.length] = cast(char[])buf[]; i += buf.length; buffer[i] = 0x1A; // ending sentinal i++; assert(i == len); } void compile() { /* Create a DMDScript program, and compile our text buffer. */ program = new Program(); program.compile(srcfile, buffer, null); } void execute() { /* Execute the resulting program. */ program.execute(null); } } -- Carlos Santander Bernal |
September 16, 2005 Re: Expose D Objects as DMDScript Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Carlos Santander | Carlos Santander wrote:
> Kyle Furlong escribió:
>
>> How? :-)
>
>
> I think this belongs to the DMDScript newsgroup.
>
> Anyway, this should give you an idea of what you need. I haven't tested in a while, but it might just work ;)
>
>
> /* Digital Mars DMDScript source code.
> * Copyright (c) 2000-2002 by Chromium Communications
> * D version Copyright (c) 2004-2005 by Digital Mars
> * All Rights Reserved
> * written by Walter Bright
> * www.digitalmars.com
> * Use at your own risk. There is no warranty, express or implied.
> * License for redistribution is by the GNU General Public License in gpl.txt.
> *
> * A binary, non-exclusive license for commercial use can be
> * purchased from www.digitalmars.com/dscript/buy.html.
> *
> * DMDScript is implemented in the D Programming Language,
> * www.digitalmars.com/d/
> *
> * For a C++ implementation of DMDScript, including COM support,
> * see www.digitalmars.com/dscript/cpp.html.
> */
>
>
> module testscript;
>
> import std.conv;
> import std.path;
> import std.file;
> import std.stdio;
>
> import dmdscript.script;
>
> enum
> {
> EXITCODE_INIT_ERROR = 1,
> EXITCODE_INVALID_ARGS = 2,
> EXITCODE_RUNTIME_ERROR = 3,
> }
>
> class C:Dobject
> {
> int _p;
> int _q;
>
> this(ThreadContext *tc)
> {
> super(tc.Dobject_prototype);
>
> Put("p",0,0);
> Put("1",0,0);
> }
>
> int opIndex(int idx)
> {
> if (idx==1) return _q;
> throw new Exception( format("[opIndex] index out of bounds: ",idx));
> }
>
> void opIndexAssign(int v,int idx)
> {
> if (idx==1)
> {
> _q=v;
> Put("1",_q,0);
> }
> else
> throw new Exception(format("[opIndexAssign] index out of bounds: ",idx));
> }
>
> void p(int newP)
> {
> _p=newP;
> Put("p",newP,0);
> }
>
> int p() { return _p; }
>
> Value* Put(d_string PropertyName, Value* value, uint attributes)
> {
> if (PropertyName=="p")
> {
> _p=cast(int)value.toNumber();
> writefln("[0: c.p changed to ",_p,"]");
> }
> else if (PropertyName=="1")
> {
> _q=cast(int)value.toNumber();
> writefln("[0: c.q changed to ",_q,"]");
> }
> return super.Put(PropertyName,value,attributes);
> }
>
> Value* Put(Identifier* key, Value* value, uint attributes)
> {
> if (key.toString=="p")
> {
> _p=cast(int)value.toNumber();
> writefln("[1: c.p changed to ",_p,"]");
> }
> else if (key.toString=="1")
> {
> _q=cast(int)value.toNumber();
> writefln("[1: c.q changed to ",_q,"]");
> }
> return super.Put(key,value,attributes);
> }
>
> Value* Put(d_string PropertyName, Dobject o, uint attributes)
> {
> if (PropertyName=="p")
> {
> _p=cast(int)o.value.toNumber();
> writefln("[2: c.p changed to ",_p,"]");
> }
> else if (PropertyName=="1")
> {
> _q=cast(int)o.value.toNumber();
> writefln("[2: c.q changed to ",_q,"]");
> }
> return super.Put(PropertyName,o,attributes);
> }
>
> Value* Put(d_string PropertyName, d_number n, uint attributes)
> {
> if (PropertyName=="p")
> {
> _p=cast(int)n;
> writefln("[3: c.p changed to ",_p,"]");
> }
> else if (PropertyName=="1")
> {
> _q=cast(int)n;
> writefln("[3: c.q changed to ",_q,"]");
> }
> return super.Put(PropertyName,n,attributes);
> }
>
> Value* Put(d_string PropertyName, d_string s, uint attributes)
> {
> if (PropertyName=="p")
> {
> _p=toInt(s);
> writefln("[4: c.p changed to ",_p,"]");
> }
> else if (PropertyName=="1")
> {
> _q=toInt(s);
> writefln("[4: c.q changed to ",_q,"]");
> }
> return super.Put(PropertyName,s,attributes);
> }
>
>
>
> Value* Put(d_uint32 index, Value* vindex, Value* value, uint attributes)
> {
> if (index==1)
> {
> _q=cast(int)value.toNumber();
> writefln("[5: c.q changed to ",_q,"]");
> }
> return super.Put(index,vindex,value,attributes);
> }
>
> Value* Put(d_uint32 index, Value* value, uint attributes)
> {
> if (index==1)
> {
> _q=cast(int)value.toNumber();
> writefln("[5: c.q changed to ",_q,"]");
> }
> return super.Put(index,value,attributes);
> }
>
>
> /*
> Value* Get(d_string PropertyName)
> {
> return Get(PropertyName, Value.calcHash(PropertyName));
> }
>
> Value* Get(Identifier* id)
> {
> Value* v;
>
> //writefln("Dobject.Get(this = %x, '%s', hash = %x)", cast(uint)cast(void*)this, PropertyName, hash);
> //writef("\tinternal_prototype = %p\n", this.internal_prototype);
> //writef("\tDfunction.getPrototype() = %p\n", Dfunction.getPrototype());
> v = proptable.get(&id.value, id.value.hash);
> //if (v) writef("found it %p\n", v.object);
> return v;
> }
>
> Value* Get(d_string PropertyName, uint hash)
> {
> Value* v;
>
> //writefln("Dobject.Get(this = %x, '%s', hash = %x)", cast(uint)cast(void*)this, PropertyName, hash);
> //writef("\tinternal_prototype = %p\n", this.internal_prototype);
> //writef("\tDfunction.getPrototype() = %p\n", Dfunction.getPrototype());
> v = proptable.get(PropertyName, hash);
> //if (v) writef("found it %p\n", v.object);
> return v;
> }
>
> Value* Get(d_uint32 index)
> {
> Value* v;
>
> v = proptable.get(index);
> // if (!v)
> // v = &vundefined;
> return v;
> }
>
> Value* Get(d_uint32 index, Value* vindex)
> {
> return proptable.get(vindex, Value.calcHash(index));
> }
> */
> }
>
> C c;
>
> int main(char[][] args)
> {
>
> char [][] src;
>
> do
> {
> writef(">");
> fflush(stdout);
> char * buf = new char[80];
> gets(buf);
> char [] tmp = std.string.toString(buf);
> if (tmp.length>0 && tmp[0]=='#')
> {
> delete buf;
> break;
> }
> src ~= tmp.dup;
> }
> while (true)
> SrcFile f=new SrcFile(std.string.join(src,"\r\n"));
> f.compile();
>
> ThreadContext *tc;
> tc = ThreadContext.getThreadContext();
> assert(tc != null);
> c=new C(tc);
> c.p=4;
> c[1]=9;
> PutValue(f.program.callcontext,"c",&c.value);
> writefln("[c.p=",c.p,"]");
> writefln("[c[1]=",c[1],"]");
>
> f.execute();
>
> writefln("[c.p=",c.p,"]");
> writefln("[c[1]=",c[1],"]");
>
> return EXIT_SUCCESS;
> }
>
> class SrcFile
> {
> char[] srcfile;
> char[][] includes;
>
> Program program;
> char[] buffer;
>
> this (char [] src)
> {
> buffer = /*"var c=new Object();c.p="~format(c.p)~" ;" ~*/ src.dup ~ ";";
> }
>
> this(char[] srcfilename, char[][] includes)
> {
> /* DMDScript source files default to a '.ds' extension
> */
>
> srcfile = std.path.defaultExt(srcfilename, "ds");
> this.includes = includes;
> }
>
> void read()
> {
> /* Read the source file, prepend the include files,
> * and put it all in buffer[]. Allocate an extra byte
> * to buffer[] and terminate it with a 0x1A.
> * (If the 0x1A isn't at the end, the lexer will put
> * one there, forcing an extra copy to be made of the
> * source text.)
> */
>
> //writef("read file '%s'\n",srcfile);
>
> // Read the includes[] files
> uint i;
> void[] buf;
> ulong len;
>
> len = std.file.getSize(srcfile);
> foreach (char[] filename; includes)
> {
> len += std.file.getSize(filename);
> }
> len++; // leave room for sentinal
>
> assert(len < uint.max);
>
> // Prefix the includes[] files
>
> buffer = new tchar[len];
>
> foreach (char[] filename; includes)
> {
> buf = std.file.read(filename);
> buffer[i .. i + buf.length] = cast(char[])buf[];
> i += buf.length;
> }
>
> buf = std.file.read(srcfile);
> buffer[i .. i + buf.length] = cast(char[])buf[];
> i += buf.length;
>
> buffer[i] = 0x1A; // ending sentinal
> i++;
> assert(i == len);
> }
>
> void compile()
> {
> /* Create a DMDScript program, and compile our text buffer.
> */
>
> program = new Program();
> program.compile(srcfile, buffer, null);
> }
>
> void execute()
> {
> /* Execute the resulting program.
> */
>
> program.execute(null);
> }
> }
>
Okay, but I have a more complicated design requirement. The object cannot inherit from Dobject. The D object cannot know anything about DMDScript. Basically the scripting package is implemented as a plugin, with the main code only knowing about certain interfaces. An ideal solution of course would be to use reflection, but thats a ways away I guess.
|
September 17, 2005 Re: Expose D Objects as DMDScript Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kyle Furlong | Kyle Furlong escribió: > > Okay, but I have a more complicated design requirement. The object cannot inherit from Dobject. The D object cannot know anything about DMDScript. Basically the scripting package is implemented as a plugin, with the main code only knowing about certain interfaces. An ideal solution of course would be to use reflection, but thats a ways away I guess. Wrap your D object in a Dobject subclass. I did that when (in another sample) I changed a button's caption using DMDScript. The button knew nothing about DMDScript, of course. I don't know, there should be a way to get it done. -- Carlos Santander Bernal |
September 17, 2005 Re: Expose D Objects as DMDScript Objects | ||||
---|---|---|---|---|
| ||||
Posted in reply to Carlos Santander | Carlos Santander wrote: > Kyle Furlong escribió: > >> >> Okay, but I have a more complicated design requirement. The object cannot inherit from Dobject. The D object cannot know anything about DMDScript. Basically the scripting package is implemented as a plugin, with the main code only knowing about certain interfaces. An ideal solution of course would be to use reflection, but thats a ways away I guess. > > > Wrap your D object in a Dobject subclass. I did that when (in another sample) I changed a button's caption using DMDScript. The button knew nothing about DMDScript, of course. I don't know, there should be a way to get it done. > What I meant was that the code which has the D object must be completely scripting language agnostic. So it could implement an IScriptable interface or such but that is about the extent of it. The design is for a game engine. So I am trying to implement a plugin system whereby any subsystem can be changed out for a different implementation. So you could use DirectX or OpenGL, or use Lua or DMDScript, all you would have to do is write a dll with certain requirements. The pertinent classes/interfaces are: <code> /**************************************** ScriptingEngine.d - ScriptingEngine Implementation Author: Kyle Furlong Date: Sept. 13, 2005 ****************************************/ module Dluge.Plugings.Scripting.ScriptingEngine; private { import Dluge.All; import Dluge.Plugins.Scripting.Script; import std.c.windows.windows; import std.stdio; import std.string; import dmdscript.program; import dmdscript.dglobal; } extern(C) { export IScriptingEngine Create() { return new ScriptingEngineImpl(); } } private class ScriptingEngineImpl : IScriptingEngine { public IScript Create(char[] source) { return new Script(source); } public bit Initialize() { writefln("Scripting Engine Initialize"); return true; } public bit Initialized() { return true; } private int i = 0; public void Frame() { //writefln(format(i++)); } public void Shutdown() { } } extern (C) { void gc_init(); void gc_term(); void _minit(); void _moduleCtor(); void _moduleUnitTests(); } extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: gc_init(); // initialize GC _minit(); // initialize module list _moduleCtor(); // run module constructors _moduleUnitTests(); // run module unit tests break; case DLL_PROCESS_DETACH: gc_term(); // shut down GC break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: // Multiple threads not supported yet return false; } return true; } /**************************************** Script.d - IScript Implementation for DMDScript Author: Kyle Furlong Date: Sept. 15, 2005 ****************************************/ module Dluge.Plugins.Scripting.Script; private { import Dluge.All; import dmdscript.program; import std.date; } public class Script : IScript { private char[] name = ""; public char[] Name() { return name; } private char[] source = ""; public char[] Source() { return source; } private Program program; this(char[] source) { this.program = new Program(); this.source = source; this.name = std.string.toString(getUTCtime()); } bit Run(char[][] args) { try { program.execute(args); return true; } catch(ScriptException e) { return false; } } bit Compile() { try { program.compile(name, source, null); return true; } catch(ScriptException e) { return false; } } void AddObject(char[] name, *IScriptable* o) // This needs to be worked on { program.callcontext.global.Put(name, o, DontEnum); } void RemoveObject(char[] name) { program.callcontext.global.Delete(name); } } /**************************************** IScript.d - Script interface Author: Kyle Furlong Date: Sept. 12, 2005 ****************************************/ module Dluge.Scripting.IScript; private { import Dluge.Common; } public interface IScript { bit Run(char[][] args); bit Compile(); void AddObject(char[] name, Object o); void RemoveObject(char[] name); } /**************************************** ScriptingEngine.d - Scripting engine interface Author: Kyle Furlong Date: Sept. 12, 2005 ****************************************/ module Dluge.Scripting.ScriptingEngine; private { import Dluge.Plugin; import Dluge.Common; import Dluge.Scripting.IScript; } public static class ScriptingEngine { mixin PluginProxy!(IScriptingEngine); } public interface IScriptingEngine : IPlugin { IScript Create(char[] script); } </code> _______________________________________________________ Let me know if you have any insight. |
Copyright © 1999-2021 by the D Language Foundation