11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2013 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/tools/profile_reset/jtl_compiler.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <limits>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <map>
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <numeric>
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/logging.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/profile_resetter/jtl_foundation.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/tools/profile_reset/jtl_parser.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace jtl = jtl_foundation;
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Serializes symbols into byte-code in a streaming manner.
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ByteCodeWriter {
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  explicit ByteCodeWriter(std::string* output) : output_(output) {}
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ~ByteCodeWriter() {}
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void WriteUint8(uint8 value) { output_->push_back(static_cast<char>(value)); }
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void WriteUint32(uint32 value) {
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (int i = 0; i < 4; ++i) {
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      output_->push_back(static_cast<char>(value & 0xFFu));
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      value >>= 8;
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void WriteOpCode(uint8 op_code) { WriteUint8(op_code); }
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void WriteHash(const std::string& hash) {
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CHECK(jtl::Hasher::IsHash(hash));
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    *output_ += hash;
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void WriteBool(bool value) { WriteUint8(value ? 1u : 0u); }
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string* output_;
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(ByteCodeWriter);
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Encapsulates meta-data about all instructions, and is capable of transcoding
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// each instruction from a parsed text-based format to byte-code.
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass InstructionSet {
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public:
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  InstructionSet() {
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Define each instruction in this list.
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Note:
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //  - Instructions ending in "hash" will write their 'HashString' arguments
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //    directly into the byte-code.
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //  - Instructions ending in "hashed" will first hash their 'String'
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    //    arguments, and will write this hash to the byte-code.
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("go", jtl::NAVIGATE, Arguments(String)));
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("any", jtl::NAVIGATE_ANY, Arguments()));
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("back", jtl::NAVIGATE_BACK, Arguments()));
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("store_bool", jtl::STORE_BOOL, Arguments(String, Bool)));
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("store_hash",
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::STORE_HASH, Arguments(String, HashString)));
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("store_hashed",
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::STORE_HASH, Arguments(String, String)));
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("store_node_bool",
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::STORE_NODE_BOOL, Arguments(String)));
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("store_node_hash",
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::STORE_NODE_HASH, Arguments(String)));
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("store_node_registerable_domain_hash",
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::STORE_NODE_REGISTERABLE_DOMAIN_HASH,
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    Arguments(String)));
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_bool", jtl::COMPARE_NODE_BOOL, Arguments(Bool)));
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_hashed",
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::COMPARE_NODE_HASH, Arguments(String)));
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_hashed_not",
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::COMPARE_NODE_HASH_NOT, Arguments(String)));
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_stored_bool",
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::COMPARE_STORED_BOOL,
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    Arguments(String, Bool, Bool)));
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_stored_hashed",
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::COMPARE_STORED_HASH,
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    Arguments(String, String, String)));
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_to_stored_bool",
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::COMPARE_NODE_TO_STORED_BOOL,
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    Arguments(String)));
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_to_stored_hash",
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::COMPARE_NODE_TO_STORED_HASH,
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    Arguments(String)));
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("compare_substring_hashed",
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    jtl::COMPARE_NODE_SUBSTRING,
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    Arguments(StringPattern)));
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Add(Instruction("break", jtl::STOP_EXECUTING_SENTENCE, Arguments()));
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  JtlCompiler::CompileError::ErrorCode TranscodeInstruction(
951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const std::string& name,
961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const base::ListValue& arguments,
971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      bool ends_sentence,
981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const jtl::Hasher& hasher,
991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ByteCodeWriter* target) const {
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (instruction_map_.count(name) == 0)
1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return JtlCompiler::CompileError::INVALID_OPERATION_NAME;
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const Instruction& instruction(instruction_map_.at(name));
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (instruction.argument_types.size() != arguments.GetSize())
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return JtlCompiler::CompileError::INVALID_ARGUMENT_COUNT;
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    target->WriteOpCode(instruction.op_code);
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (size_t i = 0; i < arguments.GetSize(); ++i) {
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      switch (instruction.argument_types[i]) {
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        case Bool: {
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          bool value = false;
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (!arguments.GetBoolean(i, &value))
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          target->WriteBool(value);
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          break;
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        case String: {
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          std::string value;
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (!arguments.GetString(i, &value))
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          target->WriteHash(hasher.GetHash(value));
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          break;
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        case StringPattern: {
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          std::string value;
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (!arguments.GetString(i, &value))
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (value.empty() ||
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              value.size() > std::numeric_limits<uint32>::max())
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            return JtlCompiler::CompileError::INVALID_ARGUMENT_VALUE;
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          target->WriteHash(hasher.GetHash(value));
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          target->WriteUint32(static_cast<uint32>(value.size()));
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          uint32 pattern_sum = std::accumulate(
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              value.begin(), value.end(), static_cast<uint32>(0u));
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          target->WriteUint32(pattern_sum);
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          break;
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        case HashString: {
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          std::string hash_value;
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          if (!arguments.GetString(i, &hash_value) ||
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              !jtl::Hasher::IsHash(hash_value))
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          target->WriteHash(hash_value);
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          break;
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        }
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        default:
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          NOTREACHED();
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          return JtlCompiler::CompileError::INVALID_ARGUMENT_TYPE;
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (ends_sentence)
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      target->WriteOpCode(jtl::END_OF_SENTENCE);
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return JtlCompiler::CompileError::ERROR_NONE;
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private:
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // The possible types of an operation's argument.
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  enum ArgumentType {
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    None,
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Bool,
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    String,
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    StringPattern,
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    HashString
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Encapsulates meta-data about one instruction.
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  struct Instruction {
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Instruction() : op_code(jtl::END_OF_SENTENCE) {}
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Instruction(const char* name,
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                jtl_foundation::OpCodes op_code,
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                const std::vector<ArgumentType>& argument_types)
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        : name(name), op_code(op_code), argument_types(argument_types) {}
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string name;
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    jtl::OpCodes op_code;
1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::vector<ArgumentType> argument_types;
1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  };
1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static std::vector<ArgumentType> Arguments(ArgumentType arg1_type = None,
1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             ArgumentType arg2_type = None,
1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             ArgumentType arg3_type = None) {
1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::vector<ArgumentType> result;
1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (arg1_type != None)
1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      result.push_back(arg1_type);
1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (arg2_type != None)
1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      result.push_back(arg2_type);
1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (arg3_type != None)
1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      result.push_back(arg3_type);
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return result;
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void Add(const Instruction& instruction) {
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    instruction_map_[instruction.name] = instruction;
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::map<std::string, Instruction> instruction_map_;
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DISALLOW_COPY_AND_ASSIGN(InstructionSet);
1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}  // namespace
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool JtlCompiler::Compile(const std::string& source_code,
2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          const std::string& hash_seed,
2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          std::string* output_bytecode,
2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          CompileError* error_details) {
2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(output_bytecode);
2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  InstructionSet instruction_set;
2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ByteCodeWriter bytecode_writer(output_bytecode);
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  jtl::Hasher hasher(hash_seed);
2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string compacted_source_code;
2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<size_t> newline_indices;
2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t mismatched_quotes_line;
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!JtlParser::RemoveCommentsAndAllWhitespace(source_code,
2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                 &compacted_source_code,
2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                 &newline_indices,
2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                 &mismatched_quotes_line)) {
2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (error_details) {
2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      error_details->context = "";  // No meaningful intra-line context here.
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      error_details->line_number = mismatched_quotes_line;
2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      error_details->error_code = CompileError::MISMATCHED_DOUBLE_QUOTES;
2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  JtlParser parser(compacted_source_code, newline_indices);
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  while (!parser.HasFinished()) {
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string operation_name;
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    base::ListValue arguments;
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool ends_sentence = false;
2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!parser.ParseNextOperation(
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci             &operation_name, &arguments, &ends_sentence)) {
2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (error_details) {
2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error_details->context = parser.GetLastContext();
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error_details->line_number = parser.GetLastLineNumber();
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error_details->error_code = CompileError::PARSING_ERROR;
2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    CompileError::ErrorCode error_code = instruction_set.TranscodeInstruction(
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        operation_name, arguments, ends_sentence, hasher, &bytecode_writer);
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (error_code != CompileError::ERROR_NONE) {
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (error_details) {
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error_details->context = parser.GetLastContext();
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error_details->line_number = parser.GetLastLineNumber();
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        error_details->error_code = error_code;
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
253