[439] | 1 | #include "proto_to_ruby.h"
|
---|
| 2 |
|
---|
| 3 | using namespace ruby_fuzzer;
|
---|
| 4 |
|
---|
| 5 | std::string protoConverter::removeSpecial(const std::string &x)
|
---|
| 6 | {
|
---|
| 7 | std::string tmp(x);
|
---|
| 8 | if (!tmp.empty())
|
---|
| 9 | tmp.erase(std::remove_if(tmp.begin(), tmp.end(),
|
---|
| 10 | [](char c) { return !(std::isalpha(c) || std::isdigit(c)); } ), tmp.end());
|
---|
| 11 | return tmp;
|
---|
| 12 | }
|
---|
| 13 |
|
---|
| 14 | void protoConverter::visit(ArrType const& x)
|
---|
| 15 | {
|
---|
| 16 | if (x.elements_size() > 0) {
|
---|
| 17 | int i = x.elements_size();
|
---|
| 18 | m_output << "[";
|
---|
| 19 | for (auto &e : x.elements()) {
|
---|
| 20 | i--;
|
---|
| 21 | if (i == 0) {
|
---|
| 22 | visit(e);
|
---|
| 23 | } else {
|
---|
| 24 | visit(e);
|
---|
| 25 | m_output << ", ";
|
---|
| 26 | }
|
---|
| 27 | }
|
---|
| 28 | m_output << "]";
|
---|
| 29 | } else {
|
---|
| 30 | m_output << "[1]";
|
---|
| 31 | }
|
---|
| 32 | }
|
---|
| 33 |
|
---|
| 34 | void protoConverter::visit(Array const& x)
|
---|
| 35 | {
|
---|
| 36 | switch (x.arr_func()) {
|
---|
| 37 | case Array::FLATTEN:
|
---|
| 38 | visit(x.arr_arg());
|
---|
| 39 | m_output << ".flatten";
|
---|
| 40 | break;
|
---|
| 41 | case Array::COMPACT:
|
---|
| 42 | visit(x.arr_arg());
|
---|
| 43 | m_output << ".compact";
|
---|
| 44 | break;
|
---|
| 45 | case Array::FETCH:
|
---|
| 46 | visit(x.arr_arg());
|
---|
| 47 | m_output << ".fetch";
|
---|
| 48 | break;
|
---|
| 49 | case Array::FILL:
|
---|
| 50 | visit(x.arr_arg());
|
---|
| 51 | m_output << ".fill";
|
---|
| 52 | break;
|
---|
| 53 | case Array::ROTATE:
|
---|
| 54 | visit(x.arr_arg());
|
---|
| 55 | m_output << ".rotate";
|
---|
| 56 | break;
|
---|
| 57 | case Array::ROTATE_E:
|
---|
| 58 | visit(x.arr_arg());
|
---|
| 59 | m_output << ".rotate!";
|
---|
| 60 | break;
|
---|
| 61 | case Array::DELETEIF:
|
---|
| 62 | visit(x.arr_arg());
|
---|
| 63 | m_output << ".delete_if";
|
---|
| 64 | break;
|
---|
| 65 | case Array::INSERT:
|
---|
| 66 | visit(x.arr_arg());
|
---|
| 67 | m_output << ".insert";
|
---|
| 68 | break;
|
---|
| 69 | case Array::BSEARCH:
|
---|
| 70 | visit(x.arr_arg());
|
---|
| 71 | m_output << ".bsearch";
|
---|
| 72 | break;
|
---|
| 73 | case Array::KEEPIF:
|
---|
| 74 | visit(x.arr_arg());
|
---|
| 75 | m_output << ".keep_if";
|
---|
| 76 | break;
|
---|
| 77 | case Array::SELECT:
|
---|
| 78 | visit(x.arr_arg());
|
---|
| 79 | m_output << ".select";
|
---|
| 80 | break;
|
---|
| 81 | case Array::VALUES_AT:
|
---|
| 82 | visit(x.arr_arg());
|
---|
| 83 | m_output << ".values_at";
|
---|
| 84 | break;
|
---|
| 85 | case Array::BLOCK:
|
---|
| 86 | visit(x.arr_arg());
|
---|
| 87 | m_output << ".index";
|
---|
| 88 | break;
|
---|
| 89 | case Array::DIG:
|
---|
| 90 | visit(x.arr_arg());
|
---|
| 91 | m_output << ".dig";
|
---|
| 92 | break;
|
---|
| 93 | case Array::SLICE:
|
---|
| 94 | visit(x.arr_arg());
|
---|
| 95 | m_output << ".slice";
|
---|
| 96 | break;
|
---|
| 97 | case Array::PERM:
|
---|
| 98 | visit(x.arr_arg());
|
---|
| 99 | m_output << ".permutation";
|
---|
| 100 | break;
|
---|
| 101 | case Array::COMB:
|
---|
| 102 | visit(x.arr_arg());
|
---|
| 103 | m_output << ".combination";
|
---|
| 104 | break;
|
---|
| 105 | case Array::ASSOC:
|
---|
| 106 | visit(x.arr_arg());
|
---|
| 107 | m_output << ".assoc";
|
---|
| 108 | break;
|
---|
| 109 | case Array::RASSOC:
|
---|
| 110 | visit(x.arr_arg());
|
---|
| 111 | m_output << ".rassoc";
|
---|
| 112 | break;
|
---|
| 113 | }
|
---|
| 114 | m_output << "(";
|
---|
| 115 | visit(x.val_arg());
|
---|
| 116 | m_output << ")";
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | void protoConverter::visit(AssignmentStatement const& x)
|
---|
| 120 | {
|
---|
| 121 | m_output << "var_" << m_numLiveVars << " = ";
|
---|
| 122 | visit(x.rvalue());
|
---|
| 123 | m_numVarsPerScope.top()++;
|
---|
| 124 | m_numLiveVars++;
|
---|
| 125 | m_output << "\n";
|
---|
| 126 | }
|
---|
| 127 |
|
---|
| 128 | void protoConverter::visit(BinaryOp const& x)
|
---|
| 129 | {
|
---|
| 130 | m_output << "(";
|
---|
| 131 | visit(x.left());
|
---|
| 132 | switch (x.op()) {
|
---|
| 133 | case BinaryOp::ADD: m_output << " + "; break;
|
---|
| 134 | case BinaryOp::SUB: m_output << " - "; break;
|
---|
| 135 | case BinaryOp::MUL: m_output << " * "; break;
|
---|
| 136 | case BinaryOp::DIV: m_output << " / "; break;
|
---|
| 137 | case BinaryOp::MOD: m_output << " % "; break;
|
---|
| 138 | case BinaryOp::XOR: m_output << " ^ "; break;
|
---|
| 139 | case BinaryOp::AND: m_output << " and "; break;
|
---|
| 140 | case BinaryOp::OR: m_output << " or "; break;
|
---|
| 141 | case BinaryOp::EQ: m_output << " == "; break;
|
---|
| 142 | case BinaryOp::NE: m_output << " != "; break;
|
---|
| 143 | case BinaryOp::LE: m_output << " <= "; break;
|
---|
| 144 | case BinaryOp::GE: m_output << " >= "; break;
|
---|
| 145 | case BinaryOp::LT: m_output << " < "; break;
|
---|
| 146 | case BinaryOp::GT: m_output << " > "; break;
|
---|
| 147 | case BinaryOp::RS: m_output << " >> "; break;
|
---|
| 148 | }
|
---|
| 149 | visit(x.right());
|
---|
| 150 | m_output << ")";
|
---|
| 151 | }
|
---|
| 152 |
|
---|
| 153 | void protoConverter::visit(BuiltinFuncs const& x)
|
---|
| 154 | {
|
---|
| 155 | switch (x.bifunc_oneof_case()) {
|
---|
| 156 | case BuiltinFuncs::kOs:
|
---|
| 157 | visit(x.os());
|
---|
| 158 | break;
|
---|
| 159 | case BuiltinFuncs::kTime:
|
---|
| 160 | visit(x.time());
|
---|
| 161 | break;
|
---|
| 162 | case BuiltinFuncs::kArr:
|
---|
| 163 | visit(x.arr());
|
---|
| 164 | break;
|
---|
| 165 | case BuiltinFuncs::kMops:
|
---|
| 166 | visit(x.mops());
|
---|
| 167 | break;
|
---|
| 168 | case BuiltinFuncs::BIFUNC_ONEOF_NOT_SET:
|
---|
| 169 | m_output << "1";
|
---|
| 170 | break;
|
---|
| 171 | }
|
---|
| 172 | m_output << "\n";
|
---|
| 173 | }
|
---|
| 174 |
|
---|
| 175 | void protoConverter::visit(Const const& x)
|
---|
| 176 | {
|
---|
| 177 | switch (x.const_oneof_case()) {
|
---|
| 178 | case Const::kIntLit:
|
---|
| 179 | m_output << "(" << (x.int_lit() % 13) << ")";
|
---|
| 180 | break;
|
---|
| 181 | case Const::kBoolVal:
|
---|
| 182 | m_output << "(" << x.bool_val() << ")";
|
---|
| 183 | break;
|
---|
| 184 | case Const::CONST_ONEOF_NOT_SET:
|
---|
| 185 | m_output << "1";
|
---|
| 186 | break;
|
---|
| 187 | }
|
---|
| 188 | }
|
---|
| 189 |
|
---|
| 190 | void protoConverter::visit(Function const& x)
|
---|
| 191 | {
|
---|
| 192 | m_output << "def foo()\nvar_0 = 1\n";
|
---|
| 193 | visit(x.statements());
|
---|
| 194 | m_output << "end\n";
|
---|
| 195 | m_output << "foo\n";
|
---|
| 196 | }
|
---|
| 197 |
|
---|
| 198 | void protoConverter::visit(HashType const& x)
|
---|
| 199 | {
|
---|
| 200 | if (x.keyval_size() > 0) {
|
---|
| 201 | int i = x.keyval_size();
|
---|
| 202 | m_output << "{";
|
---|
| 203 | for (auto &e : x.keyval()) {
|
---|
| 204 | i--;
|
---|
| 205 | if (i == 0) {
|
---|
| 206 | visit(e);
|
---|
| 207 | }
|
---|
| 208 | else {
|
---|
| 209 | visit(e);
|
---|
| 210 | m_output << ", ";
|
---|
| 211 | }
|
---|
| 212 | }
|
---|
| 213 | m_output << "}";
|
---|
| 214 | }
|
---|
| 215 | }
|
---|
| 216 |
|
---|
| 217 | void protoConverter::visit(IfElse const& x)
|
---|
| 218 | {
|
---|
| 219 | m_output << "if ";
|
---|
| 220 | visit(x.cond());
|
---|
| 221 | m_output << "\n";
|
---|
| 222 | visit(x.if_body());
|
---|
| 223 | m_output << "\nelse\n";
|
---|
| 224 | visit(x.else_body());
|
---|
| 225 | m_output << "\nend\n";
|
---|
| 226 | }
|
---|
| 227 |
|
---|
| 228 | void protoConverter::visit(KVPair const& x)
|
---|
| 229 | {
|
---|
| 230 | m_output << "\"" << removeSpecial(x.key()) << "\"";
|
---|
| 231 | m_output << " => ";
|
---|
| 232 | m_output << "\"" << removeSpecial(x.val()) << "\"";
|
---|
| 233 | }
|
---|
| 234 |
|
---|
| 235 | void protoConverter::visit(MathConst const& x)
|
---|
| 236 | {
|
---|
| 237 | switch (x.math_const()) {
|
---|
| 238 | case MathConst::PI:
|
---|
| 239 | m_output << "Math::PI";
|
---|
| 240 | break;
|
---|
| 241 | case MathConst::E:
|
---|
| 242 | m_output << "Math::E";
|
---|
| 243 | break;
|
---|
| 244 | }
|
---|
| 245 | }
|
---|
| 246 |
|
---|
| 247 | void protoConverter::visit(MathOps const& x)
|
---|
| 248 | {
|
---|
| 249 | switch (x.math_op()) {
|
---|
| 250 | case MathOps::CBRT:
|
---|
| 251 | m_output << "Math.cbrt(";
|
---|
| 252 | visit(x.math_arg());
|
---|
| 253 | m_output << ")";
|
---|
| 254 | break;
|
---|
| 255 | case MathOps::COS:
|
---|
| 256 | m_output << "Math.cos(";
|
---|
| 257 | visit(x.math_arg());
|
---|
| 258 | m_output << ")";
|
---|
| 259 | break;
|
---|
| 260 | case MathOps::ERF:
|
---|
| 261 | m_output << "Math.erf(";
|
---|
| 262 | visit(x.math_arg());
|
---|
| 263 | m_output << ")";
|
---|
| 264 | break;
|
---|
| 265 | case MathOps::ERFC:
|
---|
| 266 | m_output << "Math.erfc(";
|
---|
| 267 | visit(x.math_arg());
|
---|
| 268 | m_output << ")";
|
---|
| 269 | break;
|
---|
| 270 | case MathOps::LOG:
|
---|
| 271 | m_output << "Math.log(";
|
---|
| 272 | visit(x.math_arg());
|
---|
| 273 | m_output << ")";
|
---|
| 274 | break;
|
---|
| 275 | case MathOps::LOG10:
|
---|
| 276 | m_output << "Math.log10(";
|
---|
| 277 | visit(x.math_arg());
|
---|
| 278 | m_output << ")";
|
---|
| 279 | break;
|
---|
| 280 | case MathOps::LOG2:
|
---|
| 281 | m_output << "Math.log2(";
|
---|
| 282 | visit(x.math_arg());
|
---|
| 283 | m_output << ")";
|
---|
| 284 | break;
|
---|
| 285 | case MathOps::SIN:
|
---|
| 286 | m_output << "Math.sin(";
|
---|
| 287 | visit(x.math_arg());
|
---|
| 288 | m_output << ")";
|
---|
| 289 | break;
|
---|
| 290 | case MathOps::SQRT:
|
---|
| 291 | m_output << "Math.sqrt(";
|
---|
| 292 | visit(x.math_arg());
|
---|
| 293 | m_output << ")";
|
---|
| 294 | break;
|
---|
| 295 | case MathOps::TAN:
|
---|
| 296 | m_output << "Math.tan(";
|
---|
| 297 | visit(x.math_arg());
|
---|
| 298 | m_output << ")";
|
---|
| 299 | break;
|
---|
| 300 | }
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | void protoConverter::visit(MathType const& x)
|
---|
| 304 | {
|
---|
| 305 | switch (x.math_arg_oneof_case()) {
|
---|
| 306 | case MathType::kMathRval:
|
---|
| 307 | visit(x.math_rval());
|
---|
| 308 | break;
|
---|
| 309 | case MathType::kMathConst:
|
---|
| 310 | visit(x.math_const());
|
---|
| 311 | break;
|
---|
| 312 | case MathType::MATH_ARG_ONEOF_NOT_SET:
|
---|
| 313 | m_output << "1";
|
---|
| 314 | break;
|
---|
| 315 | }
|
---|
| 316 | }
|
---|
| 317 |
|
---|
| 318 | void protoConverter::visit(ObjectSpace const& x)
|
---|
| 319 | {
|
---|
| 320 | switch (x.os_func()) {
|
---|
| 321 | case ObjectSpace::COUNT:
|
---|
| 322 | m_output << "ObjectSpace.count_objects";
|
---|
| 323 | break;
|
---|
| 324 | }
|
---|
| 325 | m_output << "(";
|
---|
| 326 | visit(x.os_arg());
|
---|
| 327 | m_output << ")" << "\n";
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | void protoConverter::visit(Rvalue const& x)
|
---|
| 331 | {
|
---|
| 332 | switch (x.rvalue_oneof_case()) {
|
---|
| 333 | case Rvalue::kVarref:
|
---|
| 334 | visit(x.varref());
|
---|
| 335 | break;
|
---|
| 336 | case Rvalue::kCons:
|
---|
| 337 | visit(x.cons());
|
---|
| 338 | break;
|
---|
| 339 | case Rvalue::kBinop:
|
---|
| 340 | visit(x.binop());
|
---|
| 341 | break;
|
---|
| 342 | case Rvalue::RVALUE_ONEOF_NOT_SET:
|
---|
| 343 | m_output << "1";
|
---|
| 344 | break;
|
---|
| 345 | }
|
---|
| 346 | }
|
---|
| 347 |
|
---|
| 348 | void protoConverter::visit(Statement const& x)
|
---|
| 349 | {
|
---|
| 350 | switch (x.stmt_oneof_case()) {
|
---|
| 351 | case Statement::kAssignment:
|
---|
| 352 | visit(x.assignment());
|
---|
| 353 | break;
|
---|
| 354 | case Statement::kIfelse:
|
---|
| 355 | visit(x.ifelse());
|
---|
| 356 | break;
|
---|
| 357 | case Statement::kTernaryStmt:
|
---|
| 358 | visit(x.ternary_stmt());
|
---|
| 359 | break;
|
---|
| 360 | case Statement::kBuiltins:
|
---|
| 361 | visit(x.builtins());
|
---|
| 362 | break;
|
---|
| 363 | case Statement::kBlockstmt:
|
---|
| 364 | visit(x.blockstmt());
|
---|
| 365 | break;
|
---|
| 366 | case Statement::STMT_ONEOF_NOT_SET:
|
---|
| 367 | break;
|
---|
| 368 | }
|
---|
| 369 | m_output << "\n";
|
---|
| 370 | }
|
---|
| 371 |
|
---|
| 372 | void protoConverter::visit(StatementSeq const& x)
|
---|
| 373 | {
|
---|
| 374 | if (x.statements_size() > 0) {
|
---|
| 375 | m_numVarsPerScope.push(0);
|
---|
| 376 | m_output << "@scope ||= begin\n";
|
---|
| 377 | for (auto &st : x.statements())
|
---|
| 378 | visit(st);
|
---|
| 379 | m_output << "end\n";
|
---|
| 380 | m_numLiveVars -= m_numVarsPerScope.top();
|
---|
| 381 | m_numVarsPerScope.pop();
|
---|
| 382 | }
|
---|
| 383 | }
|
---|
| 384 |
|
---|
| 385 | void protoConverter::visit(StringExtNoArg const& x)
|
---|
| 386 | {
|
---|
| 387 | m_output << "\"" << removeSpecial(x.str_arg()) << "\"";
|
---|
| 388 | switch (x.str_op()) {
|
---|
| 389 | case StringExtNoArg::DUMP:
|
---|
| 390 | m_output << ".dump";
|
---|
| 391 | break;
|
---|
| 392 | case StringExtNoArg::STRIP:
|
---|
| 393 | m_output << ".strip";
|
---|
| 394 | break;
|
---|
| 395 | case StringExtNoArg::LSTRIP:
|
---|
| 396 | m_output << ".lstrip";
|
---|
| 397 | break;
|
---|
| 398 | case StringExtNoArg::RSTRIP:
|
---|
| 399 | m_output << ".rstrip";
|
---|
| 400 | break;
|
---|
| 401 | case StringExtNoArg::STRIPE:
|
---|
| 402 | m_output << ".strip!";
|
---|
| 403 | break;
|
---|
| 404 | case StringExtNoArg::LSTRIPE:
|
---|
| 405 | m_output << ".lstrip!";
|
---|
| 406 | break;
|
---|
| 407 | case StringExtNoArg::RSTRIPE:
|
---|
| 408 | m_output << ".rstrip!";
|
---|
| 409 | break;
|
---|
| 410 | case StringExtNoArg::SWAPCASE:
|
---|
| 411 | m_output << ".swapcase";
|
---|
| 412 | break;
|
---|
| 413 | case StringExtNoArg::SWAPCASEE:
|
---|
| 414 | m_output << ".swapcase!";
|
---|
| 415 | break;
|
---|
| 416 | case StringExtNoArg::SQUEEZE:
|
---|
| 417 | m_output << ".squeeze";
|
---|
| 418 | break;
|
---|
| 419 | }
|
---|
| 420 | }
|
---|
| 421 |
|
---|
| 422 | void protoConverter::visit(Ternary const& x)
|
---|
| 423 | {
|
---|
| 424 | m_output << "(";
|
---|
| 425 | visit(x.tern_cond());
|
---|
| 426 | m_output << " ? ";
|
---|
| 427 | visit(x.t_branch());
|
---|
| 428 | m_output << " : ";
|
---|
| 429 | visit(x.f_branch());
|
---|
| 430 | m_output << ")\n";
|
---|
| 431 | }
|
---|
| 432 |
|
---|
| 433 | void protoConverter::visit(Time const& x)
|
---|
| 434 | {
|
---|
| 435 | switch (x.t_func()) {
|
---|
| 436 | case Time::AT:
|
---|
| 437 | m_output << "Time.at";
|
---|
| 438 | break;
|
---|
| 439 | case Time::GM:
|
---|
| 440 | m_output << "Time.gm";
|
---|
| 441 | break;
|
---|
| 442 | }
|
---|
| 443 | m_output << "(" << (x.t_arg()% 13) << ")" << "\n";
|
---|
| 444 | }
|
---|
| 445 |
|
---|
| 446 | void protoConverter::visit(VarRef const& x)
|
---|
| 447 | {
|
---|
| 448 | m_output << "var_" << (static_cast<uint32_t>(x.varnum()) % m_numLiveVars);
|
---|
| 449 | }
|
---|
| 450 |
|
---|
| 451 | std::string protoConverter::FunctionToString(Function const& input)
|
---|
| 452 | {
|
---|
| 453 | visit(input);
|
---|
| 454 | return m_output.str();
|
---|
| 455 | }
|
---|