00001
00002
00003
00004
00005
00006
00007
00008 #include "v8_generator.h"
00009 #include "be_extern.h"
00010
00011 #include "utl_identifier.h"
00012
00013 using namespace AstTypeClassification;
00014
00015 void v8_generator::fwd_decl()
00016 {
00017 if (first_) {
00018 be_global->add_include("<v8.h>", BE_GlobalData::STREAM_CPP);
00019 first_ = false;
00020 be_global->header_ <<
00021 "namespace v8 {\n"
00022 " class Value;\n"
00023 "}\n\n";
00024 }
00025 }
00026
00027 bool v8_generator::gen_enum(AST_Enum*, UTL_ScopedName*, const std::vector<AST_EnumVal*>&,
00028 const char*)
00029 {
00030 return true;
00031 }
00032
00033 namespace {
00034
00035 std::string getV8Type(AST_Type* type,
00036 AST_PredefinedType::PredefinedType* pt = 0)
00037 {
00038 const Classification cls = classify(type);
00039 if (cls & (CL_ENUM | CL_STRING)) return "String";
00040 if (cls & (CL_STRUCTURE | CL_UNION)) return "Object";
00041 if (cls & (CL_ARRAY | CL_SEQUENCE)) return "Array";
00042 if (cls & CL_PRIMITIVE) {
00043 AST_Type* actual = resolveActualType(type);
00044 AST_PredefinedType* p = AST_PredefinedType::narrow_from_decl(actual);
00045 if (pt) *pt = p->pt();
00046 switch (p->pt()) {
00047 case AST_PredefinedType::PT_char:
00048 case AST_PredefinedType::PT_wchar:
00049 return "String";
00050 case AST_PredefinedType::PT_boolean:
00051 return "Boolean";
00052 case AST_PredefinedType::PT_octet:
00053 case AST_PredefinedType::PT_ushort:
00054 case AST_PredefinedType::PT_short:
00055 case AST_PredefinedType::PT_ulong:
00056 case AST_PredefinedType::PT_long:
00057 return "Integer";
00058 default:
00059 return "Number";
00060 }
00061 }
00062 return "";
00063 }
00064
00065 bool builtInSeq(AST_Type* type)
00066 {
00067 const std::string name = scoped(type->name());
00068 static const char PRE[] = "CORBA::";
00069 if (std::strncmp(name.c_str(), PRE, sizeof(PRE) - 1)) return false;
00070 return name.rfind("Seq") == name.size() - 3;
00071 }
00072
00073 void gen_copyto(const char* tgt, const char* src, AST_Type* type,
00074 const char* prop)
00075 {
00076 const Classification cls = classify(type);
00077 AST_PredefinedType::PredefinedType pt = AST_PredefinedType::PT_void;
00078 const std::string v8Type = getV8Type(type, &pt),
00079 propName = std::string(tgt) + "->Set(" + prop + ", ";
00080
00081 if (cls & CL_SCALAR) {
00082 std::string prefix, suffix, v8fn = "New";
00083
00084 if (cls & CL_ENUM) {
00085 const std::string underscores =
00086 dds_generator::scoped_helper(type->name(), "_"),
00087 array = "gen_" + underscores + "_names";
00088 prefix = '(' + std::string(src) + " >= sizeof(" + array + ")/sizeof(" +
00089 array + "[0])) ? \"<<invalid>>\" : " + array + "[static_cast<int>(";
00090 suffix = ")]";
00091
00092 } else if (cls & CL_STRING) {
00093 if (cls & CL_WIDE) {
00094 be_global->impl_ <<
00095 " {\n"
00096 " const size_t len = ACE_OS::strlen(" << src << ".in());\n"
00097 " uint16_t* const str = new uint16_t[len + 1];\n"
00098 " for (size_t i = 0; i <= len; ++i) {\n"
00099 " str[i] = " << src << "[i];\n"
00100 " }\n"
00101 " " << propName << "v8::String::New(str));\n"
00102 " delete[] str;\n"
00103 " }\n";
00104 return;
00105 }
00106 suffix = ".in()";
00107
00108 } else if (pt == AST_PredefinedType::PT_char) {
00109 be_global->impl_ <<
00110 " {\n"
00111 " const char str[] = {" << src << ", 0};\n"
00112 " " << propName << "v8::String::New(str));\n"
00113 " }\n";
00114 return;
00115
00116 } else if (pt == AST_PredefinedType::PT_wchar) {
00117 be_global->impl_ <<
00118 " {\n"
00119 " const uint16_t str[] = {" << src << ", 0};\n"
00120 " " << propName << "v8::String::New(str));\n"
00121 " }\n";
00122 return;
00123
00124 } else if (pt == AST_PredefinedType::PT_ulong) {
00125 v8fn = "NewFromUnsigned";
00126 }
00127
00128 be_global->impl_ <<
00129 " " << propName << "v8::" << v8Type << "::" << v8fn << '('
00130 << prefix << src << suffix << "));\n";
00131
00132 } else if ((cls & CL_SEQUENCE) && builtInSeq(type)) {
00133 AST_Type* real_type = resolveActualType(type);
00134 AST_Sequence* seq = AST_Sequence::narrow_from_decl(real_type);
00135 AST_Type* elem = seq->base_type();
00136 be_global->impl_ <<
00137 " {\n"
00138 " const v8::Local<v8::Array> seq = v8::Array::New(" << src
00139 << ".length());\n"
00140 " for (CORBA::ULong j = 0; j < " << src << ".length(); ++j) {\n";
00141 gen_copyto("seq", (std::string(src) + "[j]").c_str(), elem, "j");
00142 be_global->impl_ <<
00143 " }\n"
00144 " " << propName << "seq" << ");\n"
00145 " }\n";
00146
00147 } else {
00148 be_global->impl_ <<
00149 " " << propName << "v8::Handle<v8::Value>(copyToV8("
00150 << src << ")));\n";
00151 }
00152 }
00153
00154 struct gen_field_copyto {
00155 gen_field_copyto(const char* tgt, const char* src) : tgt_(tgt), src_(src) {}
00156 const std::string tgt_, src_;
00157 void operator()(AST_Field* field) const
00158 {
00159 const std::string fieldName = field->local_name()->get_string(),
00160 source = src_ + '.' + fieldName,
00161 prop = "v8::String::NewSymbol(\"" + fieldName + "\")";
00162 gen_copyto(tgt_.c_str(), source.c_str(),
00163 field->field_type(), prop.c_str());
00164 }
00165 };
00166 }
00167
00168 bool v8_generator::gen_struct(AST_Structure*, UTL_ScopedName* name,
00169 const std::vector<AST_Field*>& fields,
00170 AST_Type::SIZE_TYPE, const char*)
00171 {
00172 fwd_decl();
00173 {
00174 NamespaceGuard ng;
00175 const std::string clazz = scoped(name);
00176 {
00177 Function ctv("copyToV8", "v8::Value*");
00178 ctv.addArg("src", "const " + clazz + '&');
00179 ctv.endArgs();
00180 be_global->impl_ <<
00181 " const v8::Local<v8::Object> stru = v8::Object::New();\n";
00182 std::for_each(fields.begin(), fields.end(),
00183 gen_field_copyto("stru", "src"));
00184 be_global->impl_ <<
00185 " return *stru;\n";
00186 }
00187 }
00188
00189 if (idl_global->is_dcps_type(name)) {
00190 be_global->add_include("dds/DCPS/V8TypeConverter.h",
00191 BE_GlobalData::STREAM_CPP);
00192 ScopedNamespaceGuard cppGuard(name, be_global->impl_);
00193 const std::string lname = name->last_component()->get_string(),
00194 tsv8 = lname + "TypeSupportV8Impl";
00195 be_global->impl_ <<
00196 "class " << tsv8 << "\n"
00197 " : public virtual " << lname << "TypeSupportImpl\n"
00198 " , public virtual OpenDDS::DCPS::V8TypeConverter {\n\n"
00199 " v8::Value* toV8(const void* source) const\n"
00200 " {\n"
00201 " return OpenDDS::DCPS::copyToV8(*static_cast<const " << lname
00202 << "*>(source));\n"
00203 " }\n\n"
00204 "public:\n"
00205 " struct Initializer {\n"
00206 " Initializer()\n"
00207 " {\n"
00208 " " << lname << "TypeSupport_var ts = new " << tsv8 << ";\n"
00209 " ts->register_type(0, \"\");\n"
00210 " }\n"
00211 " };\n"
00212 "};\n\n" <<
00213 tsv8 << "::Initializer init_tsv8_" << lname << ";\n";
00214 }
00215 return true;
00216 }
00217
00218 bool v8_generator::gen_typedef(AST_Typedef*, UTL_ScopedName* name, AST_Type* type,
00219 const char* )
00220 {
00221 fwd_decl();
00222 switch (type->node_type()) {
00223 case AST_Decl::NT_sequence: {
00224 NamespaceGuard ng;
00225 AST_Sequence* seq = AST_Sequence::narrow_from_decl(type);
00226 const std::string cxx = scoped(name);
00227 AST_Type* elem = seq->base_type();
00228 {
00229 Function ctv("copyToV8", "v8::Value*");
00230 ctv.addArg("src", "const " + cxx + '&');
00231 ctv.endArgs();
00232 be_global->impl_ <<
00233 " const v8::Local<v8::Array> tgt = v8::Array::New(src.length());\n"
00234 " for (CORBA::ULong i = 0; i < src.length(); ++i) {\n"
00235 " ";
00236 gen_copyto("tgt", "src[i]", elem, "i");
00237 be_global->impl_ <<
00238 " }\n"
00239 " return *tgt;\n";
00240 }
00241 break;
00242 }
00243 case AST_Decl::NT_array: {
00244
00245 break;
00246 }
00247 default:
00248 return true;
00249 }
00250 return true;
00251 }
00252
00253 bool v8_generator::gen_union(AST_Union*, UTL_ScopedName* ,
00254 const std::vector<AST_UnionBranch*>& ,
00255 AST_Type* , const char* )
00256 {
00257 fwd_decl();
00258 return true;
00259 }