[flang] Begin work on character provenances.

Original-commit: flang-compiler/f18@ea3c05af5a
Reviewed-on: https://github.com/flang-compiler/f18/pull/9
Tree-same-pre-rewrite: false
This commit is contained in:
peter klausler 2018-02-07 13:18:36 -08:00 committed by GitHub
parent fb7dc91efd
commit ea69370e52
3 changed files with 146 additions and 2 deletions

View File

@ -0,0 +1,95 @@
#ifndef FORTRAN_PROVENANCE_H_
#define FORTRAN_PROVENANCE_H_
#include "source.h"
#include <string>
#include <variant>
namespace Fortran {
class SourceContexts;
using Provenance = size_t;
struct ProvenanceRange {
Provenance begin;
size_t bytes;
};
class Sources {
public:
Sources() {}
Sources(Sources &&) = default;
Sources &operator(Sources &&) = default;
size_t size() const { return bytes_; }
char &operator[size_t at] const;
private:
struct Context {
struct Inclusion {
const SourceFile &source;
};
struct MacroUse {
ProvenanceRange definition;
};
int myIndex; // *contexts[myIndex] == this;
ProvenanceRange replaces;
std::variant<SourceFile, Inclusion, MacroUse> v;
};
std::vector<std::unique_ptr<Context>> contexts_;
size_t bytes_;
};
class ProvenancedChar {
public:
using type = char;
char character() const { return static_cast<char>(packed_); }
Provenance provenance() const { return packed_ >> 8; }
private:
size_t packed_;
};
class ProvenancedString {
private:
class iterator {
public:
iterator(const Sources &sources, Provenance at)
: sources_{&sources}, at_{at} {}
iterator(const iterator &that)
: sources_{that.sources_}, at_{that.at_} {}
iterator &operator(const iterator &that) {
sources_ = that.sources_;
at_ = that.at_;
return *this;
}
const char &operator*() const;
iterator &operator++() {
++at_;
return *this;
}
iterator &operator++(int) {
iterator result{*this};
++at_;
return result;
}
bool operator<(const iterator &that) { return at_ < that.at_; }
bool operator<=(const iterator &that) { return at_ <= that.at_; }
bool operator==(const iterator &that) { return at_ == that.at_; }
bool operator!=(const iterator &that) { return at_ != that.at_; }
private:
const Sources *sources_;
size_t at_;
};
iterator begin(const Sources &sources) const {
return iterator(sources, start_);
}
iterator end(const Sources &sources) const {
return iterator(sources, start_ + bytes_);
}
public:
size_t size() const { return bytes_; }
private:
Provenance start_;
size_t bytes_;
};
} // namespace Fortran
#endif // FORTRAN_PROVENANCE_H_

View File

@ -18,6 +18,24 @@ namespace parser {
SourceFile::~SourceFile() { Close(); }
static std::vector<size_t> FindLineStarts(const char *source, size_t bytes) {
if (bytes == 0) {
return {};
}
CHECK(source[bytes - 1] == '\n' && "missing ultimate newline");
std::vector<size_t> result;
size_t at{0};
do {
result.push_back(at);
const void *vp{static_cast<const void *>(&source[at])};
const void *vnl{std::memchr(vp, '\n', bytes - at)};
const char *nl{static_cast<const char *>(vnl)};
at = nl + 1 - source;
} while (at < bytes);
result.shrink_to_fit();
return result;
}
bool SourceFile::Open(std::string path, std::stringstream *error) {
Close();
path_ = path;
@ -51,12 +69,13 @@ bool SourceFile::Open(std::string path, std::stringstream *error) {
if (S_ISREG(statbuf.st_mode)) {
bytes_ = static_cast<size_t>(statbuf.st_size);
if (bytes_ > 0) {
auto vp = mmap(0, bytes_, PROT_READ, MAP_SHARED, fileDescriptor_, 0);
void *vp = mmap(0, bytes_, PROT_READ, MAP_SHARED, fileDescriptor_, 0);
if (vp != MAP_FAILED) {
content_ = reinterpret_cast<const char *>(vp);
content_ = static_cast<const char *>(const_cast<const void *>(vp));
if (content_[bytes_ - 1] == '\n' &&
std::memchr(vp, '\r', bytes_) == nullptr) {
isMemoryMapped_ = true;
lineStart_ = FindLineStarts(content_, bytes_);
return true;
}
// The file needs normalizing.
@ -105,6 +124,7 @@ bool SourceFile::Open(std::string path, std::stringstream *error) {
*to++ = '\n'; // supply a missing terminal newline
}
bytes_ = to - contig;
lineStart_ = FindLineStarts(content_, bytes_);
return true;
}
@ -123,5 +143,27 @@ void SourceFile::Close() {
}
path_.clear();
}
Position SourceFile::FindOffsetPosition(size_t at) const {
CHECK(at < bytes_);
size_t lo{0}, hi{lineStart_.size()};
while (lo < hi) {
size_t mid{(lo + hi) >> 1};
if (lineStart_[mid] > at) {
hi = mid;
} else {
lo = mid;
}
}
return {static_cast<int>(lo + 1), static_cast<int>(at - lineStart_[lo] + 1)};
}
size_t SourceFile::FindPositionOffset(int lineNumber, int column) const {
return lineStart_.at(lineNumber - 1) + column - 1;
}
size_t SourceFile::FindPositionOffset(Position pos) const {
return FindPositionOffset(pos.lineNumber(), pos.column());
}
} // namespace parser
} // namespace Fortran

View File

@ -5,8 +5,10 @@
// - Line ending markers are converted to single newline characters
// - A newline character is added to the last line of the file if one is needed
#include "position.h"
#include <sstream>
#include <string>
#include <vector>
namespace Fortran {
namespace parser {
@ -20,6 +22,10 @@ public:
std::string path() const { return path_; }
const char *content() const { return content_; }
size_t bytes() const { return bytes_; }
size_t lines() const { return lineStart_.size(); }
Position FindOffsetPosition(size_t) const;
size_t FindPositionOffset(int lineNumber, int column) const;
size_t FindPositionOffset(Position) const;
private:
std::string path_;
@ -27,6 +33,7 @@ private:
bool isMemoryMapped_{false};
const char *content_{nullptr};
size_t bytes_{0};
std::vector<size_t> lineStart_;
};
} // namespace parser
} // namespace Fortran