Skip to content

Commit

Permalink
Models own their error buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnDTill committed Jul 31, 2023
1 parent c73cdc6 commit bc79bce
Show file tree
Hide file tree
Showing 13 changed files with 124 additions and 80 deletions.
2 changes: 1 addition & 1 deletion app/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ void MainWindow::run(){
if(editor->isRunning()) return;

editor->runThread();
if(editor->getModel()->errors.empty()){
if(Program::instance()->noErrors()){
interpreter_poll_timer.start(INTERPETER_POLL_PERIOD);

editor_had_focus = false;
Expand Down
5 changes: 5 additions & 0 deletions src/forscape_dynamic_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class Settings {
return static_cast<WarningLevel>(flags[setting]);
}

WarningLevel warningLevel(SettingId setting) const noexcept {
assert(setting < NUM_CODE_SETTINGS);
return static_cast<WarningLevel>(flags[setting]);
}

template<SettingId setting> void setWarningLevel(WarningLevel warning_level) alloc_except {
static_assert(setting < NUM_CODE_SETTINGS);
assert(warning_level < NUM_WARNING_LEVELS);
Expand Down
124 changes: 76 additions & 48 deletions src/forscape_error.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#include "forscape_error.h"

#include <typeset_line.h>
#include "forscape_program.h"
#include "typeset_line.h"
#include <typeset_markerlink.h>
#include <typeset_model.h>
#include <typeset_text.h>
#include "typeset_model.h"
#include "typeset_text.h"

namespace Forscape {

Expand All @@ -12,14 +13,24 @@ namespace Code {
#ifndef FORSCAPE_TYPESET_HEADLESS
void Error::writeTo(Typeset::Text* t, Typeset::View* caller) const {
Typeset::Line* l = selection.getStartLine();
Typeset::Model* model = t->getModel();
t->tags.push_back( SemanticTag(0, SEM_ERROR) );
t->setString("ERROR");
model->appendLine();
t = model->lastText();
t->tags.push_back( SemanticTag(0, SEM_ERROR) );
model->appendSerialToOutput(selection.getModel()->path.u8string());
model->appendLine();
t = model->lastText();

if(caller){
t->getParent()->appendConstruct(new Typeset::MarkerLink(l, caller, selection.getModel()));
t = t->nextTextAsserted();
t->setString(" - ");
t->getModel()->appendSerialToOutput(std::string(message()));
model->appendSerialToOutput(std::string(consoleMessage()));
}else{
t->setString("Line " + line() + " - ");
t->getModel()->appendSerialToOutput(std::string(message()));
model->appendSerialToOutput(std::string(consoleMessage()));
}
t->tags.push_back( SemanticTag(0, SEM_ERROR) );
}
Expand All @@ -37,8 +48,6 @@ void Error::writeErrors(const std::vector<Error>& errors, Typeset::Model* m, Typ
err.writeTo(m->lastText(), caller);
m->appendLine();
}

m->appendSerialToOutput(*errors.front().error_out);
}

Typeset::Model* Error::writeErrors(const std::vector<Error>& errors, Typeset::View* caller){
Expand All @@ -51,19 +60,24 @@ Typeset::Model* Error::writeErrors(const std::vector<Error>& errors, Typeset::Vi
#endif

Error::Error(const Typeset::Selection& selection, ErrorCode code, size_t start, size_t len, const std::string* const error_out) noexcept
: selection(selection), code(code), start(start), len(len), error_out(error_out) {}
: selection(selection), code(code), tooltip_start(start), tooltip_len(len), buffer(error_out) {}

std::string_view Error::message() const noexcept {
assert(error_out != nullptr);
return std::string_view(error_out->data()+start, len);
std::string_view Error::tooltipMessage() const noexcept {
assert(buffer != nullptr);
return std::string_view(buffer->data()+tooltip_start, tooltip_len);
}

std::string_view Error::consoleMessage() const noexcept {
assert(buffer != nullptr);
return std::string_view(buffer->data()+console_start, console_len);
}

std::string Error::line() const {
return std::to_string(selection.getStartLine()->id+1);
}

void ErrorStream::reset() noexcept {
error_out.clear();
error_warning_buffer.clear();
errors.clear();
warnings.clear();
}
Expand All @@ -74,43 +88,53 @@ bool ErrorStream::noErrors() const noexcept {

void ErrorStream::fail(const Typeset::Selection& selection, ErrorCode code) alloc_except {
Typeset::Model* model = selection.getModel();
writeLocation(ERROR, selection, model);

const size_t start = error_out.size();
error_out += getMessage(code);
errors.push_back(Error(selection, code, start, error_out.size()-start, &error_out));
model->errors.push_back(errors.back());
const size_t start = active_buffer->size();
*active_buffer += getMessage(code);

Error error(selection, code, start, active_buffer->size()-start, active_buffer);

//DO THIS: quotes must show up
if(shouldQuote(code)){
error_out += ": ";
error_out += selection.str();
*active_buffer += ": ";
*active_buffer += selection.str();
}

error_out += '\n';
error.console_start = start;
error.console_len = active_buffer->size()-start;

errors.push_back(error);
model->errors.push_back(error);
}

void ErrorStream::fail(const Typeset::Selection& selection, const std::string& str, ErrorCode code) alloc_except {
Typeset::Model* model = selection.getModel();
writeLocation(ERROR, selection, model);

const size_t start = error_out.size();
error_out += str;
error_out += '\n';
errors.push_back(Error(selection, code, start, str.length(), &error_out));
model->errors.push_back(errors.back());
const size_t start = active_buffer->size();
*active_buffer += str;
*active_buffer += '\n';
Error error(selection, code, start, str.length(), active_buffer);
error.console_start = start;
error.console_len = str.length();
errors.push_back(error);
model->errors.push_back(error);
}

void Forscape::Code::ErrorStream::warn(SettingId setting, const Typeset::Selection& selection, ErrorCode code) noexcept {
warn(Program::instance()->settings.warningLevel(setting), selection, code);
}

void ErrorStream::warn(WarningLevel warning_level, const Typeset::Selection& selection, ErrorCode code) alloc_except {
assert(warning_level < NUM_WARNING_LEVELS);
if(warning_level == NO_WARNING) return;

Typeset::Model* model = selection.getModel();
writeLocation(warning_level, selection, model);

const size_t start = error_out.size();
error_out += getMessage(code);
const size_t start = active_buffer->size();
*active_buffer += getMessage(code);

const Error error(selection, code, start, error_out.size()-start, &error_out);
Error error(selection, code, start, active_buffer->size()-start, active_buffer);
error.console_start = start;
error.console_len = error.tooltip_len;

switch (warning_level) {
case ERROR: errors.push_back(error); model->errors.push_back(error); break;
Expand All @@ -119,40 +143,44 @@ void ErrorStream::warn(WarningLevel warning_level, const Typeset::Selection& sel
}

if(shouldQuote(code)){
error_out += ": ";
error_out += selection.str();
*active_buffer += ": ";
*active_buffer += selection.str();
}
}

error_out += '\n';
void ErrorStream::warn(SettingId setting, const Typeset::Selection& selection, const std::string& str, ErrorCode code) noexcept {
warn(Program::instance()->settings.warningLevel(setting), selection, str, code);
}

void ErrorStream::warn(WarningLevel warning_level, const Typeset::Selection& selection, const std::string& str, ErrorCode code) alloc_except {
if(warning_level == NO_WARNING) return;

Typeset::Model* model = selection.getModel();
writeLocation(warning_level, selection, model);

const size_t start = error_out.size();
error_out += str;
error_out += '\n';
const size_t start = active_buffer->size();
*active_buffer += str;

Error error(selection, code, start, str.size(), active_buffer);
error.console_start = start;
error.console_len = str.size();

const Error error(selection, code, start, str.size(), &error_out);
switch (warning_level) {
case ERROR: errors.push_back(error); model->errors.push_back(error); break;
case WARN: warnings.push_back(error); model->warnings.push_back(error); break;
default: break;
}
}

void ErrorStream::writeLocation(WarningLevel level, const Typeset::Selection& selection, const Typeset::Model* const model) alloc_except {
assert(model == selection.getModel());
error_out += warning_labels[level];
error_out += '\n';
error_out += model->path.u8string();
error_out += ": Line ";
error_out += selection.getStartLineAsString();
error_out += '\n';
//DO THIS: no link here, markerlink design is bad
void ErrorStream::setBuffer(std::string* buffer) noexcept {
active_buffer = buffer;
}

void Forscape::Code::ErrorStream::setProgramBuffer() noexcept {
active_buffer = &error_warning_buffer;
}

const std::vector<Error>& ErrorStream::getErrors() const noexcept {
return errors;
}

}
Expand Down
22 changes: 14 additions & 8 deletions src/forscape_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ struct Error {
Typeset::Selection selection;
ErrorCode code;
size_t flag;
size_t start;
size_t len;
const std::string* const error_out = nullptr;
size_t tooltip_start; //Index of buffer for tooltip
size_t tooltip_len; //Length of tooltip
size_t console_start; //Index of start for console
size_t console_len; //Length of console message
const std::string* const buffer = nullptr;

Error() noexcept = default;
Error(const Typeset::Selection& selection, ErrorCode code, size_t start, size_t len, const std::string* const error_out) noexcept;
Expand All @@ -30,13 +32,15 @@ struct Error {
static void writeErrors(const std::vector<Error>& errors, Typeset::Model* m, Typeset::View* caller);
static Typeset::Model* writeErrors(const std::vector<Error>& errors, Typeset::View* caller);
#endif
std::string_view message() const noexcept;
std::string_view tooltipMessage() const noexcept;
std::string_view consoleMessage() const noexcept;
std::string line() const;
};

class ErrorStream {
private:
std::string error_out;
std::string error_warning_buffer;
std::string* active_buffer = &error_warning_buffer;
std::vector<Error> errors;
std::vector<Error> warnings;

Expand All @@ -45,11 +49,13 @@ class ErrorStream {
bool noErrors() const noexcept;
void fail(const Typeset::Selection& selection, ErrorCode code) alloc_except;
void fail(const Typeset::Selection& selection, const std::string& str, ErrorCode code = ErrorCode::VALUE_NOT_DETERMINED) alloc_except;
void warn(SettingId setting, const Typeset::Selection& selection, ErrorCode code) alloc_except;
void warn(WarningLevel warning_level, const Typeset::Selection& selection, ErrorCode code) alloc_except;
void warn(SettingId setting, const Typeset::Selection& selection, const std::string& str, ErrorCode code = ErrorCode::VALUE_NOT_DETERMINED) alloc_except;
void warn(WarningLevel warning_level, const Typeset::Selection& selection, const std::string& str, ErrorCode code = ErrorCode::VALUE_NOT_DETERMINED) alloc_except;

private:
void writeLocation(WarningLevel level, const Typeset::Selection& selection, const Typeset::Model* const model) alloc_except;
void setBuffer(std::string* buffer) noexcept;
void setProgramBuffer() noexcept;
const std::vector<Error>& getErrors() const noexcept;
};

}
Expand Down
10 changes: 5 additions & 5 deletions src/forscape_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -863,8 +863,8 @@ ParseNode Parser::implicitMult() alloc_except {
ParseNode pn = collectImplicitMult(n);
return parse_tree.getNumArgs(pn) != 1 ? pn : parse_tree.child(pn);
}
default:
return n;
case INTEGER: return error(TRAILING_CONSTANT);
default: return n;
}
}

Expand Down Expand Up @@ -1500,7 +1500,7 @@ ParseNode Parser::identifierFollowOn(ParseNode id) noexcept{
}
index = index_backup;

//DO THIS: you have to address this heinuous hack
//EVENTUALLY: you have to address this heinuous hack
model->errors.clear();
error_node = NONE;
}
Expand Down Expand Up @@ -1618,7 +1618,7 @@ ParseNode Parser::fractionDeriv(const Typeset::Selection& c, Op type, ForscapeTo
advance();
if(match(ARGCLOSE)){
consume(tt);
if(error_node != NONE) return error_node; //DO THIS: the parser error strategy is terrible
if(error_node != NONE) return error_node; //EVENTUALLY: the parser error strategy is terrible
ParseNode id = isolatedIdentifier();
if(error_node != NONE) return error_node;
consume(ARGCLOSE);
Expand Down Expand Up @@ -2146,7 +2146,7 @@ const Typeset::Marker& Parser::rMarkPrev() const noexcept{

bool Parser::noErrors() const noexcept{
assert((error_node == NONE) == (model->errors.empty()));
return error_node == NONE; //DO THIS: a bit odd here
return error_node == NONE;
}

void Parser::recover() noexcept{
Expand Down
1 change: 0 additions & 1 deletion src/forscape_program.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ class Program {
FORSCAPE_UNORDERED_MAP<std::filesystem::path, Typeset::Model*> source_files; //May contain multiple entries per model
Typeset::Model* program_entry_point = nullptr;

//DO THIS (ERRORS): define differences between model errors/warnings and program errors/warnings
//DESIGN QUAGMIRE (AST): define difference between model parse_tree and program parse_tree

private:
Expand Down
8 changes: 2 additions & 6 deletions src/forscape_static_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,7 @@ ParseNode StaticPass::resolveStmt(ParseNode pn) noexcept{
ParseNode expr = resolveExprTop(parse_tree.child(pn));
parse_tree.setArg<0>(pn, expr);
if(parse_tree.getOp(expr) != OP_CALL || !isAbstractFunctionGroup(parse_tree.getType(parse_tree.arg<0>(expr)))){
error_stream.warn(
settings().warningLevel<WARN_UNUSED_VARIABLE>(), //DO THIS: rather specify the setting, not fetch warning level
parse_tree.getSelection(expr),
UNUSED_EXPRESSION);
error_stream.warn(WARN_UNUSED_VARIABLE, parse_tree.getSelection(expr), UNUSED_EXPRESSION);
parse_tree.setOp(pn, OP_DO_NOTHING);
}

Expand Down Expand Up @@ -1751,8 +1748,7 @@ ParseNode StaticPass::resolvePower(ParseNode pn){
//return ast.setComplement(base);

case OP_MAYBE_TRANSPOSE:
error_stream.warn(
settings().warningLevel<WARN_TRANSPOSE_T>(), parse_tree.getSelection(rhs), TRANSPOSE_T);
error_stream.warn(WARN_TRANSPOSE_T, parse_tree.getSelection(rhs), TRANSPOSE_T);

parse_tree.setOp(pn, OP_TRANSPOSE);
parse_tree.reduceNumArgs(pn, 1);
Expand Down
12 changes: 5 additions & 7 deletions src/forscape_symbol_lexical_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,11 +686,7 @@ void SymbolLexicalPass::resolveAlgorithm(ParseNode pn) alloc_except {
}

bool success = defineLocalScope( param, false );
if(!success){
error_stream.reset(); //DO THIS: this is unacceptable
error(parse_tree.getSelection(param), REDEFINE_PARAMETER);
parse_tree.setFlag(param, NONE);
}
if(!success) error(parse_tree.getSelection(param), REDEFINE_PARAMETER);
}
cutoff = std::numeric_limits<size_t>::max();

Expand Down Expand Up @@ -1218,8 +1214,10 @@ void SymbolLexicalPass::makeEntry(const Typeset::Selection& c, ParseNode pn, boo

void SymbolLexicalPass::appendEntry(ParseNode pn, size_t& old_entry, bool immutable, bool warn_on_shadow) alloc_except {
if(warn_on_shadow){
const auto warning_level = settings().warningLevel<WARN_SHADOWING>();
error_stream.warn(warning_level, parse_tree.getSelection(pn), SHADOWING_VAR);
error_stream.warn(WARN_SHADOWING, parse_tree.getSelection(pn), SHADOWING_VAR);

//EVENTUALLY: how do you make an error message with multiple links?
error_stream.warn(WARN_SHADOWING, symbols[old_entry].sel(parse_tree), "Previous declaration here", SHADOWING_VAR);
}
symbol_table.addSymbol(pn, lexical_depth, closure_depth, old_entry, immutable);
old_entry = symbols.size()-1;
Expand Down
5 changes: 5 additions & 0 deletions src/typeset_constructs/typeset_markerlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "typeset_construct.h"
#include "typeset_line.h"
#include "typeset_model.h"

#ifndef FORSCAPE_TYPESET_HEADLESS
#include "typeset_view.h"
Expand Down Expand Up @@ -60,6 +61,10 @@ class MarkerLink final : public Construct {
painter.drawText(x, y, "Line " + std::to_string(line_id+1) + ':');
painter.drawLine(x, y+height(), width, 0);
}

std::string getTooltip(double x_local, double y_local) const alloc_except {
return model->path.u8string();
}
#endif
};

Expand Down
Loading

0 comments on commit bc79bce

Please sign in to comment.