Compiler performance improvements and error clean-up (#782)

* compiler cleanup and error improvement

* fix test
This commit is contained in:
water111 2021-08-24 22:15:26 -04:00 committed by GitHub
parent e7b9ad5801
commit 7a5562106e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 462 additions and 264 deletions

View file

@ -122,14 +122,14 @@ void Interpreter::disable_printfs() {
*/
void Interpreter::load_goos_library() {
auto cmd = "(load-file \"goal_src/goos-lib.gs\")";
eval_with_rewind(reader.read_from_string(cmd), global_environment.as_env());
eval_with_rewind(reader.read_from_string(cmd), global_environment.as_env_ptr());
}
/*!
* In env, set the variable named "name" to the value var.
*/
void Interpreter::define_var_in_env(Object& env, Object& var, const std::string& name) {
env.as_env()->vars[intern(name).as_symbol()] = var;
env.as_env()->vars[intern_ptr(name)] = var;
}
/*!
@ -139,6 +139,10 @@ Object Interpreter::intern(const std::string& name) {
return SymbolObject::make_new(reader.symbolTable, name);
}
HeapObject* Interpreter::intern_ptr(const std::string& name) {
return reader.symbolTable.intern_ptr(name);
}
/*!
* Display the REPL, which will run until the user executes exit.
*/
@ -152,7 +156,7 @@ void Interpreter::execute_repl(ReplWrapper& repl) {
continue;
}
// evaluate
Object evald = eval_with_rewind(*obj, global_environment.as_env());
Object evald = eval_with_rewind(*obj, global_environment.as_env_ptr());
// print
printf("%s\n", evald.print().c_str());
} catch (std::exception& e) {
@ -489,7 +493,7 @@ bool try_symbol_lookup(const Object& sym,
}
// loop up envs until we find it.
std::shared_ptr<EnvironmentObject> search_env = env;
EnvironmentObject* search_env = env.get();
for (;;) {
auto kv = search_env->vars.find(sym.as_symbol());
if (kv != search_env->vars.end()) {
@ -497,7 +501,7 @@ bool try_symbol_lookup(const Object& sym,
return true;
}
auto pe = search_env->parent_env;
auto pe = search_env->parent_env.get();
if (pe) {
search_env = pe;
} else {
@ -565,7 +569,7 @@ Object Interpreter::eval_pair(const Object& obj, const std::shared_ptr<Environme
Arguments args = get_args(obj, rest, macro->args);
auto mac_env_obj = EnvironmentObject::make_new();
auto mac_env = mac_env_obj.as_env();
auto mac_env = mac_env_obj.as_env_ptr();
mac_env->parent_env = env; // not 100% clear that this is right
set_args_in_env(obj, args, macro->args, mac_env);
// expand the macro!
@ -583,7 +587,7 @@ Object Interpreter::eval_pair(const Object& obj, const std::shared_ptr<Environme
Arguments args = get_args(obj, rest, lam->args);
eval_args(&args, env);
auto lam_env_obj = EnvironmentObject::make_new();
auto lam_env = lam_env_obj.as_env();
auto lam_env = lam_env_obj.as_env_ptr();
lam_env->parent_env = lam->parent_env;
set_args_in_env(obj, args, lam->args, lam_env);
return eval_list_return_last(lam->body, lam->body, lam_env);
@ -641,7 +645,7 @@ Object Interpreter::eval_define(const Object& form,
if (args.has_named("env")) {
auto result = eval_with_rewind(args.get_named("env"), env);
expect_env(form, result);
define_env = result.as_env();
define_env = result.as_env_ptr();
}
Object value = eval_with_rewind(args.unnamed[1], env);
@ -1018,7 +1022,7 @@ Object Interpreter::eval_load_file(const Object& form,
}
try {
return eval_with_rewind(o, global_environment.as_env());
return eval_with_rewind(o, global_environment.as_env_ptr());
} catch (std::runtime_error& e) {
throw_eval_error(form, std::string("eval error inside of load-file:\n") + e.what());
}

View file

@ -23,6 +23,7 @@ class Interpreter {
void set_global_variable_to_symbol(const std::string& name, const std::string& value);
Object eval(Object obj, const std::shared_ptr<EnvironmentObject>& env);
Object intern(const std::string& name);
HeapObject* intern_ptr(const std::string& name);
void disable_printfs();
Object eval_symbol(const Object& sym, const std::shared_ptr<EnvironmentObject>& env);
bool eval_symbol(const Object& sym,

View file

@ -46,7 +46,7 @@
namespace goos {
std::shared_ptr<EmptyListObject> gEmptyList = nullptr;
std::shared_ptr<EmptyListObject> gEmptyList = std::make_shared<EmptyListObject>();
std::shared_ptr<EmptyListObject>& get_empty_list() {
return gEmptyList;
}
@ -154,16 +154,57 @@ Object build_list(const std::vector<Object>& objects) {
return EmptyListObject::make_new();
}
Object empty = EmptyListObject::make_new();
Object head = PairObject::make_new(objects[0], empty);
Object last = head;
// this is by far the most expensive part of parsing, so this is done a bit carefully.
// we maintain a std::shared_ptr<PairObject> that represents the list, built from back to front.
std::shared_ptr<PairObject> head =
std::make_shared<PairObject>(objects.back(), EmptyListObject::make_new());
for (std::size_t i = 1; i < objects.size(); i++) {
last.as_pair()->cdr = PairObject::make_new(objects[i], empty);
last = last.as_pair()->cdr;
s64 idx = ((s64)objects.size()) - 2;
while (idx >= 0) {
Object next;
next.type = ObjectType::PAIR;
next.heap_obj = std::move(head);
head = std::make_shared<PairObject>();
head->car = objects[idx];
head->cdr = std::move(next);
idx--;
}
return head;
Object result;
result.type = ObjectType::PAIR;
result.heap_obj = head;
return result;
}
Object build_list(std::vector<Object>&& objects) {
if (objects.empty()) {
return EmptyListObject::make_new();
}
// this is by far the most expensive part of parsing, so this is done a bit carefully.
// we maintain a std::shared_ptr<PairObject> that represents the list, built from back to front.
std::shared_ptr<PairObject> head =
std::make_shared<PairObject>(objects.back(), EmptyListObject::make_new());
s64 idx = ((s64)objects.size()) - 2;
while (idx >= 0) {
Object next;
next.type = ObjectType::PAIR;
next.heap_obj = std::move(head);
head = std::make_shared<PairObject>();
head->car = std::move(objects[idx]);
head->cdr = std::move(next);
idx--;
}
Object result;
result.type = ObjectType::PAIR;
result.heap_obj = head;
return result;
}
/*!

View file

@ -167,6 +167,8 @@ class ArrayObject;
class Object {
public:
std::shared_ptr<HeapObject> heap_obj = nullptr;
friend Object build_list(const std::vector<Object>& objects);
friend Object build_list(std::vector<Object>&& objects);
union {
IntegerObject integer_obj;
@ -226,60 +228,14 @@ class Object {
return o;
}
std::shared_ptr<PairObject> as_pair() const {
if (type != ObjectType::PAIR) {
throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " +
print());
}
return std::dynamic_pointer_cast<PairObject>(heap_obj);
}
std::shared_ptr<EnvironmentObject> as_env() const {
if (type != ObjectType::ENVIRONMENT) {
throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print());
}
return std::dynamic_pointer_cast<EnvironmentObject>(heap_obj);
}
std::shared_ptr<SymbolObject> as_symbol() const {
if (type != ObjectType::SYMBOL) {
throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " +
print());
}
return std::dynamic_pointer_cast<SymbolObject>(heap_obj);
}
std::shared_ptr<StringObject> as_string() const {
if (type != ObjectType::STRING) {
throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " +
print());
}
return std::dynamic_pointer_cast<StringObject>(heap_obj);
}
std::shared_ptr<LambdaObject> as_lambda() const {
if (type != ObjectType::LAMBDA) {
throw std::runtime_error("as_lambda called on a " + object_type_to_string(type) + " " +
print());
}
return std::dynamic_pointer_cast<LambdaObject>(heap_obj);
}
std::shared_ptr<MacroObject> as_macro() const {
if (type != ObjectType::MACRO) {
throw std::runtime_error("as_macro called on a " + object_type_to_string(type) + " " +
print());
}
return std::dynamic_pointer_cast<MacroObject>(heap_obj);
}
std::shared_ptr<ArrayObject> as_array() const {
if (type != ObjectType::ARRAY) {
throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " +
print());
}
return std::dynamic_pointer_cast<ArrayObject>(heap_obj);
}
PairObject* as_pair() const;
EnvironmentObject* as_env() const;
std::shared_ptr<EnvironmentObject> as_env_ptr() const;
SymbolObject* as_symbol() const;
StringObject* as_string() const;
LambdaObject* as_lambda() const;
MacroObject* as_macro() const;
ArrayObject* as_array() const;
IntType& as_int() {
if (type != ObjectType::INTEGER) {
@ -346,9 +302,6 @@ class EmptyListObject : public HeapObject {
static Object make_new() {
Object obj;
obj.type = ObjectType::EMPTY_LIST;
if (!get_empty_list()) {
get_empty_list() = std::make_shared<EmptyListObject>();
}
obj.heap_obj = get_empty_list();
return obj;
}
@ -388,8 +341,8 @@ class SymbolObject : public HeapObject {
*/
class SymbolTable {
public:
std::shared_ptr<SymbolObject> intern(const std::string& name) {
auto kv = table.find(name);
std::shared_ptr<HeapObject> intern(const std::string& name) {
const auto& kv = table.find(name);
if (kv == table.end()) {
auto iter = table.insert({name, std::make_shared<SymbolObject>(name)});
return (*iter.first).second;
@ -398,10 +351,20 @@ class SymbolTable {
}
}
HeapObject* intern_ptr(const std::string& name) {
const auto& kv = table.find(name);
if (kv == table.end()) {
auto iter = table.insert({name, std::make_shared<SymbolObject>(name)});
return (*iter.first).second.get();
} else {
return kv->second.get();
}
}
~SymbolTable() = default;
private:
std::unordered_map<std::string, std::shared_ptr<SymbolObject>> table;
std::unordered_map<std::string, std::shared_ptr<HeapObject>> table;
};
class StringObject : public HeapObject {
@ -426,9 +389,10 @@ class PairObject : public HeapObject {
public:
Object car, cdr;
PairObject(Object car_, Object cdr_) : car(car_), cdr(cdr_) {}
PairObject(const Object& car_, const Object& cdr_) : car(car_), cdr(cdr_) {}
PairObject() = default;
static Object make_new(Object a, Object b) {
static Object make_new(const Object& a, const Object& b) {
Object obj;
obj.type = ObjectType::PAIR;
obj.heap_obj = std::make_shared<PairObject>(a, b);
@ -481,7 +445,10 @@ class EnvironmentObject : public HeapObject {
public:
std::string name;
std::shared_ptr<EnvironmentObject> parent_env;
std::unordered_map<std::shared_ptr<SymbolObject>, Object> vars;
// the symbols will be stored in the symbol table and never removed, so we don't need shared
// pointers here.
std::unordered_map<HeapObject*, Object> vars;
EnvironmentObject() = default;
@ -641,5 +608,64 @@ class ArrayObject : public HeapObject {
};
Object build_list(const std::vector<Object>& objects);
Object build_list(std::vector<Object>&& objects);
inline PairObject* Object::as_pair() const {
if (type != ObjectType::PAIR) {
throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + print());
}
return static_cast<PairObject*>(heap_obj.get());
}
inline EnvironmentObject* Object::as_env() const {
if (type != ObjectType::ENVIRONMENT) {
throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print());
}
return static_cast<EnvironmentObject*>(heap_obj.get());
}
inline std::shared_ptr<EnvironmentObject> Object::as_env_ptr() const {
if (type != ObjectType::ENVIRONMENT) {
throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print());
}
return std::dynamic_pointer_cast<EnvironmentObject>(heap_obj);
}
inline SymbolObject* Object::as_symbol() const {
if (type != ObjectType::SYMBOL) {
throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " +
print());
}
return static_cast<SymbolObject*>(heap_obj.get());
}
inline StringObject* Object::as_string() const {
if (type != ObjectType::STRING) {
throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " +
print());
}
return static_cast<StringObject*>(heap_obj.get());
}
inline LambdaObject* Object::as_lambda() const {
if (type != ObjectType::LAMBDA) {
throw std::runtime_error("as_lambda called on a " + object_type_to_string(type) + " " +
print());
}
return static_cast<LambdaObject*>(heap_obj.get());
}
inline MacroObject* Object::as_macro() const {
if (type != ObjectType::MACRO) {
throw std::runtime_error("as_macro called on a " + object_type_to_string(type) + " " + print());
}
return static_cast<MacroObject*>(heap_obj.get());
}
inline ArrayObject* Object::as_array() const {
if (type != ObjectType::ARRAY) {
throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + print());
}
return static_cast<ArrayObject*>(heap_obj.get());
}
} // namespace goos

View file

@ -189,7 +189,17 @@ Object Reader::read_from_string(const std::string& str, bool add_top_level) {
* Read a file
*/
Object Reader::read_from_file(const std::vector<std::string>& file_path) {
auto textFrag = std::make_shared<FileText>(file_util::get_file_path(file_path));
std::string joined_name;
for (const auto& thing : file_path) {
if (!joined_name.empty()) {
joined_name += '/';
}
joined_name += thing;
}
auto textFrag = std::make_shared<FileText>(file_util::get_file_path(file_path), joined_name);
db.insert(textFrag);
auto result = internal_read(textFrag);
@ -524,7 +534,7 @@ Object Reader::read_list(TextStream& ts, bool expect_close_paren) {
db.link(rv, ts.text, start_offset);
return rv;
} else {
auto rv = build_list(objects);
auto rv = build_list(std::move(objects));
db.link(rv, ts.text, start_offset);
return rv;
}

View file

@ -12,6 +12,7 @@
*/
#include "common/util/FileUtil.h"
#include "third-party/fmt/core.h"
#include "TextDB.h"
@ -64,6 +65,10 @@ int SourceText::get_line_idx(int offset) {
std::to_string(offset));
}
int SourceText::get_offset_of_line(int line_idx) {
return offset_by_line.at(line_idx);
}
/*!
* Gets the [start, end) character offset of the line containing the given offset.
*/
@ -79,8 +84,9 @@ std::pair<int, int> SourceText::get_containing_line(int offset) {
/*!
* Read text from a file.
*/
FileText::FileText(std::string filename_) : filename(std::move(filename_)) {
text = file_util::read_text_file(filename);
FileText::FileText(const std::string& filename, const std::string& description_name)
: m_filename(filename), m_desc_name(description_name) {
text = file_util::read_text_file(m_filename);
build_offsets();
}
@ -134,10 +140,14 @@ std::string TextDb::get_info_for(const Object& o, bool* terminate_compiler_error
* Given a source text and an offset, print a description of where it is.
*/
std::string TextDb::get_info_for(const std::shared_ptr<SourceText>& frag, int offset) const {
std::string result = "text from " + frag->get_description() +
", line: " + std::to_string(frag->get_line_idx(offset) + 1) + "\n";
int line_idx = frag->get_line_idx(offset);
std::string result = frag->get_description() + ", line: " + std::to_string(line_idx + 1) + "\n";
result += frag->get_line_containing_offset(offset) + "\n";
return result;
int offset_in_line = std::max(offset - frag->get_offset_of_line(line_idx), 1) - 1;
std::string pointer(offset_in_line, ' ');
pointer += "^\n";
return result + pointer;
}
/*!
@ -156,14 +166,13 @@ void TextDb::inherit_info(const Object& parent, const Object& child) {
while (!children.empty()) {
auto top = children.back();
children.pop_back();
if (map.find(top->heap_obj) == map.end()) {
map[top->heap_obj] = parent_kv->second;
}
if (top->as_pair()->car.is_pair()) {
children.push_back(&top->as_pair()->car);
}
if (top->as_pair()->cdr.is_pair()) {
children.push_back(&top->as_pair()->cdr);
if (map.insert({top->heap_obj, parent_kv->second}).second) {
if (top->as_pair()->car.is_pair()) {
children.push_back(&top->as_pair()->car);
}
if (top->as_pair()->cdr.is_pair()) {
children.push_back(&top->as_pair()->cdr);
}
}
}
}

View file

@ -34,6 +34,7 @@ class SourceText {
virtual std::string get_description() = 0;
std::string get_line_containing_offset(int offset);
int get_line_idx(int offset);
int get_offset_of_line(int line_idx);
// should the compiler keep looking up the stack when printing errors on this, or not?
// this should return true if the text source is specific enough so that they can find what they
// want
@ -73,13 +74,14 @@ class ProgramString : public SourceText {
*/
class FileText : public SourceText {
public:
FileText(std::string filename_);
FileText(const std::string& filename, const std::string& description_name);
std::string get_description() { return filename; }
std::string get_description() { return m_desc_name; }
~FileText() = default;
private:
std::string filename;
std::string m_filename;
std::string m_desc_name;
};
struct TextRef {

View file

@ -170,10 +170,15 @@ Val* Compiler::compile_error_guard(const goos::Object& code, Env* env) {
obj_print += "...";
}
bool term;
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Location:\n");
fmt::print(m_goos.reader.db.get_info_for(code, &term));
auto loc_info = m_goos.reader.db.get_info_for(code, &term);
if (term) {
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Location:\n");
fmt::print(loc_info);
}
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Code:\n");
fmt::print("{}\n", obj_print);
if (term) {
ce.print_err_stack = false;
}
@ -190,14 +195,24 @@ Val* Compiler::compile_error_guard(const goos::Object& code, Env* env) {
obj_print = obj_print.substr(0, 80);
obj_print += "...";
}
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Location:\n");
fmt::print(m_goos.reader.db.get_info_for(code));
bool term;
auto loc_info = m_goos.reader.db.get_info_for(code, &term);
if (term) {
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Location:\n");
fmt::print(loc_info);
}
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Code:\n");
fmt::print("{}\n", obj_print);
CompilerException ce("Compiler Exception");
if (term) {
ce.print_err_stack = false;
}
std::string line(80, '-');
line.push_back('\n');
fmt::print(line);
throw e;
throw ce;
}
}
@ -239,7 +254,7 @@ void Compiler::color_object_file(FileEnv* env) {
// regalloc_result_2.num_spilled_vars);
}
num_spills_in_file += regalloc_result_2.num_spills;
f->set_allocations(regalloc_result_2);
f->set_allocations(std::move(regalloc_result_2));
} else {
fmt::print(
"Warning: function {} failed register allocation with the v2 allocator. Falling back to "
@ -249,7 +264,7 @@ void Compiler::color_object_file(FileEnv* env) {
auto regalloc_result = allocate_registers(input);
m_debug_stats.num_spills_v1 += regalloc_result.num_spills;
num_spills_in_file += regalloc_result.num_spills;
f->set_allocations(regalloc_result);
f->set_allocations(std::move(regalloc_result));
}
}

View file

@ -71,8 +71,8 @@ class Compiler {
Debugger m_debugger;
goos::Interpreter m_goos;
std::unordered_map<std::string, TypeSpec> m_symbol_types;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, goos::Object> m_global_constants;
std::unordered_map<std::shared_ptr<goos::SymbolObject>, LambdaVal*> m_inlineable_functions;
std::unordered_map<goos::HeapObject*, goos::Object> m_global_constants;
std::unordered_map<goos::HeapObject*, LambdaVal*> m_inlineable_functions;
CompilerSettings m_settings;
bool m_throw_on_define_extern_redefinition = false;
SymbolInfoMap m_symbol_info;
@ -109,6 +109,7 @@ class Compiler {
Val* compile_goos_macro(const goos::Object& o,
const goos::Object& macro_obj,
const goos::Object& rest,
const goos::Object& name_symbol,
Env* env);
Val* compile_pair(const goos::Object& code, Env* env);
Val* compile_integer(const goos::Object& code, Env* env);
@ -357,9 +358,9 @@ class Compiler {
void throw_compiler_error(const goos::Object& code, const std::string& str, Args&&... args) {
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "-- Compilation Error! --\n");
if (!str.empty() && str.back() == '\n') {
fmt::print(str, std::forward<Args>(args)...);
fmt::print(fmt::emphasis::bold, str, std::forward<Args>(args)...);
} else {
fmt::print(str + '\n', std::forward<Args>(args)...);
fmt::print(fmt::emphasis::bold, str + '\n', std::forward<Args>(args)...);
}
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Form:\n");
@ -371,9 +372,9 @@ class Compiler {
void throw_compiler_error_no_code(const std::string& str, Args&&... args) {
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "-- Compilation Error! --\n");
if (!str.empty() && str.back() == '\n') {
fmt::print(str, std::forward<Args>(args)...);
fmt::print(fmt::emphasis::bold, str, std::forward<Args>(args)...);
} else {
fmt::print(str + '\n', std::forward<Args>(args)...);
fmt::print(fmt::emphasis::bold, str + '\n', std::forward<Args>(args)...);
}
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Form:\n");

View file

@ -18,8 +18,8 @@ void Env::emit(std::unique_ptr<IR> ir) {
/*!
* Allocate an IRegister with the given type.
*/
RegVal* Env::make_ireg(TypeSpec ts, RegClass reg_class) {
return m_parent->make_ireg(std::move(ts), reg_class);
RegVal* Env::make_ireg(const TypeSpec& ts, RegClass reg_class) {
return m_parent->make_ireg(ts, reg_class);
}
/*!
@ -63,7 +63,7 @@ std::unordered_map<std::string, Label>& Env::get_label_map() {
// Because this is the top of the environment chain, all these end the parent calls and provide
// errors, or return that the items were not found.
GlobalEnv::GlobalEnv() : Env(nullptr) {}
GlobalEnv::GlobalEnv() : Env(EnvKind::OTHER_ENV, nullptr) {}
std::string GlobalEnv::print() {
return "global-env";
@ -81,7 +81,7 @@ void GlobalEnv::emit(std::unique_ptr<IR> ir) {
/*!
* Allocate an IRegister with the given type.
*/
RegVal* GlobalEnv::make_ireg(TypeSpec ts, RegClass reg_class) {
RegVal* GlobalEnv::make_ireg(const TypeSpec& ts, RegClass reg_class) {
(void)ts;
(void)reg_class;
throw std::runtime_error("cannot alloc reg in GlobalEnv");
@ -136,7 +136,8 @@ void NoEmitEnv::emit(std::unique_ptr<IR> ir) {
// BlockEnv
///////////////////
BlockEnv::BlockEnv(Env* parent, std::string _name) : Env(parent), name(std::move(_name)) {}
BlockEnv::BlockEnv(Env* parent, std::string _name)
: Env(EnvKind::OTHER_ENV, parent), name(std::move(_name)) {}
std::string BlockEnv::print() {
return "block-" + name;
@ -154,7 +155,8 @@ BlockEnv* BlockEnv::find_block(const std::string& block) {
// FileEnv
///////////////////
FileEnv::FileEnv(Env* parent, std::string name) : Env(parent), m_name(std::move(name)) {}
FileEnv::FileEnv(Env* parent, std::string name)
: Env(EnvKind::FILE_ENV, parent), m_name(std::move(name)) {}
std::string FileEnv::print() {
return "file-" + m_name;
@ -202,7 +204,7 @@ bool FileEnv::is_empty() {
///////////////////
FunctionEnv::FunctionEnv(Env* parent, std::string name)
: DeclareEnv(parent), m_name(std::move(name)) {}
: DeclareEnv(EnvKind::FUNCTION_ENV, parent), m_name(std::move(name)) {}
std::string FunctionEnv::print() {
return "function-" + m_name;
@ -235,7 +237,7 @@ void FunctionEnv::resolve_gotos() {
}
}
RegVal* FunctionEnv::make_ireg(TypeSpec ts, RegClass reg_class) {
RegVal* FunctionEnv::make_ireg(const TypeSpec& ts, RegClass reg_class) {
IRegister ireg;
ireg.reg_class = reg_class;
ireg.id = m_iregs.size();

View file

@ -6,9 +6,6 @@
* manages the memory for stuff generated during compiling.
*/
#ifndef JAK_ENV_H
#define JAK_ENV_H
#include <string>
#include <memory>
#include <vector>
@ -21,17 +18,22 @@
class FileEnv;
class BlockEnv;
class FunctionEnv;
class SymbolMacroEnv;
class MacroExpandEnv;
class IR;
enum class EnvKind { FILE_ENV, FUNCTION_ENV, SYMBOL_MACRO_ENV, MACRO_EXPAND_ENV, OTHER_ENV };
/*!
* Parent class for Env's
*/
class Env {
public:
explicit Env(Env* parent) : m_parent(parent) {}
explicit Env(EnvKind kind, Env* parent);
virtual std::string print() = 0;
virtual void emit(std::unique_ptr<IR> ir);
virtual RegVal* make_ireg(TypeSpec ts, RegClass reg_class);
virtual RegVal* make_ireg(const TypeSpec& ts, RegClass reg_class);
virtual void constrain_reg(IRegConstraint constraint); // todo, remove!
virtual RegVal* lexical_lookup(goos::Object sym);
virtual BlockEnv* find_block(const std::string& name);
@ -47,8 +49,22 @@ class Env {
emit(std::make_unique<IR_Type>(std::forward<Args>(args)...));
}
FileEnv* file_env() { return m_lowest_envs.file_env; }
FunctionEnv* function_env() { return m_lowest_envs.function_env; }
SymbolMacroEnv* symbol_macro_env() { return m_lowest_envs.symbol_macro_env; }
MacroExpandEnv* macro_expand_env() { return m_lowest_envs.macro_expand_env; }
protected:
EnvKind m_kind;
Env* m_parent = nullptr;
// cache of the lowest env of the given type, possibly including ourselves
struct {
FileEnv* file_env = nullptr;
FunctionEnv* function_env = nullptr;
SymbolMacroEnv* symbol_macro_env = nullptr;
MacroExpandEnv* macro_expand_env = nullptr;
} m_lowest_envs;
};
/*!
@ -59,7 +75,7 @@ class GlobalEnv : public Env {
GlobalEnv();
std::string print() override;
void emit(std::unique_ptr<IR> ir) override;
RegVal* make_ireg(TypeSpec ts, RegClass reg_class) override;
RegVal* make_ireg(const TypeSpec& ts, RegClass reg_class) override;
void constrain_reg(IRegConstraint constraint) override;
RegVal* lexical_lookup(goos::Object sym) override;
BlockEnv* find_block(const std::string& name) override;
@ -77,7 +93,7 @@ class GlobalEnv : public Env {
*/
class NoEmitEnv : public Env {
public:
explicit NoEmitEnv(Env* parent) : Env(parent) {}
explicit NoEmitEnv(Env* parent) : Env(EnvKind::OTHER_ENV, parent) {}
std::string print() override;
void emit(std::unique_ptr<IR> ir) override;
~NoEmitEnv() = default;
@ -133,7 +149,7 @@ class FileEnv : public Env {
*/
class DeclareEnv : public Env {
public:
explicit DeclareEnv(Env* parent) : Env(parent) {}
explicit DeclareEnv(EnvKind kind, Env* parent) : Env(kind, parent) {}
virtual std::string print() = 0;
~DeclareEnv() = default;
@ -168,12 +184,12 @@ class FunctionEnv : public DeclareEnv {
void set_segment(int seg) { segment = seg; }
void emit(std::unique_ptr<IR> ir) override;
void finish();
RegVal* make_ireg(TypeSpec ts, RegClass reg_class) override;
RegVal* make_ireg(const TypeSpec& ts, RegClass reg_class) override;
const std::vector<std::unique_ptr<IR>>& code() const { return m_code; }
int max_vars() const { return m_iregs.size(); }
const std::vector<IRegConstraint>& constraints() { return m_constraints; }
void constrain(const IRegConstraint& c) { m_constraints.push_back(c); }
void set_allocations(const AllocationResult& result) { m_regalloc_result = result; }
void set_allocations(AllocationResult&& result) { m_regalloc_result = std::move(result); }
RegVal* lexical_lookup(goos::Object sym) override;
const AllocationResult& alloc_result() { return m_regalloc_result; }
bool needs_aligned_stack() const { return m_aligned_stack_required; }
@ -250,7 +266,7 @@ class BlockEnv : public Env {
class LexicalEnv : public DeclareEnv {
public:
explicit LexicalEnv(Env* parent) : DeclareEnv(parent) {}
explicit LexicalEnv(Env* parent) : DeclareEnv(EnvKind::OTHER_ENV, parent) {}
RegVal* lexical_lookup(goos::Object sym) override;
std::string print() override;
std::unordered_map<std::string, RegVal*> vars;
@ -258,7 +274,7 @@ class LexicalEnv : public DeclareEnv {
class LabelEnv : public Env {
public:
explicit LabelEnv(Env* parent) : Env(parent) {}
explicit LabelEnv(Env* parent) : Env(EnvKind::OTHER_ENV, parent) {}
std::string print() override { return "labelenv"; }
std::unordered_map<std::string, Label>& get_label_map() override;
BlockEnv* find_block(const std::string& name) override;
@ -267,22 +283,51 @@ class LabelEnv : public Env {
std::unordered_map<std::string, Label> m_labels;
};
class WithInlineEnv : public Env {
public:
WithInlineEnv(Env* parent, bool _inline_preference)
: Env(parent), inline_preference(_inline_preference) {}
bool inline_preference = false;
};
class SymbolMacroEnv : public Env {
public:
explicit SymbolMacroEnv(Env* parent) : Env(parent) {}
std::unordered_map<std::shared_ptr<goos::SymbolObject>, goos::Object> macros;
explicit SymbolMacroEnv(Env* parent) : Env(EnvKind::SYMBOL_MACRO_ENV, parent) {}
// key is goos symbols.
std::unordered_map<goos::HeapObject*, goos::Object> macros;
std::string print() override { return "symbol-macro-env"; }
};
class MacroExpandEnv : public Env {
public:
MacroExpandEnv(Env* parent,
const goos::HeapObject* macro_name,
const goos::Object& macro_body,
const goos::Object& macro_use)
: Env(EnvKind::MACRO_EXPAND_ENV, parent),
m_macro_name(macro_name),
m_macro_body(macro_body),
m_macro_use_location(macro_use) {
MacroExpandEnv* parent_macro = nullptr;
if (parent) {
parent_macro = parent->macro_expand_env();
}
if (parent_macro) {
m_root_form = parent_macro->m_root_form;
} else {
m_root_form = m_macro_use_location;
}
}
std::string print() override { return "macro-env"; }
const goos::HeapObject* name() const { return m_macro_name; }
const goos::Object& macro_body() const { return m_macro_body; }
const goos::Object& macro_use_location() const { return m_macro_use_location; }
const goos::Object& root_form() const { return m_root_form; }
private:
const goos::HeapObject* m_macro_name = nullptr;
goos::Object m_macro_body;
goos::Object m_macro_use_location;
goos::Object m_root_form;
};
template <typename T>
T* get_parent_env_of_type(Env* in) {
T* get_parent_env_of_type_slow(Env* in) {
for (;;) {
auto attempt = dynamic_cast<T*>(in);
if (attempt)
@ -293,11 +338,29 @@ T* get_parent_env_of_type(Env* in) {
in = in->parent();
}
}
// function
// block
// lexical
// label
// symbolmacro
// get parent env of type.
#endif // JAK_ENV_H
inline Env::Env(EnvKind kind, Env* parent) : m_kind(kind), m_parent(parent) {
if (m_kind == EnvKind::FILE_ENV) {
m_lowest_envs.file_env = static_cast<FileEnv*>(this);
} else {
m_lowest_envs.file_env = m_parent ? m_parent->m_lowest_envs.file_env : nullptr;
}
if (m_kind == EnvKind::FUNCTION_ENV) {
m_lowest_envs.function_env = static_cast<FunctionEnv*>(this);
} else {
m_lowest_envs.function_env = m_parent ? m_parent->m_lowest_envs.function_env : nullptr;
}
if (m_kind == EnvKind::SYMBOL_MACRO_ENV) {
m_lowest_envs.symbol_macro_env = static_cast<SymbolMacroEnv*>(this);
} else {
m_lowest_envs.symbol_macro_env = m_parent ? m_parent->m_lowest_envs.symbol_macro_env : nullptr;
}
if (m_kind == EnvKind::MACRO_EXPAND_ENV) {
m_lowest_envs.macro_expand_env = static_cast<MacroExpandEnv*>(this);
} else {
m_lowest_envs.macro_expand_env = m_parent ? m_parent->m_lowest_envs.macro_expand_env : nullptr;
}
}

View file

@ -130,12 +130,12 @@ TypeSpec Compiler::parse_typespec(const goos::Object& src) {
bool Compiler::is_local_symbol(const goos::Object& obj, Env* env) {
// check in the symbol macro env.
auto mlet_env = get_parent_env_of_type<SymbolMacroEnv>(env);
auto mlet_env = env->symbol_macro_env();
while (mlet_env) {
if (mlet_env->macros.find(obj.as_symbol()) != mlet_env->macros.end()) {
return true;
}
mlet_env = get_parent_env_of_type<SymbolMacroEnv>(mlet_env->parent());
mlet_env = mlet_env->parent()->symbol_macro_env();
}
// check lexical

View file

@ -250,7 +250,7 @@ std::string BitFieldVal::print() const {
RegVal* BitFieldVal::to_reg(Env* env) {
int start_bit = -1;
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
RegVal* result = fe->make_ireg(coerce_to_reg_type(m_ts), RegClass::GPR_64);
// this first step gets the right 64-bits into a GPR that is also used as the result.

View file

@ -33,7 +33,7 @@ Val* Compiler::compile_rlet(const goos::Object& form, const goos::Object& rest,
auto defs = args.unnamed.front();
auto fenv = get_parent_env_of_type<FunctionEnv>(env);
auto fenv = env->function_env();
auto lenv = fenv->alloc_env<LexicalEnv>(env);
std::vector<IRegConstraint> constraints;

View file

@ -302,7 +302,7 @@ Val* Compiler::compile_pair(const goos::Object& code, Env* env) {
// next try as a macro
goos::Object macro_obj;
if (try_getting_macro_from_goos(head, &macro_obj)) {
return compile_goos_macro(code, macro_obj, rest, env);
return compile_goos_macro(code, macro_obj, rest, head, env);
}
// next try as an enum
@ -339,12 +339,12 @@ Val* Compiler::compile_char(const goos::Object& code, Env* env) {
* The type is always int.
*/
Val* Compiler::compile_integer(s64 value, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
return fe->alloc_val<IntegerConstantVal>(m_ts.make_typespec("int"), &value, 8);
}
Val* Compiler::compile_integer(const U128& value, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
return fe->alloc_val<IntegerConstantVal>(m_ts.make_typespec("int"), &value, 16);
}
@ -352,7 +352,7 @@ Val* Compiler::compile_integer(const U128& value, Env* env) {
* Get a SymbolVal representing a GOAL symbol object.
*/
SymbolVal* Compiler::compile_get_sym_obj(const std::string& name, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
return fe->alloc_val<SymbolVal>(name, m_ts.make_typespec("symbol"));
}
@ -372,7 +372,7 @@ Val* Compiler::compile_get_symbol_value(const goos::Object& form,
auto ts = existing_symbol->second;
auto sext = m_ts.lookup_type(ts)->get_load_signed();
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto sym = fe->alloc_val<SymbolVal>(name, m_ts.make_typespec("symbol"));
auto re = fe->alloc_val<SymbolValueVal>(sym, ts, sext);
return re;
@ -391,13 +391,13 @@ Val* Compiler::compile_symbol(const goos::Object& form, Env* env) {
}
// see if the symbol is defined in any enclosing symbol macro envs (mlet's).
auto mlet_env = get_parent_env_of_type<SymbolMacroEnv>(env);
auto mlet_env = env->symbol_macro_env();
while (mlet_env) {
auto mlkv = mlet_env->macros.find(form.as_symbol());
if (mlkv != mlet_env->macros.end()) {
return compile_error_guard(mlkv->second, env);
}
mlet_env = get_parent_env_of_type<SymbolMacroEnv>(mlet_env->parent());
mlet_env = mlet_env->parent()->symbol_macro_env();
}
// see if it's a local variable
@ -430,7 +430,7 @@ Val* Compiler::compile_symbol(const goos::Object& form, Env* env) {
* Compile a string constant. The constant is placed in the same segment as the parent function.
*/
Val* Compiler::compile_string(const goos::Object& form, Env* env) {
auto segment = get_parent_env_of_type<FunctionEnv>(env)->segment;
auto segment = env->function_env()->segment;
if (segment == TOP_LEVEL_SEGMENT) {
segment = MAIN_SEGMENT;
}
@ -442,9 +442,9 @@ Val* Compiler::compile_string(const goos::Object& form, Env* env) {
*/
Val* Compiler::compile_string(const std::string& str, Env* env, int seg) {
auto obj = std::make_unique<StaticString>(str, seg);
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto result = fe->alloc_val<StaticVal>(obj.get(), m_ts.make_typespec("string"));
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fie = env->file_env();
fie->add_static(std::move(obj));
return result;
}
@ -455,7 +455,7 @@ Val* Compiler::compile_string(const std::string& str, Env* env, int seg) {
* of the code, at least in Jak 1.
*/
Val* Compiler::compile_float(const goos::Object& code, Env* env) {
auto segment = get_parent_env_of_type<FunctionEnv>(env)->segment;
auto segment = env->function_env()->segment;
if (segment == TOP_LEVEL_SEGMENT) {
segment = MAIN_SEGMENT;
}
@ -470,9 +470,9 @@ Val* Compiler::compile_float(const goos::Object& code, Env* env) {
*/
Val* Compiler::compile_float(float value, Env* env, int seg) {
auto obj = std::make_unique<StaticFloat>(value, seg);
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto result = fe->alloc_val<FloatConstantVal>(m_ts.make_typespec("float"), obj.get());
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fie = env->file_env();
fie->add_static(std::move(obj));
return result;
}

View file

@ -47,7 +47,7 @@ Val* Compiler::compile_block(const goos::Object& form, const goos::Object& _rest
throw_compiler_error(form, "Block form has an empty or invalid body");
}
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
// create environment
auto block_env = fe->alloc_env<BlockEnv>(env, symbol_string(name));
@ -116,7 +116,7 @@ Val* Compiler::compile_return_from(const goos::Object& form, const goos::Object&
// evaluate expression to return
auto result = compile_error_guard(value_expression, env);
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
// find block to return from
auto block = dynamic_cast<BlockEnv*>(env->find_block(block_name));
@ -163,7 +163,7 @@ Val* Compiler::compile_label(const goos::Object& form, const goos::Object& rest,
// make a label pointing to the end of the current function env. safe because we'll always add
// a terminating "null" instruction at the end.
auto func_env = get_parent_env_of_type<FunctionEnv>(env);
auto func_env = env->function_env();
labels[label_name] = Label(func_env, func_env->code().size());
return get_none();
}
@ -182,7 +182,7 @@ Val* Compiler::compile_goto(const goos::Object& form, const goos::Object& rest,
// add this goto to the list of gotos to resolve after the function is done.
// it's safe to have this reference, as the FunctionEnv also owns the goto.
get_parent_env_of_type<FunctionEnv>(env)->unresolved_gotos.push_back({ir_goto.get(), label_name});
env->function_env()->unresolved_gotos.push_back({ir_goto.get(), label_name});
env->emit(std::move(ir_goto));
return get_none();
}

View file

@ -49,7 +49,7 @@ Val* Compiler::compile_seval(const goos::Object& form, const goos::Object& rest,
(void)env;
try {
for_each_in_list(rest, [&](const goos::Object& o) {
m_goos.eval_with_rewind(o, m_goos.global_environment.as_env());
m_goos.eval_with_rewind(o, m_goos.global_environment.as_env_ptr());
});
} catch (std::runtime_error& e) {
throw_compiler_error(form, "Error while evaluating GOOS: {}", e.what());
@ -398,7 +398,7 @@ std::string Compiler::make_symbol_info_description(const SymbolInfo& info) {
case SymbolInfo::Kind::CONSTANT:
return fmt::format(
"[Constant] Name: {} Value: {} Defined: {}", info.name(),
m_global_constants.at(m_goos.reader.symbolTable.intern(info.name())).print(),
m_global_constants.at(m_goos.reader.symbolTable.intern_ptr(info.name())).print(),
m_goos.reader.db.get_info_for(info.src_form()));
case SymbolInfo::Kind::FUNCTION:
return fmt::format("[Function] Name: {} Defined: {}", info.name(),

View file

@ -125,7 +125,7 @@ Val* Compiler::compile_condition_as_bool(const goos::Object& form,
(void)rest;
auto c = compile_condition(form, env, true);
auto result = compile_get_sym_obj("#f", env)->to_gpr(env); // todo - can be optimized.
Label label(get_parent_env_of_type<FunctionEnv>(env), -5);
Label label(env->function_env(), -5);
auto branch_ir = std::make_unique<IR_ConditionalBranch>(c, label);
auto branch_ir_ref = branch_ir.get();
env->emit(std::move(branch_ir));
@ -155,7 +155,7 @@ Val* Compiler::compile_when_goto(const goos::Object& form, const goos::Object& _
// compile as condition (will set flags register with a cmp instruction)
auto condition = compile_condition(condition_code, env, false);
auto branch = std::make_unique<IR_ConditionalBranch>(condition, Label());
get_parent_env_of_type<FunctionEnv>(env)->unresolved_cond_gotos.push_back({branch.get(), label});
env->function_env()->unresolved_cond_gotos.push_back({branch.get(), label});
env->emit(std::move(branch));
return get_none();
}
@ -169,7 +169,7 @@ Val* Compiler::compile_when_goto(const goos::Object& form, const goos::Object& _
Val* Compiler::compile_cond(const goos::Object& form, const goos::Object& rest, Env* env) {
auto result = env->make_gpr(m_ts.make_typespec("object"));
auto fenv = get_parent_env_of_type<FunctionEnv>(env);
auto fenv = env->function_env();
auto end_label = fenv->alloc_unnamed_label();
end_label->func = fenv;
end_label->idx = -3; // placeholder
@ -276,7 +276,7 @@ Val* Compiler::compile_and_or(const goos::Object& form, const goos::Object& rest
}
auto result = env->make_gpr(m_ts.make_typespec("object")); // temp type for now.
auto fenv = get_parent_env_of_type<FunctionEnv>(env);
auto fenv = env->function_env();
auto end_label = fenv->alloc_unnamed_label();
end_label->func = fenv;
end_label->idx = -4; // placeholder

View file

@ -24,7 +24,7 @@ Val* Compiler::compile_define(const goos::Object& form, const goos::Object& rest
sym.print(), global_constant->second.print());
}
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto sym_val = fe->alloc_val<SymbolVal>(symbol_string(sym), m_ts.make_typespec("symbol"));
auto compiled_val = compile_error_guard(val, env);
auto as_lambda = dynamic_cast<LambdaVal*>(compiled_val);
@ -137,7 +137,7 @@ void Compiler::set_bitfield(const goos::Object& form, BitFieldVal* dst, RegVal*
return;
}
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
// first, get the value we want to modify:
auto original_original = dst->parent()->to_gpr(env);
@ -151,7 +151,7 @@ void Compiler::set_bitfield(const goos::Object& form, BitFieldVal* dst, RegVal*
}
void Compiler::set_bitfield_128(const goos::Object& form, BitFieldVal* dst, RegVal* src, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
bool get_top = dst->offset() >= 64;
@ -220,7 +220,7 @@ Val* Compiler::do_set(const goos::Object& form, Val* dest, RegVal* src_in_reg, V
// we want to allow setting a 128-bit field from a 64-bit variable.
if (as_mem_deref->info.size == 16) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto src_128 = fe->make_ireg(src_in_reg->type(), RegClass::INT_128);
env->emit_ir<IR_RegSet>(src_128, src_in_reg);
src_in_reg = src_128;
@ -229,7 +229,7 @@ Val* Compiler::do_set(const goos::Object& form, Val* dest, RegVal* src_in_reg, V
// we want to allow setting a smaller thing from a 128-bit variable
if (as_mem_deref->info.size != 16 && (src_in_reg->ireg().reg_class == RegClass::VECTOR_FLOAT ||
src_in_reg->ireg().reg_class == RegClass::INT_128)) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto src_gpr = fe->make_ireg(src_in_reg->type(), RegClass::GPR_64);
env->emit_ir<IR_RegSet>(src_gpr, src_in_reg);
src_in_reg = src_gpr;
@ -237,7 +237,7 @@ Val* Compiler::do_set(const goos::Object& form, Val* dest, RegVal* src_in_reg, V
// we want to allow setting a 64-bit place to a float
if (as_mem_deref->info.size == 8 && src_in_reg->ireg().reg_class == RegClass::FLOAT) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto src_gpr = fe->make_ireg(src_in_reg->type(), RegClass::GPR_64);
env->emit_ir<IR_RegSet>(src_gpr, src_in_reg);
src_in_reg = src_gpr;

View file

@ -8,17 +8,6 @@
#include "third-party/fmt/core.h"
namespace {
/*!
* Get the preference to inline of the given environment.
*/
bool get_inline_preference(Env* env) {
auto ile = get_parent_env_of_type<WithInlineEnv>(env);
if (ile) {
return ile->inline_preference;
} else {
return false;
}
}
/*!
* Hacky function to seek past arguments to get a goos::Object containing the body of a lambda.
@ -61,12 +50,12 @@ Val* Compiler::compile_inline(const goos::Object& form, const goos::Object& rest
throw_compiler_error(form,
"Cannot inline {} because inlining of this function was disallowed.");
}
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
return fe->alloc_val<InlinedLambdaVal>(kv->second->type(), kv->second);
}
Val* Compiler::compile_local_vars(const goos::Object& form, const goos::Object& rest, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
for_each_in_list(rest, [&](const goos::Object& o) {
if (o.is_symbol()) {
@ -112,8 +101,8 @@ Val* Compiler::compile_local_vars(const goos::Object& form, const goos::Object&
* confusing special cases...
*/
Val* Compiler::compile_lambda(const goos::Object& form, const goos::Object& rest, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto obj_env = get_parent_env_of_type<FileEnv>(env);
auto fe = env->function_env();
auto obj_env = env->file_env();
auto args = get_va(form, rest);
if (args.unnamed.empty() || !args.unnamed.front().is_list() ||
!args.only_contains_named({"name", "inline-only", "segment", "behavior"})) {
@ -329,7 +318,7 @@ Val* Compiler::compile_lambda(const goos::Object& form, const goos::Object& rest
*/
Val* Compiler::compile_function_or_method_call(const goos::Object& form, Env* env) {
goos::Object f = form;
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto args = get_va(form, form);
auto uneval_head = args.unnamed.at(0);
@ -347,9 +336,8 @@ Val* Compiler::compile_function_or_method_call(const goos::Object& form, Env* en
if (kv->second->func ==
nullptr || // only-inline, we must inline it as there is no code generated for it
kv->second->func->settings
.inline_by_default || // inline when possible, so we should inline
(kv->second->func->settings.allow_inline &&
get_inline_preference(env))) { // inline is allowed, and we prefer it locally
.inline_by_default) { // inline when possible, so we should inline
auto_inline = true;
head = kv->second;
}
@ -588,7 +576,7 @@ Val* Compiler::compile_real_function_call(const goos::Object& form,
const std::vector<RegVal*>& args,
Env* env,
const std::string& method_type_name) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
fe->require_aligned_stack();
TypeSpec return_ts;
if (function->type().arg_count() == 0) {
@ -660,7 +648,7 @@ Val* Compiler::compile_real_function_call(const goos::Object& form,
* Currently there aren't many useful settings, but more may be added in the future.
*/
Val* Compiler::compile_declare(const goos::Object& form, const goos::Object& rest, Env* env) {
auto& settings = get_parent_env_of_type<DeclareEnv>(env)->settings;
auto& settings = get_parent_env_of_type_slow<DeclareEnv>(env)->settings;
if (settings.is_set) {
throw_compiler_error(form, "Function cannot have multiple declares");
@ -696,7 +684,7 @@ Val* Compiler::compile_declare(const goos::Object& form, const goos::Object& res
settings.inline_by_default = false;
settings.save_code = true;
} else if (first.as_symbol()->name == "asm-func") {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
fe->is_asm_func = true;
if (!rrest->is_pair()) {
throw_compiler_error(
@ -716,7 +704,7 @@ Val* Compiler::compile_declare(const goos::Object& form, const goos::Object& res
if (!rrest->is_empty_list()) {
throw_compiler_error(first, "Invalid allow-saved-regs declare");
}
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
fe->asm_func_saved_regs = true;
} else {

View file

@ -1,5 +1,6 @@
#include "goalc/compiler/Compiler.h"
#include "third-party/fmt/core.h"
#include "common/goos/PrettyPrinter.h"
using namespace goos;
@ -9,7 +10,7 @@ using namespace goos;
bool Compiler::try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest) {
Object macro_obj;
bool got_macro = false;
if (m_goos.eval_symbol(macro_name, m_goos.goal_env.as_env(), &macro_obj) &&
if (m_goos.eval_symbol(macro_name, m_goos.goal_env.as_env_ptr(), &macro_obj) &&
macro_obj.is_macro()) {
got_macro = true;
}
@ -26,20 +27,60 @@ bool Compiler::try_getting_macro_from_goos(const goos::Object& macro_name, goos:
Val* Compiler::compile_goos_macro(const goos::Object& o,
const goos::Object& macro_obj,
const goos::Object& rest,
const goos::Object& name,
Env* env) {
auto macro = macro_obj.as_macro();
Arguments args = m_goos.get_args(o, rest, macro->args);
auto mac_env_obj = EnvironmentObject::make_new();
auto mac_env = mac_env_obj.as_env();
mac_env->parent_env = m_goos.global_environment.as_env();
auto mac_env = mac_env_obj.as_env_ptr();
mac_env->parent_env = m_goos.global_environment.as_env_ptr();
m_goos.set_args_in_env(o, args, macro->args, mac_env);
m_goos.goal_to_goos.enclosing_method_type =
get_parent_env_of_type<FunctionEnv>(env)->method_of_type_name;
m_goos.goal_to_goos.enclosing_method_type = env->function_env()->method_of_type_name;
auto goos_result = m_goos.eval_list_return_last(macro->body, macro->body, mac_env);
// make the macro expanded form point to the source where the macro was used for error messages.
m_goos.reader.db.inherit_info(o, goos_result);
// m_goos.reader.db.inherit_info(o, goos_result);
m_goos.goal_to_goos.reset();
return compile_error_guard(goos_result, env);
auto compile_env_for_macro =
env->function_env()->alloc_env<MacroExpandEnv>(env, name.as_symbol(), macro->body, o);
try {
return compile(goos_result, compile_env_for_macro);
} catch (CompilerException& ce) {
if (ce.print_err_stack) {
bool good_info = false;
auto info = m_goos.reader.db.get_info_for(o, &good_info);
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Code:\n");
fmt::print("{}\n", pretty_print::to_string(goos_result, 120));
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "From macro: ");
fmt::print(fg(fmt::color::orange), "{}\n", name.print());
if (good_info) {
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Used in:\n");
fmt::print("{}\n", info);
ce.print_err_stack = false;
}
std::string line(80, '-');
line.push_back('\n');
fmt::print(line);
}
throw;
} catch (std::runtime_error& e) {
bool good_info = false;
auto info = m_goos.reader.db.get_info_for(o, &good_info);
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Code:\n");
fmt::print("{}\n", pretty_print::to_string(goos_result, 120));
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "From macro: ");
fmt::print(fg(fmt::color::orange), "{}\n", name.print());
if (good_info) {
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Used in:\n");
fmt::print("{}\n", info);
}
std::string line(80, '-');
line.push_back('\n');
fmt::print(line);
throw;
}
}
/*!
@ -60,8 +101,8 @@ Val* Compiler::compile_gscond(const goos::Object& form, const goos::Object& rest
}
// check condition:
Object condition_result =
m_goos.eval_with_rewind(current_case.as_pair()->car, m_goos.global_environment.as_env());
Object condition_result = m_goos.eval_with_rewind(current_case.as_pair()->car,
m_goos.global_environment.as_env_ptr());
if (m_goos.truthy(condition_result)) {
if (current_case.as_pair()->cdr.is_empty_list()) {
return get_none();
@ -176,7 +217,7 @@ Val* Compiler::compile_mlet(const goos::Object& form, const goos::Object& rest,
auto defs = pair_car(rest);
auto body = pair_cdr(rest);
auto fenv = get_parent_env_of_type<FunctionEnv>(env);
auto fenv = env->function_env();
auto menv = fenv->alloc_env<SymbolMacroEnv>(env);
for_each_in_list(defs, [&](const goos::Object& o) {
@ -214,13 +255,13 @@ bool Compiler::expand_macro_once(const goos::Object& src, goos::Object* out, Env
auto macro = macro_obj.as_macro();
Arguments args = m_goos.get_args(src, rest, macro->args);
auto mac_env_obj = EnvironmentObject::make_new();
auto mac_env = mac_env_obj.as_env();
mac_env->parent_env = m_goos.global_environment.as_env();
auto mac_env = mac_env_obj.as_env_ptr();
mac_env->parent_env = m_goos.global_environment.as_env_ptr();
m_goos.set_args_in_env(src, args, macro->args, mac_env);
auto goos_result = m_goos.eval_list_return_last(macro->body, macro->body, mac_env);
// make the macro expanded form point to the source where the macro was used for error messages.
m_goos.reader.db.inherit_info(src, goos_result);
// m_goos.reader.db.inherit_info(src, goos_result);
*out = goos_result;
return true;

View file

@ -43,7 +43,7 @@ Val* Compiler::number_to_integer(const goos::Object& form, Val* in, Env* env) {
if (is_binteger(ts)) {
throw_compiler_error(form, "Cannot convert {} (a binteger) to an integer yet.", in->print());
} else if (is_float(ts)) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto result = fe->make_gpr(m_ts.make_typespec("int"));
env->emit(std::make_unique<IR_FloatToInt>(result, in->to_fpr(env)));
return result;
@ -62,7 +62,7 @@ Val* Compiler::number_to_binteger(const goos::Object& form, Val* in, Env* env) {
} else if (is_float(ts)) {
throw_compiler_error(form, "Cannot convert {} (a float) to an integer yet.", in->print());
} else if (is_integer(ts)) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
RegVal* input = in->to_reg(env);
auto sa = fe->make_gpr(m_ts.make_typespec("int"));
env->emit(std::make_unique<IR_LoadConstant64>(sa, 3));
@ -82,7 +82,7 @@ Val* Compiler::number_to_float(const goos::Object& form, Val* in, Env* env) {
} else if (is_float(ts)) {
return in;
} else if (is_integer(ts)) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto result = fe->make_fpr(m_ts.make_typespec("float"));
env->emit(std::make_unique<IR_IntToFloat>(result, in->to_gpr(env)));
return result;
@ -339,8 +339,7 @@ Val* Compiler::compile_sub(const goos::Object& form, const goos::Object& rest, E
case MATH_FLOAT:
if (args.unnamed.size() == 1) {
auto result =
compile_float(0, env, get_parent_env_of_type<FunctionEnv>(env)->segment)->to_fpr(env);
auto result = compile_float(0, env, env->function_env()->segment)->to_fpr(env);
env->emit(std::make_unique<IR_FloatMath>(
FloatMathKind::SUB_SS, result,
to_math_type(form, compile_error_guard(args.unnamed.at(0), env), math_type, env)
@ -382,7 +381,7 @@ Val* Compiler::compile_div(const goos::Object& form, const goos::Object& rest, E
auto math_type = get_math_mode(first_type);
switch (math_type) {
case MATH_INT: {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto first_thing = first_val->to_gpr(env);
auto result = env->make_gpr(first_type);
env->emit(std::make_unique<IR_RegSet>(result, first_thing));
@ -458,7 +457,7 @@ Val* Compiler::compile_variable_shift(const goos::Object& form,
env->emit(std::make_unique<IR_RegSet>(result, in));
env->emit(std::make_unique<IR_RegSet>(sa_in, sa));
auto fenv = get_parent_env_of_type<FunctionEnv>(env);
auto fenv = env->function_env();
IRegConstraint sa_con;
sa_con.ireg = sa_in->ireg();
@ -550,7 +549,7 @@ Val* Compiler::compile_mod(const goos::Object& form, const goos::Object& rest, E
va_check(form, args, {{}, {}}, {});
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env);
auto fenv = get_parent_env_of_type<FunctionEnv>(env);
auto fenv = env->function_env();
if (get_math_mode(first->type()) != MathMode::MATH_INT ||
get_math_mode(second->type()) != MathMode::MATH_INT) {

View file

@ -73,8 +73,7 @@ Val* Compiler::compile_define_state_hook(const goos::Object& form,
state_name, existing_var->second.print(), state_type.print());
}
m_symbol_types[state_name] = state_type;
auto sym_val =
get_parent_env_of_type<FunctionEnv>(env)->alloc_val<SymbolVal>(state_name, state_type);
auto sym_val = env->function_env()->alloc_val<SymbolVal>(state_name, state_type);
env->emit(std::make_unique<IR_SetSymbolValue>(sym_val, state_object));
return get_none();

View file

@ -265,7 +265,7 @@ StaticResult Compiler::compile_new_static_structure(const goos::Object& form,
obj->data.resize(type_info->get_size_in_memory());
compile_static_structure_inline(form, type, _field_defs, obj.get(), 0, env);
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fie = env->file_env();
auto result = StaticResult::make_structure_reference(obj.get(), type);
fie->add_static(std::move(obj));
return result;
@ -444,7 +444,7 @@ Val* Compiler::compile_bitfield_definition(const goos::Object& form,
if (use_128) {
auto integer_lo = compile_integer(constant_integer_part.lo, env)->to_gpr(env);
auto integer_hi = compile_integer(constant_integer_part.hi, env)->to_gpr(env);
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto rv = fe->make_ireg(type, RegClass::INT_128);
auto xmm_temp = fe->make_ireg(TypeSpec("object"), RegClass::INT_128);
@ -529,8 +529,8 @@ Val* Compiler::compile_bitfield_definition(const goos::Object& form,
* - Strings
*/
StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form, Env* env) {
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fie = env->file_env();
auto fe = env->function_env();
auto segment = fe->segment;
if (segment == TOP_LEVEL_SEGMENT) {
segment = MAIN_SEGMENT;
@ -586,8 +586,8 @@ StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form
*/
StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env* env) {
auto form = expand_macro_completely(form_before_macro, env);
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fie = env->file_env();
auto fe = env->function_env();
auto segment = fe->segment;
if (segment == TOP_LEVEL_SEGMENT) {
segment = MAIN_SEGMENT;
@ -804,7 +804,7 @@ void Compiler::fill_static_array_inline(const goos::Object& form,
StaticResult Compiler::fill_static_array(const goos::Object& form,
const goos::Object& rest,
Env* env) {
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fie = env->file_env();
// (new 'static 'boxed-array ...)
// get all arguments now
auto args = get_list_as_vector(rest);
@ -843,7 +843,7 @@ StaticResult Compiler::fill_static_array(const goos::Object& form,
StaticResult Compiler::fill_static_boxed_array(const goos::Object& form,
const goos::Object& rest,
Env* env) {
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fie = env->file_env();
// (new 'static 'boxed-array ...)
// get all arguments now
// auto args = get_list_as_vector(rest);
@ -975,7 +975,7 @@ void Compiler::fill_static_inline_array_inline(const goos::Object& form,
StaticResult Compiler::fill_static_inline_array(const goos::Object& form,
const goos::Object& rest,
Env* env) {
auto fie = get_parent_env_of_type<FileEnv>(env);
auto fie = env->file_env();
// (new 'static 'inline-array ...)
// get all arguments now
auto args = get_list_as_vector(rest);
@ -1011,7 +1011,7 @@ Val* Compiler::compile_static_pair(const goos::Object& form, Env* env) {
assert(form.is_pair()); // (quote PAIR)
auto result = compile_static_no_eval_for_pairs(form, env);
assert(result.is_reference());
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto static_result = fe->alloc_val<StaticVal>(result.reference(), result.typespec());
return static_result;
}
@ -1020,7 +1020,7 @@ Val* Compiler::compile_new_static_structure_or_basic(const goos::Object& form,
const TypeSpec& type,
const goos::Object& field_defs,
Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto sr = compile_new_static_structure(form, type, field_defs, env);
auto result = fe->alloc_val<StaticVal>(sr.reference(), type);
return result;

View file

@ -33,7 +33,7 @@ RegVal* Compiler::compile_get_method_of_type(const goos::Object& /*form*/,
auto offset_of_method = get_offset_of_method(info.id);
assert(type->type() == TypeSpec("type"));
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
MemLoadInfo load_info;
load_info.sign_extend = false;
@ -87,7 +87,7 @@ RegVal* Compiler::compile_get_method_of_object(const goos::Object& form,
}
method_info.type = method_info.type.substitute_for_method_call(compile_time_type.base_type());
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
RegVal* runtime_type = nullptr;
if (m_ts.should_use_virtual_methods(compile_time_type, method_info.id)) {
@ -126,8 +126,7 @@ Val* Compiler::compile_format_string(const goos::Object& form,
const std::string& out_stream) {
// Add first two format args
args.insert(args.begin(),
compile_string(fmt_template, env, get_parent_env_of_type<FunctionEnv>(env)->segment)
->to_gpr(env));
compile_string(fmt_template, env, env->function_env()->segment)->to_gpr(env));
args.insert(args.begin(), compile_get_sym_obj(out_stream, env)->to_gpr(env));
// generate code in the method_env
@ -268,10 +267,10 @@ Val* Compiler::generate_inspector_for_structure_type(const goos::Object& form,
emitter::gRegInfo.get_gpr_ret_reg());
// add this function to the object file
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto method = fe->alloc_val<LambdaVal>(m_ts.make_typespec("function"));
method->func = method_env.get();
auto obj_env_inspect = get_parent_env_of_type<FileEnv>(method_env.get());
auto obj_env_inspect = method_env->file_env();
obj_env_inspect->add_function(std::move(method_env));
// call method-set!
@ -339,10 +338,10 @@ Val* Compiler::generate_inspector_for_bitfield_type(const goos::Object& form,
}
// add this function to the object file
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto method = fe->alloc_val<LambdaVal>(m_ts.make_typespec("function"));
method->func = method_env.get();
auto obj_env_inspect = get_parent_env_of_type<FileEnv>(method_env.get());
auto obj_env_inspect = method_env->file_env();
obj_env_inspect->add_function(std::move(method_env));
// call method-set!
@ -407,7 +406,7 @@ Val* Compiler::compile_deftype(const goos::Object& form, const goos::Object& res
* Compile a (defmethod ...) form
*/
Val* Compiler::compile_defmethod(const goos::Object& form, const goos::Object& _rest, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto* rest = &_rest;
auto& method_name = pair_car(*rest);
@ -576,7 +575,7 @@ Val* Compiler::compile_defmethod(const goos::Object& form, const goos::Object& _
new_func_env->emit(std::make_unique<IR_Null>());
new_func_env->finish();
auto obj_env = get_parent_env_of_type<FileEnv>(new_func_env.get());
auto obj_env = new_func_env->file_env();
assert(obj_env);
if (new_func_env->settings.save_code) {
obj_env->add_function(std::move(new_func_env));
@ -600,7 +599,7 @@ Val* Compiler::get_field_of_structure(const StructureType* type,
Val* object,
const std::string& field_name,
Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
Val* result = nullptr;
int offset = -type->get_offset();
auto field = m_ts.lookup_field_info(type->get_name(), field_name);
@ -630,7 +629,7 @@ Val* Compiler::get_field_of_bitfield(const BitFieldType* type,
Val* object,
const std::string& field_name,
Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
Val* result = nullptr;
auto bitfield_info = m_ts.lookup_bitfield_info(type->get_name(), field_name);
result = fe->alloc_val<BitFieldVal>(bitfield_info.result_type, object, bitfield_info.offset,
@ -653,7 +652,7 @@ Val* Compiler::get_field_of_bitfield(const BitFieldType* type,
* location. Otherwise set! or & won't work.
*/
Val* Compiler::compile_deref(const goos::Object& form, const goos::Object& _rest, Env* env) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
if (_rest.is_empty_list()) {
throw_compiler_error(form, "-> must get at least one argument");
}
@ -859,7 +858,7 @@ Val* Compiler::compile_the_as(const goos::Object& form, const goos::Object& rest
va_check(form, args, {{}, {}}, {});
auto desired_ts = parse_typespec(args.unnamed.at(0));
auto base = compile_error_guard(args.unnamed.at(1), env);
auto result = get_parent_env_of_type<FunctionEnv>(env)->alloc_val<AliasVal>(desired_ts, base);
auto result = env->function_env()->alloc_val<AliasVal>(desired_ts, base);
if (base->settable()) {
result->mark_as_settable();
}
@ -888,7 +887,7 @@ Val* Compiler::compile_the(const goos::Object& form, const goos::Object& rest, E
result->set_type(desired_ts);
return result;
} else {
result = get_parent_env_of_type<FunctionEnv>(env)->alloc_val<AliasVal>(desired_ts, base);
result = env->function_env()->alloc_val<AliasVal>(desired_ts, base);
return result;
}
}
@ -898,7 +897,7 @@ Val* Compiler::compile_the(const goos::Object& form, const goos::Object& rest, E
}
}
auto result = get_parent_env_of_type<FunctionEnv>(env)->alloc_val<AliasVal>(desired_ts, base);
auto result = env->function_env()->alloc_val<AliasVal>(desired_ts, base);
if (base->settable()) {
result->mark_as_settable();
}
@ -1020,7 +1019,7 @@ Val* Compiler::compile_static_new(const goos::Object& form,
if (unquoted.is_symbol() &&
(unquoted.as_symbol()->name == "boxed-array" || unquoted.as_symbol()->name == "array" ||
unquoted.as_symbol()->name == "inline-array")) {
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto sr = compile_static(form, env);
auto result = fe->alloc_val<StaticVal>(sr.reference(), sr.typespec());
return result;
@ -1045,7 +1044,7 @@ Val* Compiler::compile_stack_new(const goos::Object& form,
Env* env,
bool call_constructor) {
auto type_of_object = parse_typespec(unquote(type));
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
if (type_of_object == TypeSpec("inline-array") || type_of_object == TypeSpec("array")) {
if (call_constructor) {
throw_compiler_error(form, "Constructing stack arrays is not yet supported");
@ -1166,7 +1165,7 @@ Val* Compiler::compile_new(const goos::Object& form, const goos::Object& _rest,
Val* Compiler::compile_car(const goos::Object& form, const goos::Object& rest, Env* env) {
auto args = get_va(form, rest);
va_check(form, args, {{}}, {});
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto pair = compile_error_guard(args.unnamed.at(0), env);
if (pair->type() != m_ts.make_typespec("object")) {
typecheck(form, m_ts.make_typespec("pair"), pair->type(), "Type of argument to car");
@ -1179,7 +1178,7 @@ Val* Compiler::compile_car(const goos::Object& form, const goos::Object& rest, E
Val* Compiler::compile_cdr(const goos::Object& form, const goos::Object& rest, Env* env) {
auto args = get_va(form, rest);
va_check(form, args, {{}}, {});
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto fe = env->function_env();
auto pair = compile_error_guard(args.unnamed.at(0), env);
if (pair->type() != m_ts.make_typespec("object")) {
typecheck(form, m_ts.make_typespec("pair"), pair->type(), "Type of argument to cdr");

View file

@ -65,7 +65,7 @@ void MakeSystem::load_project_file(const std::string& file_path) {
// read the file
auto data = m_goos.reader.read_from_file({file_path});
// interpret it, which will call various handlers.
m_goos.eval(data, m_goos.global_environment.as_env());
m_goos.eval(data, m_goos.global_environment.as_env_ptr());
}
goos::Object MakeSystem::handle_defstep(const goos::Object& form,

View file

@ -19,7 +19,7 @@
class IRegSet {
public:
IRegSet() = default;
IRegSet() { m_data.reserve(4); }
/*!
* Add the given ireg to the set.

View file

@ -11,7 +11,7 @@ using namespace goos;
namespace {
// helper to evaluate a string as a goos expression.
std::string e(Interpreter& interp, const std::string& in) {
return interp.eval(interp.reader.read_from_string(in), interp.global_environment.as_env())
return interp.eval(interp.reader.read_from_string(in), interp.global_environment.as_env_ptr())
.print();
}
} // namespace

View file

@ -349,8 +349,6 @@ TEST(GoosReader, TextDb) {
.as_pair()
->cdr.as_pair()
->car;
std::string expected = "text from " +
file_util::get_file_path({"test", "test_data", "test_reader_file0.gc"}) +
", line: 5\n(1 2 3 4)\n";
std::string expected = "test/test_data/test_reader_file0.gc, line: 5\n(1 2 3 4)\n ^\n";
EXPECT_EQ(expected, reader.db.get_info_for(result));
}