// export.h -- Export declarations in Go frontend.     -*- C++ -*-

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef GO_EXPORT_H
#define GO_EXPORT_H

#include "string-dump.h"

class Go_sha1_helper;
class Gogo;
class Named_object;
class Export_function_body;
class Import_init;
class Named_object;
class Bindings;
class Type;
class Package;
class Import_init_set;
class Backend;
class Temporary_statement;
class Unnamed_label;
struct Export_impl;

// Codes used for the builtin types.  These are all negative to make
// them easily distinct from the codes assigned by Export::write_type.
// Note that these codes may not be changed!  Changing them would
// break existing export data.

enum Builtin_code
{
  BUILTIN_INT8 = -1,
  BUILTIN_INT16 = -2,
  BUILTIN_INT32 = -3,
  BUILTIN_INT64 = -4,
  BUILTIN_UINT8 = -5,
  BUILTIN_UINT16 = -6,
  BUILTIN_UINT32 = -7,
  BUILTIN_UINT64 = -8,
  BUILTIN_FLOAT32 = -9,
  BUILTIN_FLOAT64 = -10,
  BUILTIN_INT = -11,
  BUILTIN_UINT = -12,
  BUILTIN_UINTPTR = -13,
  BUILTIN_BOOL = -15,
  BUILTIN_STRING = -16,
  BUILTIN_COMPLEX64 = -17,
  BUILTIN_COMPLEX128 = -18,
  BUILTIN_ERROR = -19,
  BUILTIN_BYTE = -20,
  BUILTIN_RUNE = -21,

  SMALLEST_BUILTIN_CODE = -21
};

// Export data version number. New export data is written with the
// "current" version, but there is support for reading files with
// older version export data (at least for now).

enum Export_data_version {
  EXPORT_FORMAT_UNKNOWN = 0,
  EXPORT_FORMAT_V1 = 1,
  EXPORT_FORMAT_V2 = 2,
  EXPORT_FORMAT_V3 = 3,
  EXPORT_FORMAT_CURRENT = EXPORT_FORMAT_V3
};

// This class manages exporting Go declarations.  It handles the main
// loop of exporting.  A pointer to this class is also passed to the
// various specific export implementations.

class Export : public String_dump
{
 public:
  // The Stream class is an interface used to output the exported
  // information.  The caller should instantiate a child of this
  // class.
  class Stream
  {
   public:
    Stream();
    virtual ~Stream();

    // Write a string. Implements the String_dump interface.
    void
    write_string(const std::string& s)
    { this->write_and_sum_bytes(s.data(), s.length()); }

    // Write a nul terminated string. Implements the String_dump interface.
    void
    write_c_string(const char* s)
    { this->write_and_sum_bytes(s, strlen(s)); }

    // Write some bytes.
    void
    write_bytes(const char* bytes, size_t length)
    { this->write_and_sum_bytes(bytes, length); }

    // Return the raw bytes of the checksum data.
    std::string
    checksum();

    // Write a checksum string to the stream.  This will be called at
    // the end of the other output.
    void
    write_checksum(const std::string&);

   protected:
    // This function is called with data to export.  This data must be
    // made available as a contiguous stream for the importer.
    virtual void
    do_write(const char* bytes, size_t length) = 0;

  private:
    void
    write_and_sum_bytes(const char*, size_t);

    // The checksum helper.
    Go_sha1_helper* sha1_helper_;
  };

  Export(Stream*);
  ~Export();

  // Size of export data magic string (which includes version number).
  static const int magic_len = 4;

  // Magic strings (current version and older versions).
  static const char cur_magic[magic_len];
  static const char v1_magic[magic_len];
  static const char v2_magic[magic_len];

  // The length of the checksum string.
  static const int checksum_len = 20;

  // Register the builtin types.
  void
  register_builtin_types(Gogo*);

  // Export the identifiers in BINDINGS which are marked for export.
  // The exporting is done via a series of calls to THIS->STREAM_.  If
  // is nothing to export, this->stream_->write will not be called.
  // PREFIX is the package prefix.  PKGPATH is the package path.
  // Only one of PREFIX and PKGPATH will be non-empty.
  // PACKAGES is all the packages we have seen.
  // IMPORTS is the explicitly imported packages.
  // IMPORT_INIT_FN is the name of the import initialization function
  // for this package; it will be empty if none is needed.
  // IMPORTED_INIT_FNS is the list of initialization functions for
  // imported packages.
  void
  export_globals(const std::string& package_name,
		 const std::string& prefix,
		 const std::string& pkgpath,
		 const std::map<std::string, Package*>& packages,
		 const std::map<std::string, Package*>& imports,
		 const std::string& import_init_fn,
		 const Import_init_set& imported_init_fns,
		 const Bindings* bindings);

  // Set the index of a type.
  bool
  set_type_index(Type*);

  // Write a string to the export stream.
  void
  write_string(const std::string& s)
  { this->stream_->write_string(s); }

  // Write a nul terminated string to the export stream.
  void
  write_c_string(const char* s)
  { this->stream_->write_c_string(s); }

  // Write some bytes to the export stream.
  void
  write_bytes(const char* bytes, size_t length)
  { this->stream_->write_bytes(bytes, length); }

