Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix compiler crashes and improve return statements. #652

Merged
merged 4 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 42 additions & 11 deletions common/goos/Reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,27 +110,38 @@ Reader::Reader() {
add_reader_macro(",@", "unquote-splicing");

// setup table of which characters are valid for starting a symbol
for (auto& x : valid_symbols_chars) {
for (auto& x : m_valid_symbols_chars) {
x = false;
}

for (char x = 'a'; x <= 'z'; x++) {
valid_symbols_chars[(int)x] = true;
m_valid_symbols_chars[(int)x] = true;
}

for (char x = 'A'; x <= 'Z'; x++) {
valid_symbols_chars[(int)x] = true;
m_valid_symbols_chars[(int)x] = true;
}

for (char x = '0'; x <= '9'; x++) {
valid_symbols_chars[(int)x] = true;
m_valid_symbols_chars[(int)x] = true;
}

const char bonus[] = "!$%&*+-/\\.,@^_-;:<>?~=#";

for (const char* c = bonus; *c; c++) {
valid_symbols_chars[(int)*c] = true;
m_valid_symbols_chars[(int)*c] = true;
}

// table of characters that are valid in source code:
for (auto& x : m_valid_source_text_chars) {
x = false;
}
for (int i = ' '; i <= '~'; i++) {
m_valid_source_text_chars[i] = true;
}
m_valid_source_text_chars[(int)'\n'] = true;
m_valid_source_text_chars[(int)'\t'] = true;
m_valid_source_text_chars[(int)'\r'] = true;
}

/*!
Expand Down Expand Up @@ -190,6 +201,17 @@ Object Reader::read_from_file(const std::vector<std::string>& file_path) {
* Common read for a SourceText
*/
Object Reader::internal_read(std::shared_ptr<SourceText> text, bool add_top_level) {
// validate the input;
for (int offset = 0; offset < text->get_size(); offset++) {
if (!m_valid_source_text_chars[(u8)text->get_text()[offset]]) {
// failed.
int line_number = text->get_line_idx(offset) + 1;
throw std::runtime_error(fmt::format("Invalid character found on line {} of {}: 0x{:x}",
line_number, text->get_description(),
(u32)text->get_text()[offset]));
}
}

// first create stream
TextStream ts(text);

Expand All @@ -205,6 +227,15 @@ Object Reader::internal_read(std::shared_ptr<SourceText> text, bool add_top_leve
}
}

bool Reader::check_string_is_valid(const std::string& str) const {
for (auto c : str) {
if (!m_valid_source_text_chars[(u8)c]) {
return false;
}
}
return true;
}

/*!
* Given a stream starting at the first character of a token, get the token. Doesn't consume
* whitespace at the end and leaves the stream on the first character after the token.
Expand Down Expand Up @@ -258,7 +289,7 @@ Token Reader::get_next_token(TextStream& stream) {
* These are used to make 'x turn into (quote x) and similar.
*/
void Reader::add_reader_macro(const std::string& shortcut, std::string replacement) {
reader_macros[shortcut] = std::move(replacement);
m_reader_macros[shortcut] = std::move(replacement);
}

/*!
Expand Down Expand Up @@ -377,16 +408,16 @@ Object Reader::read_list(TextStream& ts, bool expect_close_paren) {

// reader macro thing:
std::vector<std::string> reader_macro_string_stack;
auto kv = reader_macros.find(tok.text);
if (kv != reader_macros.end()) {
while (kv != reader_macros.end()) {
auto kv = m_reader_macros.find(tok.text);
if (kv != m_reader_macros.end()) {
while (kv != m_reader_macros.end()) {
// build a stack of reader macros to apply to this form.
reader_macro_string_stack.push_back(kv->second);
if (!ts.text_remains()) {
throw_reader_error(ts, "Something must follow a reader macro", 0);
}
tok = get_next_token(ts);
kv = reader_macros.find(tok.text);
kv = m_reader_macros.find(tok.text);
}
} else {
// only look for the dot when we aren't following a quote.
Expand Down Expand Up @@ -506,7 +537,7 @@ bool Reader::try_token_as_symbol(const Token& tok, Object& obj) {
// check start character is valid:
assert(!tok.text.empty());
char start = tok.text[0];
if (valid_symbols_chars[(int)start]) {
if (m_valid_symbols_chars[(int)start]) {
obj = SymbolObject::make_new(symbolTable, tok.text);
return true;
} else {
Expand Down
7 changes: 4 additions & 3 deletions common/goos/Reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class Reader {
Object read_from_string(const std::string& str, bool add_top_level = true);
std::optional<Object> read_from_stdin(const std::string& prompt, ReplWrapper& repl);
Object read_from_file(const std::vector<std::string>& file_path);

bool check_string_is_valid(const std::string& str) const;
std::string get_source_dir();

SymbolTable symbolTable;
Expand All @@ -97,9 +97,10 @@ class Reader {
bool read_string(TextStream& stream, Object& obj);
void add_reader_macro(const std::string& shortcut, std::string replacement);

char valid_symbols_chars[256];
bool m_valid_symbols_chars[256];
bool m_valid_source_text_chars[256];

std::unordered_map<std::string, std::string> reader_macros;
std::unordered_map<std::string, std::string> m_reader_macros;
};

std::string get_readable_string(const char* in);
Expand Down
14 changes: 7 additions & 7 deletions common/util/Trie.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ class Trie {
T* operator[](const std::string& str);

// Lookup an existing object. If none exists, return nullptr.
T* lookup(const std::string& str);
T* lookup(const std::string& str) const;

// return the number of entries.
int size() const { return m_size; }

// Get all objects starting with the given prefix.
std::vector<T*> lookup_prefix(const std::string& str);
std::vector<T*> lookup_prefix(const std::string& str) const;
~Trie();

private:
Expand Down Expand Up @@ -111,7 +111,7 @@ class Trie {
}
}

T* lookup(const char* str) {
T* lookup(const char* str) const {
if (!*str) {
return value;
}
Expand All @@ -121,7 +121,7 @@ class Trie {
return nullptr;
}

void get_all_children(std::vector<T*>& result) {
void get_all_children(std::vector<T*>& result) const {
if (value) {
result.push_back(value);
}
Expand All @@ -132,7 +132,7 @@ class Trie {
}
}

std::vector<T*> lookup_prefix(const char* str) {
std::vector<T*> lookup_prefix(const char* str) const {
if (!*str) {
std::vector<T*> result;
get_all_children(result);
Expand Down Expand Up @@ -165,7 +165,7 @@ void Trie<T>::insert(const std::string& str, const T& obj) {
}

template <typename T>
T* Trie<T>::lookup(const std::string& str) {
T* Trie<T>::lookup(const std::string& str) const {
return m_root.lookup(str.c_str());
}

Expand All @@ -180,6 +180,6 @@ T* Trie<T>::operator[](const std::string& str) {
}

template <typename T>
std::vector<T*> Trie<T>::lookup_prefix(const std::string& str) {
std::vector<T*> Trie<T>::lookup_prefix(const std::string& str) const {
return m_root.lookup_prefix(str.c_str());
}
8 changes: 6 additions & 2 deletions decompiler/IR2/FormExpressionAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3187,10 +3187,14 @@ void ReturnElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
std::vector<FormElement*> new_entries;
new_entries = rewrite_to_get_var(temp_stack, pool, env.end_var(), env);

assert(!new_entries.empty());
return_code->clear();
for (auto e : new_entries) {
return_code->push_back(e);

for (int i = 0; i < ((int)new_entries.size()) - 1; i++) {
stack.push_form_element(new_entries.at(i), true);
}

return_code->push_back(new_entries.back());
stack.push_form_element(this, true);
}

Expand Down
2 changes: 2 additions & 0 deletions decompiler/util/data_decompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,8 @@ goos::Object decompile_boxed_array(const DecompilerLabel& label,
} else if (word.kind == LinkedWord::PTR) {
result.push_back(
decompile_at_label(content_type, labels.at(word.label_id), labels, words, ts));
} else if (word.kind == LinkedWord::SYM_PTR) {
result.push_back(pretty_print::to_symbol(fmt::format("'{}", word.symbol_name)));
} else {
throw std::runtime_error(
fmt::format("Unknown content type in boxed array of references, word idx {}",
Expand Down
Loading