From 456fa3a282e946c579c34a91cb35eece9bd98180 Mon Sep 17 00:00:00 2001 From: Bill Robertson Date: Thu, 15 Oct 2009 23:23:53 -0400 Subject: [PATCH] Crazy clunky type convert system or something good? --- .gitignore | 1 + extconf.rb | 9 ++++ generic_data.cpp | 7 +++ generic_data.h | 52 ++++++++++++++++++++++ ruby_data.cpp | 8 ++++ ruby_data.h | 63 +++++++++++++++++++++++++++ spec/therubyracer_spec.rb | 7 ++- supported_types.txt | 16 +++++++ t.rb | 6 +-- v8.cpp | 19 +++++--- v8_data.cpp | 9 ++++ v8_data.h | 92 +++++++++++++++++++++++++++++++++++++++ 12 files changed, 275 insertions(+), 14 deletions(-) create mode 100644 generic_data.cpp create mode 100644 generic_data.h create mode 100644 ruby_data.cpp create mode 100644 ruby_data.h create mode 100644 supported_types.txt create mode 100644 v8_data.cpp create mode 100644 v8_data.h diff --git a/.gitignore b/.gitignore index 93d61d7..c5ea03c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ Makefile v8.bundle *.o *.log +*~ diff --git a/extconf.rb b/extconf.rb index 4dd3170..5895566 100644 --- a/extconf.rb +++ b/extconf.rb @@ -4,3 +4,12 @@ dir_config('v8') have_library('v8') or raise "unable to find libv8" create_makefile('v8') + +# now add a few extra targets +File.open("Makefile", "a") do |makefile| +makefile.print < + +class StringDest { + + public: + StringDest(); + ~StringDest(); + + std::string pushString(const char* value, const char* name=0) { + std::string convertedValue(value); + return convertedValue; + } + + /* + const char* pushInt(int32_t value, const char* name=0) { + char buffer[64]; + std::sprintf(buffer, "%d", value); + convertedValue = buffer; + return convertedValue.c_str(); + } + */ + + std::string pushInt(int64_t value, const char* name=0) { + char buffer[64]; + std::sprintf(buffer, "%lld", value); + std::string convertedValue(buffer); + return convertedValue; + } + + std::string pushDouble(double value, const char* name=0) { + char buffer[64]; + std::sprintf(buffer, "%g", value); + std::string convertedValue(buffer); + return convertedValue; + } + + std::string pushBool(bool value, const char* name=0) { + std::string convertedValue(value ? "true" : "false"); + return convertedValue; + } + + std::string pushNull(const char* name=0) { + return ""; + } + +}; + +#endif diff --git a/ruby_data.cpp b/ruby_data.cpp new file mode 100644 index 0000000..2e3e399 --- /dev/null +++ b/ruby_data.cpp @@ -0,0 +1,8 @@ +#include "ruby_data.h" + + +RubyDest::RubyDest() { +} + +RubyDest::~RubyDest() { +} diff --git a/ruby_data.h b/ruby_data.h new file mode 100644 index 0000000..8ccdd55 --- /dev/null +++ b/ruby_data.h @@ -0,0 +1,63 @@ +#ifndef __ruby_data_h__ +#define __ruby_data_h__ + +#include + +template class RubyDataSource { + + T dest; + + public: + RubyDataSource() {} + ~RubyDataSource() {} + + R push(VALUE& value, const char* name=0) { + switch (TYPE(value)) { + case T_FIXNUM: + return dest.pushInt(FIX2INT(value), name); + case T_FLOAT: + return dest.pushDouble(NUM2DBL(value), name); + case T_STRING: + return dest.pushString(RSTRING(value)->ptr, name); + case T_NIL: + return dest.pushNull(name); + case T_TRUE: + return dest.pushBool(true, name); + case T_FALSE: + return dest.pushBool(false, name); + } + return false; + } +}; + +class RubyDest { + + public: + RubyDest(); + ~RubyDest(); + + VALUE pushString(const char* value, const char* name=0) { + return Qnil; + } + + VALUE pushInt(int64_t value, const char* name=0) { + return INT2FIX(value); + } + + VALUE pushDouble(double value, const char* name=0) { + return Qnil; + } + + VALUE pushBool(bool value, const char* name=0) { + return Qnil; + } + + VALUE pushNull(const char* name=0) { + return Qnil; + } + + +}; + + +#endif diff --git a/spec/therubyracer_spec.rb b/spec/therubyracer_spec.rb index 33130c0..5ff7c25 100644 --- a/spec/therubyracer_spec.rb +++ b/spec/therubyracer_spec.rb @@ -12,11 +12,14 @@ describe "The Ruby Racer" do eval("'Hello World'").should == "Hello World" end - it "can pass numbers back to ruby" do - eval("1").should == 1 + it "can pass doubles back to ruby" do eval("2.5").should == 2.5 end + it "can pass fixed numbers back to ruby" do + eval("1").should == 1 + end + it "can pass boolean values back to ruby" do eval("true").should be(true) eval("false").should be(false) diff --git a/supported_types.txt b/supported_types.txt new file mode 100644 index 0000000..2fd6d3a --- /dev/null +++ b/supported_types.txt @@ -0,0 +1,16 @@ +Short list of types that a receiver should handle: + +type expected method +------------------------------- + pushNull +boolean pushBool +int32 pushInt (overloaded on 32-bit int) +int64 pushInt (overloaded on 64-bit int) +double pushDouble +const char* pushString + +for lack of any better ideas have these functions return true on +success and false on error + +-- +should add more later. diff --git a/t.rb b/t.rb index 30830f8..99d995d 100644 --- a/t.rb +++ b/t.rb @@ -1,8 +1,4 @@ require 'v8' c = V8::Context.new -c.eval("5 + 2") - - - - +puts c.eval("18 + 8") diff --git a/v8.cpp b/v8.cpp index 394e9d6..feef207 100644 --- a/v8.cpp +++ b/v8.cpp @@ -1,5 +1,6 @@ -#include "ruby.h" -#include "v8.h" +#include "ruby_data.h" +#include "v8_data.h" +#include "generic_data.h" #include typedef struct v8_context { @@ -50,15 +51,19 @@ void v8_free(v8_context *s) { VALUE eval(VALUE self, VALUE javascript) { v8_context* s = 0; Data_Get_Struct(self, struct v8_context, s); - const char* text = RSTRING(javascript)->ptr; - v8::Context::Scope context_scope(s->context); v8::HandleScope handle_scope; - v8::Handle source = v8::String::New(text); + + RubyDataSource tostring; + const std::string text(tostring.push(javascript)); + printf("v8_allocate(\"%s\")\n", text.c_str()); + v8::Handle source = v8::String::New(text.c_str()); v8::Handle script = v8::Script::Compile(source); + v8::Handle local_result = script->Run(); - printf("number value: %g\n", local_result->NumberValue()); - return Qnil; + V8HandleSource toValue; + return toValue.push(local_result); + } diff --git a/v8_data.cpp b/v8_data.cpp new file mode 100644 index 0000000..3b492a5 --- /dev/null +++ b/v8_data.cpp @@ -0,0 +1,9 @@ +#include "v8_data.h" +/* +V8ScopeDest::V8ScopeDest(v8::Context::Scope& scopeArg) : scope(scopeArg) { +} + +V8ScopeDest::~V8ScopeDest() { +} +*/ + diff --git a/v8_data.h b/v8_data.h new file mode 100644 index 0000000..7b1301f --- /dev/null +++ b/v8_data.h @@ -0,0 +1,92 @@ +#ifndef __v8_data_h__ +#define __v8_data_h__ + +#include "v8.h" +#include "stdint.h" +#include + + +template class V8HandleSource { + + T dest; + + public: + + V8HandleSource() {} + ~V8HandleSource() {} + + R push(v8::Handle& value, const char* name = 0) { + + printf("******* enter push()\n"); + + if(value->IsNull()) { + return dest.pushNull(name); + } + printf("******* isNull() == false\n"); + + if(value->IsTrue()) { + return dest.pushBool(true, name); + } + printf("******* isTrue() == false\n"); + + if(value->IsFalse()) { + return dest.pushBool(false, name); + } + printf("******* isFalse() == false\n"); + + + if(value->IsString()) { + //v8::Local strValue(value->ToString()); + return dest.pushString("", name); + } + printf("******* isString() == false\n"); + + if(value->IsInt32()) { + return dest.pushInt(value->Int32Value(), name); + } + printf("******* isInt32() == false\n"); + + + if(value->IsNumber()) { + return dest.pushDouble(value->NumberValue(), name); + } + printf("******* isNumber() == false\n"); + + + } + +}; + +/* +class V8ScopeDest { + + v8::Context::Scope& scope; + + public: + V8ScopeDest(v8::Context::Scope& scope); + ~V8ScopeDest(); + + bool pushString(const char* value, const char* name=0) { + // convert and insert + return false; + } + + bool pushInt(int64_t value, const char* name=0) { + return pushDouble(value, name); + } + + bool pushDouble(double value, const char* name=0) { + // convert and insert + return false; + } + + bool pushBool(bool value, const char* name=0) { + // convert and insert + return false; + } + +}; +*/ + + +#endif