You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
7.0 KiB
268 lines
7.0 KiB
/***************************************************************************
|
|
* rubyscript.h
|
|
* This file is part of the KDE project
|
|
* copyright (C)2005 by Cyrille Berger (cberger@cberger.net)
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this program; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
***************************************************************************/
|
|
|
|
#include "rubyscript.h"
|
|
#include "rubyvariant.h"
|
|
|
|
#define HAVE_STRLCAT_PROTO 1
|
|
#define HAVE_STRLCPY_PROTO 1
|
|
#include "config.h"
|
|
|
|
#include <ruby.h>
|
|
|
|
#ifndef HAVE_RUBY_1_9
|
|
#include <env.h>
|
|
#include <rubysig.h>
|
|
#include <node.h>
|
|
#else // HAVE_RUBY_1_9
|
|
#include <ruby/backward/rubysig.h>
|
|
#endif // HAVE_RUBY_1_9
|
|
|
|
#include <main/scriptcontainer.h>
|
|
|
|
#include "rubyconfig.h"
|
|
#include "rubyextension.h"
|
|
#include "rubyinterpreter.h"
|
|
|
|
namespace Kross {
|
|
|
|
namespace Ruby {
|
|
|
|
namespace Internals {
|
|
namespace Script {
|
|
static VALUE method_added(VALUE self, VALUE unit)
|
|
{
|
|
rb_funcall(self, rb_intern("module_function"), unit);
|
|
return self;
|
|
}
|
|
};
|
|
};
|
|
|
|
class RubyScriptPrivate {
|
|
friend class RubyScript;
|
|
|
|
RubyScriptPrivate() : m_script(0), m_hasBeenCompiled(false)
|
|
{
|
|
if(RubyScriptPrivate::s_krossScript == 0)
|
|
{
|
|
RubyScriptPrivate::s_krossScript = rb_define_class_under(RubyInterpreter::krossModule(), "Script", rb_cModule);
|
|
rb_define_method(RubyScriptPrivate::s_krossScript, "method_added", (VALUE (*)(...))Internals::Script::method_added, 1);
|
|
}
|
|
}
|
|
VALUE m_script;
|
|
static VALUE s_krossScript;
|
|
bool m_hasBeenCompiled;
|
|
|
|
/// A list of functionnames.
|
|
TQStringList m_functions;
|
|
|
|
/// A list of classnames.
|
|
TQStringList m_classes;
|
|
};
|
|
|
|
VALUE RubyScriptPrivate::s_krossScript = 0;
|
|
|
|
RubyScript::RubyScript(Kross::Api::Interpreter* interpreter, Kross::Api::ScriptContainer* scriptcontainer)
|
|
: Kross::Api::Script(interpreter, scriptcontainer), d(new RubyScriptPrivate())
|
|
{
|
|
}
|
|
|
|
|
|
RubyScript::~RubyScript()
|
|
{
|
|
}
|
|
|
|
void RubyScript::compile()
|
|
{
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("RubyScript::compile()");
|
|
#endif
|
|
int critical;
|
|
|
|
#ifdef HAVE_RUBY_1_9
|
|
// FIXME
|
|
int ruby_nerrs = 0;
|
|
int ruby_errinfo = Qnil;
|
|
#else // HAVE_RUBY_1_9
|
|
ruby_nerrs = 0;
|
|
ruby_errinfo = Qnil;
|
|
#endif // HAVE_RUBY_1_9
|
|
VALUE src = RubyExtension::toVALUE( m_scriptcontainer->getCode() );
|
|
StringValue(src);
|
|
|
|
#ifdef HAVE_RUBY_1_9
|
|
// FIXME
|
|
#else // HAVE_RUBY_1_9
|
|
critical = rb_thread_critical;
|
|
rb_thread_critical = Qtrue;
|
|
ruby_in_eval++;
|
|
#endif // HAVE_RUBY_1_9
|
|
rb_funcall(d->m_script, rb_intern("module_eval"), 2, src, (char*) m_scriptcontainer->getName().latin1());
|
|
#ifdef HAVE_RUBY_1_9
|
|
// FIXME
|
|
#else // HAVE_RUBY_1_9
|
|
ruby_in_eval--;
|
|
rb_thread_critical = critical;
|
|
#endif // HAVE_RUBY_1_9
|
|
|
|
if (ruby_nerrs != 0)
|
|
{
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("Compilation has failed");
|
|
#endif
|
|
VALUE errorstring = rb_obj_as_string(ruby_errinfo);
|
|
setException( new Kross::Api::Exception(TQString("Failed to compile ruby code: %1").arg(STR2CSTR( errorstring )), 0) ); // TODO: get the error
|
|
} else {
|
|
d->m_hasBeenCompiled = true;
|
|
}
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("Compilation was successfull");
|
|
#endif
|
|
}
|
|
|
|
const TQStringList& RubyScript::getFunctionNames()
|
|
{
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("RubyScript::getFunctionNames()");
|
|
#endif
|
|
if(not d->m_hasBeenCompiled )
|
|
{
|
|
compile();
|
|
}
|
|
return d->m_functions;
|
|
}
|
|
|
|
Kross::Api::Object::Ptr RubyScript::execute()
|
|
{
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("RubyScript::execute()");
|
|
#endif
|
|
// TODO: catch ruby exception
|
|
compile();
|
|
#if 0
|
|
if (result != 0)
|
|
{
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("Execution has failed");
|
|
#endif
|
|
if( TYPE( ruby_errinfo ) == T_DATA && RubyExtension::isOfExceptionType( ruby_errinfo ) )
|
|
{
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("Kross exception");
|
|
#endif
|
|
setException( RubyExtension::convertToException( ruby_errinfo ) );
|
|
} else {
|
|
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
|
|
}
|
|
}
|
|
#endif // 0
|
|
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("Execution is finished");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
Kross::Api::Object::Ptr RubyScript::callFunction(const TQString& name, Kross::Api::List::Ptr args)
|
|
{
|
|
Q_UNUSED(name)
|
|
Q_UNUSED(args)
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("RubyScript::callFunction()");
|
|
#endif
|
|
if(not d->m_hasBeenCompiled )
|
|
{
|
|
compile();
|
|
}
|
|
|
|
Q_ASSERT(d->m_hasBeenCompiled );
|
|
|
|
#ifdef HAVE_RUBY_1_9
|
|
// FIXME
|
|
int ruby_errinfo = Qnil;
|
|
#endif // HAVE_RUBY_1_9
|
|
|
|
#if 0
|
|
// FIXME
|
|
// The original code never really did anything as far as I can tell!
|
|
TQVariant result;
|
|
int r = ruby_exec();
|
|
if (r != 0) {
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("RubyScript::callFunction failed");
|
|
#endif
|
|
VALUE errorstring = rb_obj_as_string(ruby_errinfo);
|
|
setException( new Kross::Api::Exception(TQString("Failed to call function \"%1\": %2").arg(name).arg(STR2CSTR( errorstring )), 0) ); // TODO: get the error
|
|
}
|
|
else {
|
|
VALUE self = rb_eval_string("self");
|
|
//krossdebug(QString("RubyScript::callFunction() ===> %1").arg(STR2CSTR(rb_inspect(self))));
|
|
|
|
const int rnargs = args.size();
|
|
VALUE *rargs = new VALUE[rnargs];
|
|
for(int i = 0; i < rnargs; ++i) {
|
|
rargs[i] = RubyType<TQVariant>::toVALUE( args[i] );
|
|
}
|
|
|
|
//VALUE r = rb_eval_string("myFunc()");
|
|
VALUE v = rb_funcall2(self, rb_intern(name.toLatin1()), rnargs, rargs);
|
|
result = RubyType<TQVariant>::toVariant(v);
|
|
delete[] rargs;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
const TQStringList& RubyScript::getClassNames()
|
|
{
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("RubyScript::getClassNames()");
|
|
#endif
|
|
if(not d->m_hasBeenCompiled )
|
|
{
|
|
compile();
|
|
}
|
|
return d->m_classes;
|
|
}
|
|
|
|
Kross::Api::Object::Ptr RubyScript::classInstance(const TQString& name)
|
|
{
|
|
Q_UNUSED(name)
|
|
#ifdef KROSS_RUBY_SCRIPT_DEBUG
|
|
krossdebug("RubyScript::classInstance()");
|
|
#endif
|
|
if(not d->m_hasBeenCompiled )
|
|
{
|
|
compile();
|
|
}
|
|
|
|
Q_ASSERT(d->m_hasBeenCompiled );
|
|
|
|
// FIXME
|
|
// The original code never really did anything from what I can tell!
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|