rubyscript.cpp
1/***************************************************************************
2 * rubyscript.h
3 * This file is part of the KDE project
4 * copyright (C)2005 by Cyrille Berger (cberger@cberger.net)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 ***************************************************************************/
19
20#include "rubyscript.h"
21#include "rubyvariant.h"
22
23#define HAVE_STRLCAT_PROTO 1
24#define HAVE_STRLCPY_PROTO 1
25#include "config.h"
26
27#include <ruby.h>
28
29#ifndef HAVE_RUBY_1_9
30#include <env.h>
31#include <rubysig.h>
32#include <node.h>
33#else // HAVE_RUBY_1_9
34#ifndef HAVE_RUBY_3
35#include <ruby/backward/rubysig.h>
36#endif // HAVE_RUBY_3
37#endif // HAVE_RUBY_1_9
38
39#include <main/scriptcontainer.h>
40
41#include "rubyconfig.h"
42#include "rubyextension.h"
43#include "rubyinterpreter.h"
44
45namespace Kross {
46
47namespace Ruby {
48
49namespace Internals {
50 namespace Script {
51 static VALUE method_added(VALUE self, VALUE unit)
52 {
53 rb_funcall(self, rb_intern("module_function"), unit);
54 return self;
55 }
56 };
57};
58
59class RubyScriptPrivate {
60 friend class RubyScript;
61
62 RubyScriptPrivate() : m_script(0), m_hasBeenCompiled(false)
63 {
64 if(RubyScriptPrivate::s_krossScript == 0)
65 {
66 RubyScriptPrivate::s_krossScript = rb_define_class_under(RubyInterpreter::krossModule(), "Script", rb_cModule);
67 rb_define_method(RubyScriptPrivate::s_krossScript, "method_added", (VALUE (*)(...))Internals::Script::method_added, 1);
68 }
69 }
70 VALUE m_script;
71 static VALUE s_krossScript;
72 bool m_hasBeenCompiled;
73
75 TQStringList m_functions;
76
78 TQStringList m_classes;
79};
80
81VALUE RubyScriptPrivate::s_krossScript = 0;
82
84 : Kross::Api::Script(interpreter, scriptcontainer), d(new RubyScriptPrivate())
85{
86}
87
88
92
93void RubyScript::compile()
94{
95#ifdef KROSS_RUBY_SCRIPT_DEBUG
96 krossdebug("RubyScript::compile()");
97#endif
98 int critical;
99
100#ifdef HAVE_RUBY_1_9
101 // FIXME
102 int ruby_nerrs = 0;
103 int ruby_errinfo = Qnil;
104#else // HAVE_RUBY_1_9
105 ruby_nerrs = 0;
106 ruby_errinfo = Qnil;
107#endif // HAVE_RUBY_1_9
108 VALUE src = RubyExtension::toVALUE( m_scriptcontainer->getCode() );
109 StringValue(src);
110 VALUE name = RubyExtension::toVALUE( m_scriptcontainer->getName() );
111
112#ifdef HAVE_RUBY_1_9
113 // FIXME
114#else // HAVE_RUBY_1_9
115 critical = rb_thread_critical;
116 rb_thread_critical = Qtrue;
117 ruby_in_eval++;
118#endif // HAVE_RUBY_1_9
119 rb_funcall(d->m_script, rb_intern("module_eval"), 2, src, name);
120#ifdef HAVE_RUBY_1_9
121 // FIXME
122#else // HAVE_RUBY_1_9
123 ruby_in_eval--;
124 rb_thread_critical = critical;
125#endif // HAVE_RUBY_1_9
126
127 if (ruby_nerrs != 0)
128 {
129#ifdef KROSS_RUBY_SCRIPT_DEBUG
130 krossdebug("Compilation has failed");
131#endif
132 VALUE errorstring = rb_obj_as_string(ruby_errinfo);
133 setException( new Kross::Api::Exception(TQString("Failed to compile ruby code: %1").arg(STR2CSTR( errorstring )), 0) ); // TODO: get the error
134 } else {
135 d->m_hasBeenCompiled = true;
136 }
137#ifdef KROSS_RUBY_SCRIPT_DEBUG
138 krossdebug("Compilation was successfull");
139#endif
140}
141
142const TQStringList& RubyScript::getFunctionNames()
143{
144#ifdef KROSS_RUBY_SCRIPT_DEBUG
145 krossdebug("RubyScript::getFunctionNames()");
146#endif
147 if(not d->m_hasBeenCompiled )
148 {
149 compile();
150 }
151 return d->m_functions;
152}
153
155{
156#ifdef KROSS_RUBY_SCRIPT_DEBUG
157 krossdebug("RubyScript::execute()");
158#endif
159 // TODO: catch ruby exception
160 compile();
161#if 0
162 if (result != 0)
163 {
164#ifdef KROSS_RUBY_SCRIPT_DEBUG
165 krossdebug("Execution has failed");
166#endif
167 if( TYPE( ruby_errinfo ) == T_DATA && RubyExtension::isOfExceptionType( ruby_errinfo ) )
168 {
169#ifdef KROSS_RUBY_SCRIPT_DEBUG
170 krossdebug("Kross exception");
171#endif
172 setException( RubyExtension::convertToException( ruby_errinfo ) );
173 } else {
174 setException( new Kross::Api::Exception(TQString("Failed to execute ruby code: %1").arg(STR2CSTR( rb_obj_as_string(ruby_errinfo) )), 0) ); // TODO: get the error
175 }
176 }
177#endif // 0
178
179#ifdef KROSS_RUBY_SCRIPT_DEBUG
180 krossdebug("Execution is finished");
181#endif
182 return 0;
183}
184
186{
187 Q_UNUSED(name)
188 Q_UNUSED(args)
189#ifdef KROSS_RUBY_SCRIPT_DEBUG
190 krossdebug("RubyScript::callFunction()");
191#endif
192 if(not d->m_hasBeenCompiled )
193 {
194 compile();
195 }
196
197 Q_ASSERT(d->m_hasBeenCompiled );
198
199#ifdef HAVE_RUBY_1_9
200 // FIXME
201 int ruby_errinfo = Qnil;
202#endif // HAVE_RUBY_1_9
203
204#if 0
205 // FIXME
206 // The original code never really did anything as far as I can tell!
207 TQVariant result;
208 int r = ruby_exec();
209 if (r != 0) {
210 #ifdef KROSS_RUBY_SCRIPT_DEBUG
211 krossdebug("RubyScript::callFunction failed");
212 #endif
213 VALUE errorstring = rb_obj_as_string(ruby_errinfo);
214 setException( new Kross::Api::Exception(TQString("Failed to call function \"%1\": %2").arg(name).arg(STR2CSTR( errorstring )), 0) ); // TODO: get the error
215 }
216 else {
217 VALUE self = rb_eval_string("self");
218 //krossdebug(TQString("RubyScript::callFunction() ===> %1").arg(STR2CSTR(rb_inspect(self))));
219
220 const int rnargs = args.size();
221 VALUE *rargs = new VALUE[rnargs];
222 for(int i = 0; i < rnargs; ++i) {
223 rargs[i] = RubyType<TQVariant>::toVALUE( args[i] );
224 }
225
226 //VALUE r = rb_eval_string("myFunc()");
227 VALUE v = rb_funcall2(self, rb_intern(name.toLatin1()), rnargs, rargs);
229 delete[] rargs;
230 }
231#endif
232
233 return 0;
234}
235
236const TQStringList& RubyScript::getClassNames()
237{
238#ifdef KROSS_RUBY_SCRIPT_DEBUG
239 krossdebug("RubyScript::getClassNames()");
240#endif
241 if(not d->m_hasBeenCompiled )
242 {
243 compile();
244 }
245 return d->m_classes;
246}
247
249{
250 Q_UNUSED(name)
251#ifdef KROSS_RUBY_SCRIPT_DEBUG
252 krossdebug("RubyScript::classInstance()");
253#endif
254 if(not d->m_hasBeenCompiled )
255 {
256 compile();
257 }
258
259 Q_ASSERT(d->m_hasBeenCompiled );
260
261 // FIXME
262 // The original code never really did anything from what I can tell!
263
264 return 0;
265}
266
267
268}
269
270}
Common exception class used for representing exceptions in Kross.
Definition exception.h:39
Base class for interpreters.
TDESharedPtr< List > Ptr
Shared pointer to implement reference-counting.
Definition list.h:44
TDESharedPtr< Object > Ptr
Shared pointer to implement reference-counting.
Definition object.h:57
The ScriptContainer class is something like a single standalone scriptfile.
const TQString getName() const
TQString getCode() const
Return the scriptcode this ScriptContainer holds.
void setException(Exception::Ptr e)
Set a new exception this script throwed.
Definition script.cpp:50
ScriptContainer *const m_scriptcontainer
The ScriptContainer associated with this Script.
Definition script.h:130
virtual Kross::Api::Object::Ptr callFunction(const TQString &name, Kross::Api::List::Ptr args)
Call a function.
RubyScript(Kross::Api::Interpreter *interpreter, Kross::Api::ScriptContainer *scriptcontainer)
Constructor.
virtual const TQStringList & getClassNames()
Return a list of class types this script supports.
virtual Kross::Api::Object::Ptr execute()
Execute the script.
virtual Kross::Api::Object::Ptr classInstance(const TQString &name)
Create and return a new class instance.
virtual const TQStringList & getFunctionNames()
Return a list of callable functionnames this script spends.
The Kross scripting bridge to embed scripting functionality into an application.
Definition callable.h:31
void krossdebug(const TQString &s)
Debugging function.
The RubyType helper classes used to cast between TQVariant and VALUE values.