Skip to content

Commit

Permalink
Update error reporting to show expression location
Browse files Browse the repository at this point in the history
Signed-off-by: yamacir-kit <[email protected]>
  • Loading branch information
yamacir-kit committed Jul 14, 2024
1 parent 2dbf851 commit 00714e2
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 51 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Procedures for each standard are provided by the following R7RS-style libraries:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cd build
make package
sudo apt install build/meevax_0.5.208_amd64.deb
sudo apt install build/meevax_0.5.209_amd64.deb
```

or
Expand Down Expand Up @@ -122,9 +122,9 @@ sudo rm -rf /usr/local/share/meevax

| Target Name | Description
|-------------|-------------
| `all` | Build shared-library `libmeevax.0.5.208.so` and executable `meevax`
| `all` | Build shared-library `libmeevax.0.5.209.so` and executable `meevax`
| `test` | Test executable `meevax`
| `package` | Generate debian package `meevax_0.5.208_amd64.deb`
| `package` | Generate debian package `meevax_0.5.209_amd64.deb`
| `install` | Copy files into `/usr/local` directly

## Usage
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.5.208
0.5.209
10 changes: 1 addition & 9 deletions include/meevax/kernel/boot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,10 @@ inline namespace kernel
{
for (auto&& source : sources)
{
auto input_port = input_string_port(source);

for (let const& x : input_port)
for (let const& x : input_string_port(source))
{
interaction_environment().as<environment>().evaluate(x);
}

auto taken = static_cast<std::string>(input_port.taken);

taken.pop_back();

assert(taken == source);
}
}
} // namespace kernel
Expand Down
6 changes: 3 additions & 3 deletions include/meevax/kernel/input_file_port.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ inline namespace kernel
explicit input_file_port(T&& x, Ts&&... xs)
: name { std::forward<decltype(x)>(x) }
, ifstream { name, std::forward<decltype(xs)>(xs)... }
{}
{
enable_source_cons(name);
}

auto close() -> void override;

Expand All @@ -44,8 +46,6 @@ inline namespace kernel
auto istream() -> std::istream & override;

auto istream() const -> std::istream const& override;

auto path() const -> std::filesystem::path const* override;
};

auto operator <<(std::ostream &, input_file_port const&) -> std::ostream &;
Expand Down
5 changes: 0 additions & 5 deletions include/meevax/kernel/port.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ inline namespace kernel
virtual auto close() -> void = 0;

virtual auto is_open() const -> bool = 0;

virtual auto path() const -> std::filesystem::path const*
{
return nullptr;
};
};
} // namespace kernel
} // namespace meevax
Expand Down
2 changes: 2 additions & 0 deletions include/meevax/kernel/standard_input_port.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ inline namespace kernel
{
struct standard_input_port : public textual_input_port
{
standard_input_port();

auto close() -> void override;

auto is_open() const -> bool override;
Expand Down
2 changes: 2 additions & 0 deletions include/meevax/kernel/string.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ inline namespace kernel
using std::vector<character>::emplace_back;
using std::vector<character>::end;
using std::vector<character>::insert;
using std::vector<character>::operator [];
using std::vector<character>::pop_back;
using std::vector<character>::push_back;
using std::vector<character>::rbegin;
using std::vector<character>::rend;
using std::vector<character>::reserve;
using std::vector<character>::size;
using std::vector<character>::size_type;
using std::vector<character>::vector;

explicit string(std::string const&);
Expand Down
55 changes: 53 additions & 2 deletions include/meevax/kernel/textual_input_port.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef INCLUDED_MEEVAX_KERNEL_TEXTUAL_INPUT_PORT_HPP
#define INCLUDED_MEEVAX_KERNEL_TEXTUAL_INPUT_PORT_HPP

#include <forward_list>
#include <istream>

#include <meevax/kernel/eof.hpp>
Expand Down Expand Up @@ -63,16 +64,66 @@ inline namespace kernel
auto operator ++(int) -> iterator;
};

struct source
{
std::filesystem::path path;

string code;

template <typename... Ts>
explicit source(Ts&&... xs)
: path { std::forward<decltype(xs)>(xs)... }
{
assert(not path.empty());
}
};

struct context
{
source const* file;

string::size_type begin, end;

explicit context(source const* file, string::size_type begin)
: file { file }
, begin { begin }
{}

friend auto operator <<(std::ostream & output, context const& datum) -> std::ostream &
{
auto row = 1, column = 0;

for (std::size_t i = 0; i < datum.begin; ++i)
{
if (datum.file->code[i] == '\n')
{
++row;
column = 0;
}
else
{
++column;
}
}

return output << datum.file->path.c_str() << ":" << row << ":" << column;
}
};

static inline std::unordered_map<textual_input_port const*, source> sources;

static inline std::unordered_map<pair const*, context> contexts;

std::unordered_map<std::string, object> datum_labels;

bool case_sensitive = true;

string taken;

auto at_end_of_file() const -> bool;

auto begin() -> iterator;

auto enable_source_cons(std::filesystem::path const&) -> void;

auto end() -> iterator;

auto get() -> object; // Returns character or eof (for Scheme procedure read-char)
Expand Down
16 changes: 13 additions & 3 deletions src/kernel/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <meevax/kernel/error.hpp>
#include <meevax/kernel/procedure.hpp>
#include <meevax/kernel/string.hpp>
#include <meevax/kernel/textual_input_port.hpp>

namespace meevax
{
Expand All @@ -39,11 +40,20 @@ inline namespace kernel

auto error::report(std::ostream & output) const -> std::ostream &
{
output << red("; error! ", what()) << std::endl;
output << red("; error! ", what()) << "\n; ";

for (auto iter = details.rbegin(); iter != details.rend(); ++iter)
for (auto detail = details.rbegin(); detail != details.rend(); ++detail)
{
output << faint("; at expression ", lexical_cast<std::string>(iter->expression)) << std::endl;
if (auto context = textual_input_port::contexts.find(detail->expression.get()); context != textual_input_port::contexts.end())
{
output << context->second;
}
else
{
output << "{annonymous-input-source}";
}

output << ": " << lexical_cast<std::string>(detail->expression) << std::endl;
}

return output;
Expand Down
5 changes: 0 additions & 5 deletions src/kernel/input_file_port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ inline namespace kernel
return ifstream;
}

auto input_file_port::path() const -> std::filesystem::path const*
{
return &name;
}

auto operator <<(std::ostream & output, input_file_port const& datum) -> std::ostream &
{
return output << magenta("#,(") << blue("open-input-file ") << string(datum.name) << magenta(")");
Expand Down
5 changes: 5 additions & 0 deletions src/kernel/standard_input_port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ namespace meevax
{
inline namespace kernel
{
standard_input_port::standard_input_port()
{
enable_source_cons("/dev/stdin");
}

auto standard_input_port::is_open() const -> bool
{
return true;
Expand Down
73 changes: 53 additions & 20 deletions src/kernel/textual_input_port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ inline namespace kernel
return iterator(*this);
}

auto textual_input_port::enable_source_cons(std::filesystem::path const& path) -> void
{
sources.emplace(this, path);
}

auto textual_input_port::end() -> iterator
{
return iterator();
Expand Down Expand Up @@ -187,7 +192,10 @@ inline namespace kernel
istream().putback(*iter);
}

taken.pop_back();
if (auto iter = sources.find(this); iter != sources.end())
{
iter->second.code.pop_back();
}

return c;
}
Expand Down Expand Up @@ -549,14 +557,30 @@ inline namespace kernel
case '(': // 0x28
try
{
if (let const& x = read(); x.is<eof>())
auto position = [this]()
{
return x;
}
else
if (auto source = sources.find(this); source != sources.end())
{
return source->second.code.size();
}
else
{
return std::numeric_limits<string::size_type>::max();
}
}();

let const& x = read();

let const& pare = cons(x, read(c1));

if (auto source = sources.find(this); source != sources.end()) // The iterator may be invalidated by calling read, so the iterator must be retrieved again.
{
return cons(x, read(c1));
contexts.emplace(std::piecewise_construct,
std::make_tuple(pare.get()),
std::make_tuple(&source->second, position));
}

return pare;
}
catch (std::integral_constant<char, ')'> const&)
{
Expand Down Expand Up @@ -628,31 +652,40 @@ inline namespace kernel
*/
auto & source = istream();

auto make_character = [this](auto&&... xs)
{
if (auto iter = sources.find(this); iter != sources.end())
{
iter->second.code.emplace_back(std::forward<decltype(xs)>(xs)...);
return iter->second.code.back();
}
else
{
return character(std::forward<decltype(xs)>(xs)...);
}
};

if (auto const c = source.peek(); character::is_eof(c) or character::is_ascii(c))
{
taken.emplace_back(source.get());
return taken.back();
return make_character(source.get());
}
else if (0xC2 <= c and c <= 0xDF) // 11 bit
{
taken.emplace_back((source.get() & 0b0001'1111) << 6 |
(source.get() & 0b0011'1111));
return taken.back();
return make_character((source.get() & 0b0001'1111) << 6 |
(source.get() & 0b0011'1111));
}
else if (0xE0 <= c and c <= 0xEF) // 16 bit
{
taken.emplace_back((source.get() & 0b0000'1111) << 12 |
(source.get() & 0b0011'1111) << 6 |
(source.get() & 0b0011'1111));
return taken.back();
return make_character((source.get() & 0b0000'1111) << 12 |
(source.get() & 0b0011'1111) << 6 |
(source.get() & 0b0011'1111));
}
else if (0xF0 <= c and c <= 0xF4) // 21 bit
{
taken.emplace_back((source.get() & 0b0000'0111) << 18 |
(source.get() & 0b0011'1111) << 12 |
(source.get() & 0b0011'1111) << 6 |
(source.get() & 0b0011'1111));
return taken.back();
return make_character((source.get() & 0b0000'0111) << 18 |
(source.get() & 0b0011'1111) << 12 |
(source.get() & 0b0011'1111) << 6 |
(source.get() & 0b0011'1111));
}
else
{
Expand Down

0 comments on commit 00714e2

Please sign in to comment.