  // Write a name to the export stream.  If NAME is empty, write "?".
  void
  write_name(const std::string& name);

  // Write out a type.  This handles references back to previous
  // definitions.
  void
  write_type(const Type*);

  // Write a type to an exported function body.
  void
  write_type_to(const Type*, Export_function_body*);

  // Write the escape note to the export stream.  If NOTE is NULL, write
  // nothing.
  void
  write_escape(std::string* note);

  // Write an integer value.
  void
  write_int(int);

  // Write an unsigned value.
  void
  write_unsigned(unsigned);

  // Return the index of a package.
  int
  package_index(const Package* p) const;

 private:
  Export(const Export&);
  Export& operator=(const Export&);

  // Prepare types for exporting.
  int
  prepare_types(const std::vector<Named_object*>* exports,
		Unordered_set(const Package*)* imports);

  // Write out all known packages.
  void
  write_packages(const std::map<std::string, Package*>& packages);

  typedef std::map<unsigned, std::set<unsigned> > Init_graph;

  static void
  add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink);

  static void
  populate_init_graph(Init_graph* init_graph,
                      const Import_init_set& imported_init_fns,
                      const std::map<std::string, unsigned>& init_idx);

  // Write out the imported packages.
  void
  write_imports(const std::map<std::string, Package*>& imports,
		const Unordered_set(const Package*)& type_imports);

  // Write out the imported initialization functions and init graph.
  void
  write_imported_init_fns(const std::string& package_name,
			  const std::string&, const Import_init_set&);

  // Write out all types.
  void
  write_types(int unexported_type_index);

  // Write out one type definition.
  void
  write_type_definition(const Type* type, int index);

  // Register one builtin type.
  void
  register_builtin_type(Gogo*, const char* name, Builtin_code);

  // Return the index of a type in the export data.
  int
  type_index(const Type*);

  // The stream to which we are writing data.
  Stream* stream_;
  // Index number of next type.
  int type_index_;
  // Packages we have written out.
  Unordered_map(const Package*, int) packages_;
  // Hidden implementation-specific state.
  Export_impl* impl_;
};

// An export streamer that puts the export stream in a named section.

class Stream_to_section : public Export::Stream
{
 public:
  Stream_to_section(Backend*);

 protected:
  void
  do_write(const char*, size_t);

 private:
  Backend* backend_;
};

// An export streamer that puts the export stream in a string.

class Stream_to_string : public Export::Stream
{
 public:
  Stream_to_string()
    : string_()
  {}

  const std::string&
  string() const
  { return this->string_; }

 protected:
  void
  do_write(const char* s, size_t len)
  { this->string_.append(s, len); }

 private:
  std::string string_;
};

// Class to manage exporting a function body.  This is passed around
// to Statements and Expressions.  It builds up the export data for
// the function.

class Export_function_body : public String_dump
{
 public:
  Export_function_body(Export* exp, int indent)
    : exp_(exp), body_(), type_context_(NULL), next_temporary_index_(0),
      temporary_indexes_(), next_label_index_(0), label_indexes_(),
      indent_(indent)
  { }

  // Write a character to the body.
  void
  write_char(char c)
  { this->body_.append(1, c); }

  // Write a NUL terminated string to the body.
  void
  write_c_string(const char* str)
  { this->body_.append(str); }

  // Write a string to the body.
  void
  write_string(const std::string& str)
  { this->body_.append(str); }

  // Write a type reference to the body.
  void
  write_type(const Type* type)
  { this->exp_->write_type_to(type, this); }

  // Return the current type context.
  Type*
  type_context() const
  { return this->type_context_; }

  // Set the current type context.
  void
  set_type_context(Type* type)
  { this->type_context_ = type; }

  // Append as many spaces as the current indentation level.
  void
  indent()
  {
    for (int i = this->indent_; i > 0; i--)
      this->write_char(' ');
  }

  // Increment the indentation level.
  void
  increment_indent()
  { ++this->indent_; }

  // Decrement the indentation level.
  void
  decrement_indent()
  { --this->indent_; }

  // Return the index of a package.
  int
  package_index(const Package* p) const
  { return this->exp_->package_index(p); }

  // Record a temporary statement and return its index.
  unsigned int
  record_temporary(const Temporary_statement*);

  // Return the index of a temporary statement.
  unsigned int
  temporary_index(const Temporary_statement*);

  // Return the index of an unnamed label.  If it doesn't already have
  // an index, give it one.
  unsigned int
  unnamed_label_index(const Unnamed_label*);

  // Return a reference to the completed body.
  const std::string&
  body() const
  { return this->body_; }

 private:
  // The overall export data.
  Export* exp_;
  // The body we are building.
  std::string body_;
  // Current type context.  Used to avoid duplicate type conversions.
  Type* type_context_;
  // Index to give to next temporary statement.
  unsigned int next_temporary_index_;
  // Map temporary statements to indexes.
  Unordered_map(const Temporary_statement*, unsigned int) temporary_indexes_;
  // Index to give to the next unnamed label.
  unsigned int next_label_index_;
  // Map unnamed labels to indexes.
  Unordered_map(const Unnamed_label*, unsigned int) label_indexes_;
  // Current indentation level: the number of spaces before each statement.
  int indent_;
};

#endif // !defined(GO_EXPORT_H)
