diff options
author | peter klausler <pklausler@nvidia.com> | 2020-02-04 16:55:45 -0800 |
---|---|---|
committer | peter klausler <pklausler@nvidia.com> | 2020-02-13 10:31:26 -0800 |
commit | 95696d563b927cb51f4a55976e7f64992e1c0acf (patch) | |
tree | 959b42e045042b29aeb94066d393c7ef739badc1 /flang/runtime/format.h | |
parent | dbea781d199babb68a71d08a0694522184b93e2d (diff) | |
download | llvm-95696d563b927cb51f4a55976e7f64992e1c0acf.tar.gz |
[flang] Progress on Fortran I/O runtime
Use internal units for internal I/O state
Replace use of virtual functions
reference_wrapper
Internal formatted output to array descriptor
Delete dead code
Begin list-directed internal output
Refactorings and renamings for clarity
List-directed external I/O (character)
COMPLEX list-directed output
Control list items
First cut at unformatted I/O
More OPEN statement work; rename class to ExternalFileUnit
Complete OPEN (exc. for POSITION=), add CLOSE()
OPEN(POSITION=)
Flush buffers on crash and for terminal output; clean up
Documentation
Fix backquote in documentation
Fix typo in comment
Begin implementation of input
Refactor binary floating-point properties to a new header, simplify numeric output editing
Dodge spurious GCC 7.2 build warning
Address review comments
Original-commit: flang-compiler/f18@9c4bba11cf2329575ea9ee446f69e9caa797135c
Reviewed-on: https://github.com/flang-compiler/f18/pull/982
Diffstat (limited to 'flang/runtime/format.h')
-rw-r--r-- | flang/runtime/format.h | 72 |
1 files changed, 39 insertions, 33 deletions
diff --git a/flang/runtime/format.h b/flang/runtime/format.h index c954c7f3872f..c072b3b9805d 100644 --- a/flang/runtime/format.h +++ b/flang/runtime/format.h @@ -12,8 +12,10 @@ #define FORTRAN_RUNTIME_FORMAT_H_ #include "environment.h" +#include "io-error.h" #include "terminator.h" #include "flang/common/Fortran.h" +#include "flang/decimal/decimal.h" #include <cinttypes> #include <optional> @@ -27,7 +29,7 @@ enum EditingFlags { struct MutableModes { std::uint8_t editingFlags{0}; // BN, DP, SS - common::RoundingMode roundingMode{ + enum decimal::FortranRounding round{ executionEnvironment .defaultOutputRoundingMode}; // RP/ROUND='PROCESSOR_DEFAULT' bool pad{false}; // PAD= mode on READ @@ -38,6 +40,16 @@ struct MutableModes { // A single edit descriptor extracted from a FORMAT struct DataEdit { char descriptor; // capitalized: one of A, I, B, O, Z, F, E(N/S/X), D, G + + // Special internal data edit descriptors to distinguish list-directed I/O + static constexpr char ListDirected{'g'}; // non-COMPLEX list-directed + static constexpr char ListDirectedRealPart{'r'}; // emit "(r," or "(r;" + static constexpr char ListDirectedImaginaryPart{'z'}; // emit "z)" + constexpr bool IsListDirected() const { + return descriptor == ListDirected || descriptor == ListDirectedRealPart || + descriptor == ListDirectedImaginaryPart; + } + char variation{'\0'}; // N, S, or X for EN, ES, EX std::optional<int> width; // the 'w' field; optional for A std::optional<int> digits; // the 'm' or 'd' field @@ -46,37 +58,35 @@ struct DataEdit { int repeat{1}; }; -class FormatContext : virtual public Terminator { -public: - FormatContext() {} - virtual ~FormatContext() {} - explicit FormatContext(const MutableModes &modes) : mutableModes_{modes} {} - virtual bool Emit(const char *, std::size_t) = 0; - virtual bool Emit(const char16_t *, std::size_t) = 0; - virtual bool Emit(const char32_t *, std::size_t) = 0; - virtual bool HandleSlash(int = 1) = 0; - virtual bool HandleRelativePosition(std::int64_t) = 0; - virtual bool HandleAbsolutePosition(std::int64_t) = 0; - MutableModes &mutableModes() { return mutableModes_; } - -private: - MutableModes mutableModes_; +// FormatControl<A> requires that A have these member functions; +// these default implementations just crash if called. +struct DefaultFormatControlCallbacks : public IoErrorHandler { + using IoErrorHandler::IoErrorHandler; + DataEdit GetNextDataEdit(int = 1); + bool Emit(const char *, std::size_t); + bool Emit(const char16_t *, std::size_t); + bool Emit(const char32_t *, std::size_t); + bool AdvanceRecord(int = 1); + bool HandleAbsolutePosition(std::int64_t); + bool HandleRelativePosition(std::int64_t); }; // Generates a sequence of DataEdits from a FORMAT statement or // default-CHARACTER string. Driven by I/O item list processing. // Errors are fatal. See clause 13.4 in Fortran 2018 for background. -template<typename CHAR = char> class FormatControl { +template<typename CONTEXT> class FormatControl { public: + using Context = CONTEXT; + using CharType = typename Context::CharType; + FormatControl() {} - // TODO: make 'format' a reference here and below - FormatControl(Terminator &, const CHAR *format, std::size_t formatLength, - int maxHeight = maxMaxHeight); + FormatControl(const Terminator &, const CharType *format, + std::size_t formatLength, int maxHeight = maxMaxHeight); // Determines the max parenthesis nesting level by scanning and validating // the FORMAT string. static int GetMaxParenthesisNesting( - Terminator &, const CHAR *format, std::size_t formatLength); + const Terminator &, const CharType *format, std::size_t formatLength); // For attempting to allocate in a user-supplied stack area static std::size_t GetNeededSize(int maxHeight) { @@ -86,10 +96,10 @@ public: // Extracts the next data edit descriptor, handling control edit descriptors // along the way. - void GetNext(FormatContext &, DataEdit &, int maxRepeat = 1); + DataEdit GetNextDataEdit(Context &, int maxRepeat = 1); // Emit any remaining character literals after the last data item. - void FinishOutput(FormatContext &); + void FinishOutput(Context &); private: static constexpr std::uint8_t maxMaxHeight{100}; @@ -105,27 +115,27 @@ private: ++offset_; } } - CHAR PeekNext() { + CharType PeekNext() { SkipBlanks(); return offset_ < formatLength_ ? format_[offset_] : '\0'; } - CHAR GetNextChar(Terminator &terminator) { + CharType GetNextChar(const Terminator &terminator) { SkipBlanks(); if (offset_ >= formatLength_) { terminator.Crash("FORMAT missing at least one ')'"); } return format_[offset_++]; } - int GetIntField(Terminator &, CHAR firstCh = '\0'); + int GetIntField(const Terminator &, CharType firstCh = '\0'); // Advances through the FORMAT until the next data edit // descriptor has been found; handles control edit descriptors // along the way. Returns the repeat count that appeared // before the descriptor (defaulting to 1) and leaves offset_ // pointing to the data edit. - int CueUpNextDataEdit(FormatContext &, bool stop = false); + int CueUpNextDataEdit(Context &, bool stop = false); - static constexpr CHAR Capitalize(CHAR ch) { + static constexpr CharType Capitalize(CharType ch) { return ch >= 'a' && ch <= 'z' ? ch + 'A' - 'a' : ch; } @@ -134,16 +144,12 @@ private: // user program for internal I/O. const std::uint8_t maxHeight_{maxMaxHeight}; std::uint8_t height_{0}; - const CHAR *format_{nullptr}; + const CharType *format_{nullptr}; int formatLength_{0}; int offset_{0}; // next item is at format_[offset_] // must be last, may be incomplete Iteration stack_[maxMaxHeight]; }; - -extern template class FormatControl<char>; -extern template class FormatControl<char16_t>; -extern template class FormatControl<char32_t>; } #endif // FORTRAN_RUNTIME_FORMAT_H_ |