mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
Compiler performance improvements and error clean-up (#782)
* compiler cleanup and error improvement * fix test
This commit is contained in:
parent
e7b9ad5801
commit
7a5562106e
|
@ -122,14 +122,14 @@ void Interpreter::disable_printfs() {
|
||||||
*/
|
*/
|
||||||
void Interpreter::load_goos_library() {
|
void Interpreter::load_goos_library() {
|
||||||
auto cmd = "(load-file \"goal_src/goos-lib.gs\")";
|
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.
|
* 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) {
|
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);
|
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.
|
* Display the REPL, which will run until the user executes exit.
|
||||||
*/
|
*/
|
||||||
|
@ -152,7 +156,7 @@ void Interpreter::execute_repl(ReplWrapper& repl) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// evaluate
|
// evaluate
|
||||||
Object evald = eval_with_rewind(*obj, global_environment.as_env());
|
Object evald = eval_with_rewind(*obj, global_environment.as_env_ptr());
|
||||||
// print
|
// print
|
||||||
printf("%s\n", evald.print().c_str());
|
printf("%s\n", evald.print().c_str());
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
|
@ -489,7 +493,7 @@ bool try_symbol_lookup(const Object& sym,
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop up envs until we find it.
|
// loop up envs until we find it.
|
||||||
std::shared_ptr<EnvironmentObject> search_env = env;
|
EnvironmentObject* search_env = env.get();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto kv = search_env->vars.find(sym.as_symbol());
|
auto kv = search_env->vars.find(sym.as_symbol());
|
||||||
if (kv != search_env->vars.end()) {
|
if (kv != search_env->vars.end()) {
|
||||||
|
@ -497,7 +501,7 @@ bool try_symbol_lookup(const Object& sym,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pe = search_env->parent_env;
|
auto pe = search_env->parent_env.get();
|
||||||
if (pe) {
|
if (pe) {
|
||||||
search_env = pe;
|
search_env = pe;
|
||||||
} else {
|
} 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);
|
Arguments args = get_args(obj, rest, macro->args);
|
||||||
|
|
||||||
auto mac_env_obj = EnvironmentObject::make_new();
|
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
|
mac_env->parent_env = env; // not 100% clear that this is right
|
||||||
set_args_in_env(obj, args, macro->args, mac_env);
|
set_args_in_env(obj, args, macro->args, mac_env);
|
||||||
// expand the macro!
|
// 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);
|
Arguments args = get_args(obj, rest, lam->args);
|
||||||
eval_args(&args, env);
|
eval_args(&args, env);
|
||||||
auto lam_env_obj = EnvironmentObject::make_new();
|
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;
|
lam_env->parent_env = lam->parent_env;
|
||||||
set_args_in_env(obj, args, lam->args, lam_env);
|
set_args_in_env(obj, args, lam->args, lam_env);
|
||||||
return eval_list_return_last(lam->body, lam->body, 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")) {
|
if (args.has_named("env")) {
|
||||||
auto result = eval_with_rewind(args.get_named("env"), env);
|
auto result = eval_with_rewind(args.get_named("env"), env);
|
||||||
expect_env(form, result);
|
expect_env(form, result);
|
||||||
define_env = result.as_env();
|
define_env = result.as_env_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object value = eval_with_rewind(args.unnamed[1], env);
|
Object value = eval_with_rewind(args.unnamed[1], env);
|
||||||
|
@ -1018,7 +1022,7 @@ Object Interpreter::eval_load_file(const Object& form,
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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) {
|
} catch (std::runtime_error& e) {
|
||||||
throw_eval_error(form, std::string("eval error inside of load-file:\n") + e.what());
|
throw_eval_error(form, std::string("eval error inside of load-file:\n") + e.what());
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ class Interpreter {
|
||||||
void set_global_variable_to_symbol(const std::string& name, const std::string& value);
|
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 eval(Object obj, const std::shared_ptr<EnvironmentObject>& env);
|
||||||
Object intern(const std::string& name);
|
Object intern(const std::string& name);
|
||||||
|
HeapObject* intern_ptr(const std::string& name);
|
||||||
void disable_printfs();
|
void disable_printfs();
|
||||||
Object eval_symbol(const Object& sym, const std::shared_ptr<EnvironmentObject>& env);
|
Object eval_symbol(const Object& sym, const std::shared_ptr<EnvironmentObject>& env);
|
||||||
bool eval_symbol(const Object& sym,
|
bool eval_symbol(const Object& sym,
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
namespace goos {
|
namespace goos {
|
||||||
|
|
||||||
std::shared_ptr<EmptyListObject> gEmptyList = nullptr;
|
std::shared_ptr<EmptyListObject> gEmptyList = std::make_shared<EmptyListObject>();
|
||||||
std::shared_ptr<EmptyListObject>& get_empty_list() {
|
std::shared_ptr<EmptyListObject>& get_empty_list() {
|
||||||
return gEmptyList;
|
return gEmptyList;
|
||||||
}
|
}
|
||||||
|
@ -154,16 +154,57 @@ Object build_list(const std::vector<Object>& objects) {
|
||||||
return EmptyListObject::make_new();
|
return EmptyListObject::make_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object empty = EmptyListObject::make_new();
|
// this is by far the most expensive part of parsing, so this is done a bit carefully.
|
||||||
Object head = PairObject::make_new(objects[0], empty);
|
// we maintain a std::shared_ptr<PairObject> that represents the list, built from back to front.
|
||||||
Object last = head;
|
std::shared_ptr<PairObject> head =
|
||||||
|
std::make_shared<PairObject>(objects.back(), EmptyListObject::make_new());
|
||||||
|
|
||||||
for (std::size_t i = 1; i < objects.size(); i++) {
|
s64 idx = ((s64)objects.size()) - 2;
|
||||||
last.as_pair()->cdr = PairObject::make_new(objects[i], empty);
|
while (idx >= 0) {
|
||||||
last = last.as_pair()->cdr;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -167,6 +167,8 @@ class ArrayObject;
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<HeapObject> heap_obj = nullptr;
|
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 {
|
union {
|
||||||
IntegerObject integer_obj;
|
IntegerObject integer_obj;
|
||||||
|
@ -226,60 +228,14 @@ class Object {
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<PairObject> as_pair() const {
|
PairObject* as_pair() const;
|
||||||
if (type != ObjectType::PAIR) {
|
EnvironmentObject* as_env() const;
|
||||||
throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " +
|
std::shared_ptr<EnvironmentObject> as_env_ptr() const;
|
||||||
print());
|
SymbolObject* as_symbol() const;
|
||||||
}
|
StringObject* as_string() const;
|
||||||
return std::dynamic_pointer_cast<PairObject>(heap_obj);
|
LambdaObject* as_lambda() const;
|
||||||
}
|
MacroObject* as_macro() const;
|
||||||
|
ArrayObject* as_array() const;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
IntType& as_int() {
|
IntType& as_int() {
|
||||||
if (type != ObjectType::INTEGER) {
|
if (type != ObjectType::INTEGER) {
|
||||||
|
@ -346,9 +302,6 @@ class EmptyListObject : public HeapObject {
|
||||||
static Object make_new() {
|
static Object make_new() {
|
||||||
Object obj;
|
Object obj;
|
||||||
obj.type = ObjectType::EMPTY_LIST;
|
obj.type = ObjectType::EMPTY_LIST;
|
||||||
if (!get_empty_list()) {
|
|
||||||
get_empty_list() = std::make_shared<EmptyListObject>();
|
|
||||||
}
|
|
||||||
obj.heap_obj = get_empty_list();
|
obj.heap_obj = get_empty_list();
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -388,8 +341,8 @@ class SymbolObject : public HeapObject {
|
||||||
*/
|
*/
|
||||||
class SymbolTable {
|
class SymbolTable {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<SymbolObject> intern(const std::string& name) {
|
std::shared_ptr<HeapObject> intern(const std::string& name) {
|
||||||
auto kv = table.find(name);
|
const auto& kv = table.find(name);
|
||||||
if (kv == table.end()) {
|
if (kv == table.end()) {
|
||||||
auto iter = table.insert({name, std::make_shared<SymbolObject>(name)});
|
auto iter = table.insert({name, std::make_shared<SymbolObject>(name)});
|
||||||
return (*iter.first).second;
|
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;
|
~SymbolTable() = default;
|
||||||
|
|
||||||
private:
|
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 {
|
class StringObject : public HeapObject {
|
||||||
|
@ -426,9 +389,10 @@ class PairObject : public HeapObject {
|
||||||
public:
|
public:
|
||||||
Object car, cdr;
|
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;
|
Object obj;
|
||||||
obj.type = ObjectType::PAIR;
|
obj.type = ObjectType::PAIR;
|
||||||
obj.heap_obj = std::make_shared<PairObject>(a, b);
|
obj.heap_obj = std::make_shared<PairObject>(a, b);
|
||||||
|
@ -481,7 +445,10 @@ class EnvironmentObject : public HeapObject {
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::shared_ptr<EnvironmentObject> parent_env;
|
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;
|
EnvironmentObject() = default;
|
||||||
|
|
||||||
|
@ -641,5 +608,64 @@ class ArrayObject : public HeapObject {
|
||||||
};
|
};
|
||||||
|
|
||||||
Object build_list(const std::vector<Object>& objects);
|
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
|
} // namespace goos
|
||||||
|
|
|
@ -189,7 +189,17 @@ Object Reader::read_from_string(const std::string& str, bool add_top_level) {
|
||||||
* Read a file
|
* Read a file
|
||||||
*/
|
*/
|
||||||
Object Reader::read_from_file(const std::vector<std::string>& file_path) {
|
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);
|
db.insert(textFrag);
|
||||||
|
|
||||||
auto result = internal_read(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);
|
db.link(rv, ts.text, start_offset);
|
||||||
return rv;
|
return rv;
|
||||||
} else {
|
} else {
|
||||||
auto rv = build_list(objects);
|
auto rv = build_list(std::move(objects));
|
||||||
db.link(rv, ts.text, start_offset);
|
db.link(rv, ts.text, start_offset);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/util/FileUtil.h"
|
#include "common/util/FileUtil.h"
|
||||||
|
#include "third-party/fmt/core.h"
|
||||||
|
|
||||||
#include "TextDB.h"
|
#include "TextDB.h"
|
||||||
|
|
||||||
|
@ -64,6 +65,10 @@ int SourceText::get_line_idx(int offset) {
|
||||||
std::to_string(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.
|
* 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.
|
* Read text from a file.
|
||||||
*/
|
*/
|
||||||
FileText::FileText(std::string filename_) : filename(std::move(filename_)) {
|
FileText::FileText(const std::string& filename, const std::string& description_name)
|
||||||
text = file_util::read_text_file(filename);
|
: m_filename(filename), m_desc_name(description_name) {
|
||||||
|
text = file_util::read_text_file(m_filename);
|
||||||
build_offsets();
|
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.
|
* 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 TextDb::get_info_for(const std::shared_ptr<SourceText>& frag, int offset) const {
|
||||||
std::string result = "text from " + frag->get_description() +
|
int line_idx = frag->get_line_idx(offset);
|
||||||
", line: " + std::to_string(frag->get_line_idx(offset) + 1) + "\n";
|
std::string result = frag->get_description() + ", line: " + std::to_string(line_idx + 1) + "\n";
|
||||||
result += frag->get_line_containing_offset(offset) + "\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()) {
|
while (!children.empty()) {
|
||||||
auto top = children.back();
|
auto top = children.back();
|
||||||
children.pop_back();
|
children.pop_back();
|
||||||
if (map.find(top->heap_obj) == map.end()) {
|
if (map.insert({top->heap_obj, parent_kv->second}).second) {
|
||||||
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()->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 (top->as_pair()->cdr.is_pair()) {
|
}
|
||||||
children.push_back(&top->as_pair()->cdr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ class SourceText {
|
||||||
virtual std::string get_description() = 0;
|
virtual std::string get_description() = 0;
|
||||||
std::string get_line_containing_offset(int offset);
|
std::string get_line_containing_offset(int offset);
|
||||||
int get_line_idx(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?
|
// 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
|
// this should return true if the text source is specific enough so that they can find what they
|
||||||
// want
|
// want
|
||||||
|
@ -73,13 +74,14 @@ class ProgramString : public SourceText {
|
||||||
*/
|
*/
|
||||||
class FileText : public SourceText {
|
class FileText : public SourceText {
|
||||||
public:
|
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;
|
~FileText() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string filename;
|
std::string m_filename;
|
||||||
|
std::string m_desc_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextRef {
|
struct TextRef {
|
||||||
|
|
|
@ -170,10 +170,15 @@ Val* Compiler::compile_error_guard(const goos::Object& code, Env* env) {
|
||||||
obj_print += "...";
|
obj_print += "...";
|
||||||
}
|
}
|
||||||
bool term;
|
bool term;
|
||||||
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Location:\n");
|
auto loc_info = m_goos.reader.db.get_info_for(code, &term);
|
||||||
fmt::print(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(fg(fmt::color::yellow) | fmt::emphasis::bold, "Code:\n");
|
||||||
fmt::print("{}\n", obj_print);
|
fmt::print("{}\n", obj_print);
|
||||||
|
|
||||||
if (term) {
|
if (term) {
|
||||||
ce.print_err_stack = false;
|
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 = obj_print.substr(0, 80);
|
||||||
obj_print += "...";
|
obj_print += "...";
|
||||||
}
|
}
|
||||||
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Location:\n");
|
bool term;
|
||||||
fmt::print(m_goos.reader.db.get_info_for(code));
|
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(fg(fmt::color::yellow) | fmt::emphasis::bold, "Code:\n");
|
||||||
fmt::print("{}\n", obj_print);
|
fmt::print("{}\n", obj_print);
|
||||||
|
|
||||||
|
CompilerException ce("Compiler Exception");
|
||||||
|
if (term) {
|
||||||
|
ce.print_err_stack = false;
|
||||||
|
}
|
||||||
std::string line(80, '-');
|
std::string line(80, '-');
|
||||||
line.push_back('\n');
|
line.push_back('\n');
|
||||||
fmt::print(line);
|
fmt::print(line);
|
||||||
throw e;
|
throw ce;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +254,7 @@ void Compiler::color_object_file(FileEnv* env) {
|
||||||
// regalloc_result_2.num_spilled_vars);
|
// regalloc_result_2.num_spilled_vars);
|
||||||
}
|
}
|
||||||
num_spills_in_file += regalloc_result_2.num_spills;
|
num_spills_in_file += regalloc_result_2.num_spills;
|
||||||
f->set_allocations(regalloc_result_2);
|
f->set_allocations(std::move(regalloc_result_2));
|
||||||
} else {
|
} else {
|
||||||
fmt::print(
|
fmt::print(
|
||||||
"Warning: function {} failed register allocation with the v2 allocator. Falling back to "
|
"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);
|
auto regalloc_result = allocate_registers(input);
|
||||||
m_debug_stats.num_spills_v1 += regalloc_result.num_spills;
|
m_debug_stats.num_spills_v1 += regalloc_result.num_spills;
|
||||||
num_spills_in_file += regalloc_result.num_spills;
|
num_spills_in_file += regalloc_result.num_spills;
|
||||||
f->set_allocations(regalloc_result);
|
f->set_allocations(std::move(regalloc_result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,8 @@ class Compiler {
|
||||||
Debugger m_debugger;
|
Debugger m_debugger;
|
||||||
goos::Interpreter m_goos;
|
goos::Interpreter m_goos;
|
||||||
std::unordered_map<std::string, TypeSpec> m_symbol_types;
|
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<goos::HeapObject*, goos::Object> m_global_constants;
|
||||||
std::unordered_map<std::shared_ptr<goos::SymbolObject>, LambdaVal*> m_inlineable_functions;
|
std::unordered_map<goos::HeapObject*, LambdaVal*> m_inlineable_functions;
|
||||||
CompilerSettings m_settings;
|
CompilerSettings m_settings;
|
||||||
bool m_throw_on_define_extern_redefinition = false;
|
bool m_throw_on_define_extern_redefinition = false;
|
||||||
SymbolInfoMap m_symbol_info;
|
SymbolInfoMap m_symbol_info;
|
||||||
|
@ -109,6 +109,7 @@ class Compiler {
|
||||||
Val* compile_goos_macro(const goos::Object& o,
|
Val* compile_goos_macro(const goos::Object& o,
|
||||||
const goos::Object& macro_obj,
|
const goos::Object& macro_obj,
|
||||||
const goos::Object& rest,
|
const goos::Object& rest,
|
||||||
|
const goos::Object& name_symbol,
|
||||||
Env* env);
|
Env* env);
|
||||||
Val* compile_pair(const goos::Object& code, Env* env);
|
Val* compile_pair(const goos::Object& code, Env* env);
|
||||||
Val* compile_integer(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) {
|
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");
|
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "-- Compilation Error! --\n");
|
||||||
if (!str.empty() && str.back() == '\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 {
|
} 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");
|
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) {
|
void throw_compiler_error_no_code(const std::string& str, Args&&... args) {
|
||||||
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "-- Compilation Error! --\n");
|
fmt::print(fg(fmt::color::crimson) | fmt::emphasis::bold, "-- Compilation Error! --\n");
|
||||||
if (!str.empty() && str.back() == '\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 {
|
} 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");
|
fmt::print(fg(fmt::color::yellow) | fmt::emphasis::bold, "Form:\n");
|
||||||
|
|
|
@ -18,8 +18,8 @@ void Env::emit(std::unique_ptr<IR> ir) {
|
||||||
/*!
|
/*!
|
||||||
* Allocate an IRegister with the given type.
|
* Allocate an IRegister with the given type.
|
||||||
*/
|
*/
|
||||||
RegVal* Env::make_ireg(TypeSpec ts, RegClass reg_class) {
|
RegVal* Env::make_ireg(const TypeSpec& ts, RegClass reg_class) {
|
||||||
return m_parent->make_ireg(std::move(ts), 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
|
// 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.
|
// errors, or return that the items were not found.
|
||||||
|
|
||||||
GlobalEnv::GlobalEnv() : Env(nullptr) {}
|
GlobalEnv::GlobalEnv() : Env(EnvKind::OTHER_ENV, nullptr) {}
|
||||||
|
|
||||||
std::string GlobalEnv::print() {
|
std::string GlobalEnv::print() {
|
||||||
return "global-env";
|
return "global-env";
|
||||||
|
@ -81,7 +81,7 @@ void GlobalEnv::emit(std::unique_ptr<IR> ir) {
|
||||||
/*!
|
/*!
|
||||||
* Allocate an IRegister with the given type.
|
* 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)ts;
|
||||||
(void)reg_class;
|
(void)reg_class;
|
||||||
throw std::runtime_error("cannot alloc reg in GlobalEnv");
|
throw std::runtime_error("cannot alloc reg in GlobalEnv");
|
||||||
|
@ -136,7 +136,8 @@ void NoEmitEnv::emit(std::unique_ptr<IR> ir) {
|
||||||
// BlockEnv
|
// 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() {
|
std::string BlockEnv::print() {
|
||||||
return "block-" + name;
|
return "block-" + name;
|
||||||
|
@ -154,7 +155,8 @@ BlockEnv* BlockEnv::find_block(const std::string& block) {
|
||||||
// FileEnv
|
// 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() {
|
std::string FileEnv::print() {
|
||||||
return "file-" + m_name;
|
return "file-" + m_name;
|
||||||
|
@ -202,7 +204,7 @@ bool FileEnv::is_empty() {
|
||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
FunctionEnv::FunctionEnv(Env* parent, std::string name)
|
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() {
|
std::string FunctionEnv::print() {
|
||||||
return "function-" + m_name;
|
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;
|
IRegister ireg;
|
||||||
ireg.reg_class = reg_class;
|
ireg.reg_class = reg_class;
|
||||||
ireg.id = m_iregs.size();
|
ireg.id = m_iregs.size();
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
* manages the memory for stuff generated during compiling.
|
* manages the memory for stuff generated during compiling.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JAK_ENV_H
|
|
||||||
#define JAK_ENV_H
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -21,17 +18,22 @@
|
||||||
|
|
||||||
class FileEnv;
|
class FileEnv;
|
||||||
class BlockEnv;
|
class BlockEnv;
|
||||||
|
class FunctionEnv;
|
||||||
|
class SymbolMacroEnv;
|
||||||
|
class MacroExpandEnv;
|
||||||
class IR;
|
class IR;
|
||||||
|
|
||||||
|
enum class EnvKind { FILE_ENV, FUNCTION_ENV, SYMBOL_MACRO_ENV, MACRO_EXPAND_ENV, OTHER_ENV };
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Parent class for Env's
|
* Parent class for Env's
|
||||||
*/
|
*/
|
||||||
class Env {
|
class Env {
|
||||||
public:
|
public:
|
||||||
explicit Env(Env* parent) : m_parent(parent) {}
|
explicit Env(EnvKind kind, Env* parent);
|
||||||
virtual std::string print() = 0;
|
virtual std::string print() = 0;
|
||||||
virtual void emit(std::unique_ptr<IR> ir);
|
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 void constrain_reg(IRegConstraint constraint); // todo, remove!
|
||||||
virtual RegVal* lexical_lookup(goos::Object sym);
|
virtual RegVal* lexical_lookup(goos::Object sym);
|
||||||
virtual BlockEnv* find_block(const std::string& name);
|
virtual BlockEnv* find_block(const std::string& name);
|
||||||
|
@ -47,8 +49,22 @@ class Env {
|
||||||
emit(std::make_unique<IR_Type>(std::forward<Args>(args)...));
|
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:
|
protected:
|
||||||
|
EnvKind m_kind;
|
||||||
Env* m_parent = nullptr;
|
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();
|
GlobalEnv();
|
||||||
std::string print() override;
|
std::string print() override;
|
||||||
void emit(std::unique_ptr<IR> ir) 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;
|
void constrain_reg(IRegConstraint constraint) override;
|
||||||
RegVal* lexical_lookup(goos::Object sym) override;
|
RegVal* lexical_lookup(goos::Object sym) override;
|
||||||
BlockEnv* find_block(const std::string& name) override;
|
BlockEnv* find_block(const std::string& name) override;
|
||||||
|
@ -77,7 +93,7 @@ class GlobalEnv : public Env {
|
||||||
*/
|
*/
|
||||||
class NoEmitEnv : public Env {
|
class NoEmitEnv : public Env {
|
||||||
public:
|
public:
|
||||||
explicit NoEmitEnv(Env* parent) : Env(parent) {}
|
explicit NoEmitEnv(Env* parent) : Env(EnvKind::OTHER_ENV, parent) {}
|
||||||
std::string print() override;
|
std::string print() override;
|
||||||
void emit(std::unique_ptr<IR> ir) override;
|
void emit(std::unique_ptr<IR> ir) override;
|
||||||
~NoEmitEnv() = default;
|
~NoEmitEnv() = default;
|
||||||
|
@ -133,7 +149,7 @@ class FileEnv : public Env {
|
||||||
*/
|
*/
|
||||||
class DeclareEnv : public Env {
|
class DeclareEnv : public Env {
|
||||||
public:
|
public:
|
||||||
explicit DeclareEnv(Env* parent) : Env(parent) {}
|
explicit DeclareEnv(EnvKind kind, Env* parent) : Env(kind, parent) {}
|
||||||
virtual std::string print() = 0;
|
virtual std::string print() = 0;
|
||||||
~DeclareEnv() = default;
|
~DeclareEnv() = default;
|
||||||
|
|
||||||
|
@ -168,12 +184,12 @@ class FunctionEnv : public DeclareEnv {
|
||||||
void set_segment(int seg) { segment = seg; }
|
void set_segment(int seg) { segment = seg; }
|
||||||
void emit(std::unique_ptr<IR> ir) override;
|
void emit(std::unique_ptr<IR> ir) override;
|
||||||
void finish();
|
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; }
|
const std::vector<std::unique_ptr<IR>>& code() const { return m_code; }
|
||||||
int max_vars() const { return m_iregs.size(); }
|
int max_vars() const { return m_iregs.size(); }
|
||||||
const std::vector<IRegConstraint>& constraints() { return m_constraints; }
|
const std::vector<IRegConstraint>& constraints() { return m_constraints; }
|
||||||
void constrain(const IRegConstraint& c) { m_constraints.push_back(c); }
|
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;
|
RegVal* lexical_lookup(goos::Object sym) override;
|
||||||
const AllocationResult& alloc_result() { return m_regalloc_result; }
|
const AllocationResult& alloc_result() { return m_regalloc_result; }
|
||||||
bool needs_aligned_stack() const { return m_aligned_stack_required; }
|
bool needs_aligned_stack() const { return m_aligned_stack_required; }
|
||||||
|
@ -250,7 +266,7 @@ class BlockEnv : public Env {
|
||||||
|
|
||||||
class LexicalEnv : public DeclareEnv {
|
class LexicalEnv : public DeclareEnv {
|
||||||
public:
|
public:
|
||||||
explicit LexicalEnv(Env* parent) : DeclareEnv(parent) {}
|
explicit LexicalEnv(Env* parent) : DeclareEnv(EnvKind::OTHER_ENV, parent) {}
|
||||||
RegVal* lexical_lookup(goos::Object sym) override;
|
RegVal* lexical_lookup(goos::Object sym) override;
|
||||||
std::string print() override;
|
std::string print() override;
|
||||||
std::unordered_map<std::string, RegVal*> vars;
|
std::unordered_map<std::string, RegVal*> vars;
|
||||||
|
@ -258,7 +274,7 @@ class LexicalEnv : public DeclareEnv {
|
||||||
|
|
||||||
class LabelEnv : public Env {
|
class LabelEnv : public Env {
|
||||||
public:
|
public:
|
||||||
explicit LabelEnv(Env* parent) : Env(parent) {}
|
explicit LabelEnv(Env* parent) : Env(EnvKind::OTHER_ENV, parent) {}
|
||||||
std::string print() override { return "labelenv"; }
|
std::string print() override { return "labelenv"; }
|
||||||
std::unordered_map<std::string, Label>& get_label_map() override;
|
std::unordered_map<std::string, Label>& get_label_map() override;
|
||||||
BlockEnv* find_block(const std::string& name) 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;
|
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 {
|
class SymbolMacroEnv : public Env {
|
||||||
public:
|
public:
|
||||||
explicit SymbolMacroEnv(Env* parent) : Env(parent) {}
|
explicit SymbolMacroEnv(Env* parent) : Env(EnvKind::SYMBOL_MACRO_ENV, parent) {}
|
||||||
std::unordered_map<std::shared_ptr<goos::SymbolObject>, goos::Object> macros;
|
// key is goos symbols.
|
||||||
|
std::unordered_map<goos::HeapObject*, goos::Object> macros;
|
||||||
std::string print() override { return "symbol-macro-env"; }
|
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>
|
template <typename T>
|
||||||
T* get_parent_env_of_type(Env* in) {
|
T* get_parent_env_of_type_slow(Env* in) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto attempt = dynamic_cast<T*>(in);
|
auto attempt = dynamic_cast<T*>(in);
|
||||||
if (attempt)
|
if (attempt)
|
||||||
|
@ -293,11 +338,29 @@ T* get_parent_env_of_type(Env* in) {
|
||||||
in = in->parent();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -130,12 +130,12 @@ TypeSpec Compiler::parse_typespec(const goos::Object& src) {
|
||||||
|
|
||||||
bool Compiler::is_local_symbol(const goos::Object& obj, Env* env) {
|
bool Compiler::is_local_symbol(const goos::Object& obj, Env* env) {
|
||||||
// check in the symbol macro 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) {
|
while (mlet_env) {
|
||||||
if (mlet_env->macros.find(obj.as_symbol()) != mlet_env->macros.end()) {
|
if (mlet_env->macros.find(obj.as_symbol()) != mlet_env->macros.end()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
mlet_env = get_parent_env_of_type<SymbolMacroEnv>(mlet_env->parent());
|
mlet_env = mlet_env->parent()->symbol_macro_env();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check lexical
|
// check lexical
|
||||||
|
|
|
@ -250,7 +250,7 @@ std::string BitFieldVal::print() const {
|
||||||
|
|
||||||
RegVal* BitFieldVal::to_reg(Env* env) {
|
RegVal* BitFieldVal::to_reg(Env* env) {
|
||||||
int start_bit = -1;
|
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);
|
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.
|
// this first step gets the right 64-bits into a GPR that is also used as the result.
|
||||||
|
|
|
@ -33,7 +33,7 @@ Val* Compiler::compile_rlet(const goos::Object& form, const goos::Object& rest,
|
||||||
|
|
||||||
auto defs = args.unnamed.front();
|
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);
|
auto lenv = fenv->alloc_env<LexicalEnv>(env);
|
||||||
|
|
||||||
std::vector<IRegConstraint> constraints;
|
std::vector<IRegConstraint> constraints;
|
||||||
|
|
|
@ -302,7 +302,7 @@ Val* Compiler::compile_pair(const goos::Object& code, Env* env) {
|
||||||
// next try as a macro
|
// next try as a macro
|
||||||
goos::Object macro_obj;
|
goos::Object macro_obj;
|
||||||
if (try_getting_macro_from_goos(head, ¯o_obj)) {
|
if (try_getting_macro_from_goos(head, ¯o_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
|
// next try as an enum
|
||||||
|
@ -339,12 +339,12 @@ Val* Compiler::compile_char(const goos::Object& code, Env* env) {
|
||||||
* The type is always int.
|
* The type is always int.
|
||||||
*/
|
*/
|
||||||
Val* Compiler::compile_integer(s64 value, Env* env) {
|
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);
|
return fe->alloc_val<IntegerConstantVal>(m_ts.make_typespec("int"), &value, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Compiler::compile_integer(const U128& value, Env* env) {
|
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);
|
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.
|
* Get a SymbolVal representing a GOAL symbol object.
|
||||||
*/
|
*/
|
||||||
SymbolVal* Compiler::compile_get_sym_obj(const std::string& name, Env* env) {
|
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"));
|
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 ts = existing_symbol->second;
|
||||||
auto sext = m_ts.lookup_type(ts)->get_load_signed();
|
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 sym = fe->alloc_val<SymbolVal>(name, m_ts.make_typespec("symbol"));
|
||||||
auto re = fe->alloc_val<SymbolValueVal>(sym, ts, sext);
|
auto re = fe->alloc_val<SymbolValueVal>(sym, ts, sext);
|
||||||
return re;
|
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).
|
// 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) {
|
while (mlet_env) {
|
||||||
auto mlkv = mlet_env->macros.find(form.as_symbol());
|
auto mlkv = mlet_env->macros.find(form.as_symbol());
|
||||||
if (mlkv != mlet_env->macros.end()) {
|
if (mlkv != mlet_env->macros.end()) {
|
||||||
return compile_error_guard(mlkv->second, env);
|
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
|
// 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.
|
* 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) {
|
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) {
|
if (segment == TOP_LEVEL_SEGMENT) {
|
||||||
segment = MAIN_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) {
|
Val* Compiler::compile_string(const std::string& str, Env* env, int seg) {
|
||||||
auto obj = std::make_unique<StaticString>(str, 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 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));
|
fie->add_static(std::move(obj));
|
||||||
return result;
|
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.
|
* of the code, at least in Jak 1.
|
||||||
*/
|
*/
|
||||||
Val* Compiler::compile_float(const goos::Object& code, Env* env) {
|
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) {
|
if (segment == TOP_LEVEL_SEGMENT) {
|
||||||
segment = MAIN_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) {
|
Val* Compiler::compile_float(float value, Env* env, int seg) {
|
||||||
auto obj = std::make_unique<StaticFloat>(value, 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 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));
|
fie->add_static(std::move(obj));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
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
|
// create environment
|
||||||
auto block_env = fe->alloc_env<BlockEnv>(env, symbol_string(name));
|
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
|
// evaluate expression to return
|
||||||
auto result = compile_error_guard(value_expression, env);
|
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
|
// find block to return from
|
||||||
auto block = dynamic_cast<BlockEnv*>(env->find_block(block_name));
|
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
|
// 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.
|
// 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());
|
labels[label_name] = Label(func_env, func_env->code().size());
|
||||||
return get_none();
|
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.
|
// 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.
|
// 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));
|
env->emit(std::move(ir_goto));
|
||||||
return get_none();
|
return get_none();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ Val* Compiler::compile_seval(const goos::Object& form, const goos::Object& rest,
|
||||||
(void)env;
|
(void)env;
|
||||||
try {
|
try {
|
||||||
for_each_in_list(rest, [&](const goos::Object& o) {
|
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) {
|
} catch (std::runtime_error& e) {
|
||||||
throw_compiler_error(form, "Error while evaluating GOOS: {}", e.what());
|
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:
|
case SymbolInfo::Kind::CONSTANT:
|
||||||
return fmt::format(
|
return fmt::format(
|
||||||
"[Constant] Name: {} Value: {} Defined: {}", info.name(),
|
"[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()));
|
m_goos.reader.db.get_info_for(info.src_form()));
|
||||||
case SymbolInfo::Kind::FUNCTION:
|
case SymbolInfo::Kind::FUNCTION:
|
||||||
return fmt::format("[Function] Name: {} Defined: {}", info.name(),
|
return fmt::format("[Function] Name: {} Defined: {}", info.name(),
|
||||||
|
|
|
@ -125,7 +125,7 @@ Val* Compiler::compile_condition_as_bool(const goos::Object& form,
|
||||||
(void)rest;
|
(void)rest;
|
||||||
auto c = compile_condition(form, env, true);
|
auto c = compile_condition(form, env, true);
|
||||||
auto result = compile_get_sym_obj("#f", env)->to_gpr(env); // todo - can be optimized.
|
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 = std::make_unique<IR_ConditionalBranch>(c, label);
|
||||||
auto branch_ir_ref = branch_ir.get();
|
auto branch_ir_ref = branch_ir.get();
|
||||||
env->emit(std::move(branch_ir));
|
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)
|
// compile as condition (will set flags register with a cmp instruction)
|
||||||
auto condition = compile_condition(condition_code, env, false);
|
auto condition = compile_condition(condition_code, env, false);
|
||||||
auto branch = std::make_unique<IR_ConditionalBranch>(condition, Label());
|
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));
|
env->emit(std::move(branch));
|
||||||
return get_none();
|
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) {
|
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 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();
|
auto end_label = fenv->alloc_unnamed_label();
|
||||||
end_label->func = fenv;
|
end_label->func = fenv;
|
||||||
end_label->idx = -3; // placeholder
|
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 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();
|
auto end_label = fenv->alloc_unnamed_label();
|
||||||
end_label->func = fenv;
|
end_label->func = fenv;
|
||||||
end_label->idx = -4; // placeholder
|
end_label->idx = -4; // placeholder
|
||||||
|
|
|
@ -24,7 +24,7 @@ Val* Compiler::compile_define(const goos::Object& form, const goos::Object& rest
|
||||||
sym.print(), global_constant->second.print());
|
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 sym_val = fe->alloc_val<SymbolVal>(symbol_string(sym), m_ts.make_typespec("symbol"));
|
||||||
auto compiled_val = compile_error_guard(val, env);
|
auto compiled_val = compile_error_guard(val, env);
|
||||||
auto as_lambda = dynamic_cast<LambdaVal*>(compiled_val);
|
auto as_lambda = dynamic_cast<LambdaVal*>(compiled_val);
|
||||||
|
@ -137,7 +137,7 @@ void Compiler::set_bitfield(const goos::Object& form, BitFieldVal* dst, RegVal*
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
auto fe = env->function_env();
|
||||||
|
|
||||||
// first, get the value we want to modify:
|
// first, get the value we want to modify:
|
||||||
auto original_original = dst->parent()->to_gpr(env);
|
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) {
|
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;
|
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.
|
// we want to allow setting a 128-bit field from a 64-bit variable.
|
||||||
if (as_mem_deref->info.size == 16) {
|
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);
|
auto src_128 = fe->make_ireg(src_in_reg->type(), RegClass::INT_128);
|
||||||
env->emit_ir<IR_RegSet>(src_128, src_in_reg);
|
env->emit_ir<IR_RegSet>(src_128, src_in_reg);
|
||||||
src_in_reg = src_128;
|
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
|
// 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 ||
|
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)) {
|
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);
|
auto src_gpr = fe->make_ireg(src_in_reg->type(), RegClass::GPR_64);
|
||||||
env->emit_ir<IR_RegSet>(src_gpr, src_in_reg);
|
env->emit_ir<IR_RegSet>(src_gpr, src_in_reg);
|
||||||
src_in_reg = src_gpr;
|
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
|
// 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) {
|
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);
|
auto src_gpr = fe->make_ireg(src_in_reg->type(), RegClass::GPR_64);
|
||||||
env->emit_ir<IR_RegSet>(src_gpr, src_in_reg);
|
env->emit_ir<IR_RegSet>(src_gpr, src_in_reg);
|
||||||
src_in_reg = src_gpr;
|
src_in_reg = src_gpr;
|
||||||
|
|
|
@ -8,17 +8,6 @@
|
||||||
#include "third-party/fmt/core.h"
|
#include "third-party/fmt/core.h"
|
||||||
|
|
||||||
namespace {
|
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.
|
* 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,
|
throw_compiler_error(form,
|
||||||
"Cannot inline {} because inlining of this function was disallowed.");
|
"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);
|
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) {
|
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) {
|
for_each_in_list(rest, [&](const goos::Object& o) {
|
||||||
if (o.is_symbol()) {
|
if (o.is_symbol()) {
|
||||||
|
@ -112,8 +101,8 @@ Val* Compiler::compile_local_vars(const goos::Object& form, const goos::Object&
|
||||||
* confusing special cases...
|
* confusing special cases...
|
||||||
*/
|
*/
|
||||||
Val* Compiler::compile_lambda(const goos::Object& form, const goos::Object& rest, Env* env) {
|
Val* Compiler::compile_lambda(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 obj_env = get_parent_env_of_type<FileEnv>(env);
|
auto obj_env = env->file_env();
|
||||||
auto args = get_va(form, rest);
|
auto args = get_va(form, rest);
|
||||||
if (args.unnamed.empty() || !args.unnamed.front().is_list() ||
|
if (args.unnamed.empty() || !args.unnamed.front().is_list() ||
|
||||||
!args.only_contains_named({"name", "inline-only", "segment", "behavior"})) {
|
!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) {
|
Val* Compiler::compile_function_or_method_call(const goos::Object& form, Env* env) {
|
||||||
goos::Object f = form;
|
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 args = get_va(form, form);
|
||||||
auto uneval_head = args.unnamed.at(0);
|
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 ==
|
if (kv->second->func ==
|
||||||
nullptr || // only-inline, we must inline it as there is no code generated for it
|
nullptr || // only-inline, we must inline it as there is no code generated for it
|
||||||
kv->second->func->settings
|
kv->second->func->settings
|
||||||
.inline_by_default || // inline when possible, so we should inline
|
.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
|
|
||||||
auto_inline = true;
|
auto_inline = true;
|
||||||
head = kv->second;
|
head = kv->second;
|
||||||
}
|
}
|
||||||
|
@ -588,7 +576,7 @@ Val* Compiler::compile_real_function_call(const goos::Object& form,
|
||||||
const std::vector<RegVal*>& args,
|
const std::vector<RegVal*>& args,
|
||||||
Env* env,
|
Env* env,
|
||||||
const std::string& method_type_name) {
|
const std::string& method_type_name) {
|
||||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
auto fe = env->function_env();
|
||||||
fe->require_aligned_stack();
|
fe->require_aligned_stack();
|
||||||
TypeSpec return_ts;
|
TypeSpec return_ts;
|
||||||
if (function->type().arg_count() == 0) {
|
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.
|
* 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) {
|
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) {
|
if (settings.is_set) {
|
||||||
throw_compiler_error(form, "Function cannot have multiple declares");
|
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.inline_by_default = false;
|
||||||
settings.save_code = true;
|
settings.save_code = true;
|
||||||
} else if (first.as_symbol()->name == "asm-func") {
|
} 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;
|
fe->is_asm_func = true;
|
||||||
if (!rrest->is_pair()) {
|
if (!rrest->is_pair()) {
|
||||||
throw_compiler_error(
|
throw_compiler_error(
|
||||||
|
@ -716,7 +704,7 @@ Val* Compiler::compile_declare(const goos::Object& form, const goos::Object& res
|
||||||
if (!rrest->is_empty_list()) {
|
if (!rrest->is_empty_list()) {
|
||||||
throw_compiler_error(first, "Invalid allow-saved-regs declare");
|
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;
|
fe->asm_func_saved_regs = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "goalc/compiler/Compiler.h"
|
#include "goalc/compiler/Compiler.h"
|
||||||
#include "third-party/fmt/core.h"
|
#include "third-party/fmt/core.h"
|
||||||
|
#include "common/goos/PrettyPrinter.h"
|
||||||
|
|
||||||
using namespace goos;
|
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) {
|
bool Compiler::try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest) {
|
||||||
Object macro_obj;
|
Object macro_obj;
|
||||||
bool got_macro = false;
|
bool got_macro = false;
|
||||||
if (m_goos.eval_symbol(macro_name, m_goos.goal_env.as_env(), ¯o_obj) &&
|
if (m_goos.eval_symbol(macro_name, m_goos.goal_env.as_env_ptr(), ¯o_obj) &&
|
||||||
macro_obj.is_macro()) {
|
macro_obj.is_macro()) {
|
||||||
got_macro = true;
|
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,
|
Val* Compiler::compile_goos_macro(const goos::Object& o,
|
||||||
const goos::Object& macro_obj,
|
const goos::Object& macro_obj,
|
||||||
const goos::Object& rest,
|
const goos::Object& rest,
|
||||||
|
const goos::Object& name,
|
||||||
Env* env) {
|
Env* env) {
|
||||||
auto macro = macro_obj.as_macro();
|
auto macro = macro_obj.as_macro();
|
||||||
Arguments args = m_goos.get_args(o, rest, macro->args);
|
Arguments args = m_goos.get_args(o, rest, macro->args);
|
||||||
auto mac_env_obj = EnvironmentObject::make_new();
|
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 = m_goos.global_environment.as_env();
|
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.set_args_in_env(o, args, macro->args, mac_env);
|
||||||
m_goos.goal_to_goos.enclosing_method_type =
|
m_goos.goal_to_goos.enclosing_method_type = env->function_env()->method_of_type_name;
|
||||||
get_parent_env_of_type<FunctionEnv>(env)->method_of_type_name;
|
|
||||||
auto goos_result = m_goos.eval_list_return_last(macro->body, macro->body, 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.
|
// 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();
|
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:
|
// check condition:
|
||||||
Object condition_result =
|
Object condition_result = m_goos.eval_with_rewind(current_case.as_pair()->car,
|
||||||
m_goos.eval_with_rewind(current_case.as_pair()->car, m_goos.global_environment.as_env());
|
m_goos.global_environment.as_env_ptr());
|
||||||
if (m_goos.truthy(condition_result)) {
|
if (m_goos.truthy(condition_result)) {
|
||||||
if (current_case.as_pair()->cdr.is_empty_list()) {
|
if (current_case.as_pair()->cdr.is_empty_list()) {
|
||||||
return get_none();
|
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 defs = pair_car(rest);
|
||||||
auto body = pair_cdr(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);
|
auto menv = fenv->alloc_env<SymbolMacroEnv>(env);
|
||||||
|
|
||||||
for_each_in_list(defs, [&](const goos::Object& o) {
|
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();
|
auto macro = macro_obj.as_macro();
|
||||||
Arguments args = m_goos.get_args(src, rest, macro->args);
|
Arguments args = m_goos.get_args(src, rest, macro->args);
|
||||||
auto mac_env_obj = EnvironmentObject::make_new();
|
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 = m_goos.global_environment.as_env();
|
mac_env->parent_env = m_goos.global_environment.as_env_ptr();
|
||||||
m_goos.set_args_in_env(src, args, macro->args, mac_env);
|
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);
|
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.
|
// 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;
|
*out = goos_result;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -43,7 +43,7 @@ Val* Compiler::number_to_integer(const goos::Object& form, Val* in, Env* env) {
|
||||||
if (is_binteger(ts)) {
|
if (is_binteger(ts)) {
|
||||||
throw_compiler_error(form, "Cannot convert {} (a binteger) to an integer yet.", in->print());
|
throw_compiler_error(form, "Cannot convert {} (a binteger) to an integer yet.", in->print());
|
||||||
} else if (is_float(ts)) {
|
} 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"));
|
auto result = fe->make_gpr(m_ts.make_typespec("int"));
|
||||||
env->emit(std::make_unique<IR_FloatToInt>(result, in->to_fpr(env)));
|
env->emit(std::make_unique<IR_FloatToInt>(result, in->to_fpr(env)));
|
||||||
return result;
|
return result;
|
||||||
|
@ -62,7 +62,7 @@ Val* Compiler::number_to_binteger(const goos::Object& form, Val* in, Env* env) {
|
||||||
} else if (is_float(ts)) {
|
} else if (is_float(ts)) {
|
||||||
throw_compiler_error(form, "Cannot convert {} (a float) to an integer yet.", in->print());
|
throw_compiler_error(form, "Cannot convert {} (a float) to an integer yet.", in->print());
|
||||||
} else if (is_integer(ts)) {
|
} 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);
|
RegVal* input = in->to_reg(env);
|
||||||
auto sa = fe->make_gpr(m_ts.make_typespec("int"));
|
auto sa = fe->make_gpr(m_ts.make_typespec("int"));
|
||||||
env->emit(std::make_unique<IR_LoadConstant64>(sa, 3));
|
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)) {
|
} else if (is_float(ts)) {
|
||||||
return in;
|
return in;
|
||||||
} else if (is_integer(ts)) {
|
} 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"));
|
auto result = fe->make_fpr(m_ts.make_typespec("float"));
|
||||||
env->emit(std::make_unique<IR_IntToFloat>(result, in->to_gpr(env)));
|
env->emit(std::make_unique<IR_IntToFloat>(result, in->to_gpr(env)));
|
||||||
return result;
|
return result;
|
||||||
|
@ -339,8 +339,7 @@ Val* Compiler::compile_sub(const goos::Object& form, const goos::Object& rest, E
|
||||||
|
|
||||||
case MATH_FLOAT:
|
case MATH_FLOAT:
|
||||||
if (args.unnamed.size() == 1) {
|
if (args.unnamed.size() == 1) {
|
||||||
auto result =
|
auto result = compile_float(0, env, env->function_env()->segment)->to_fpr(env);
|
||||||
compile_float(0, env, get_parent_env_of_type<FunctionEnv>(env)->segment)->to_fpr(env);
|
|
||||||
env->emit(std::make_unique<IR_FloatMath>(
|
env->emit(std::make_unique<IR_FloatMath>(
|
||||||
FloatMathKind::SUB_SS, result,
|
FloatMathKind::SUB_SS, result,
|
||||||
to_math_type(form, compile_error_guard(args.unnamed.at(0), env), math_type, env)
|
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);
|
auto math_type = get_math_mode(first_type);
|
||||||
switch (math_type) {
|
switch (math_type) {
|
||||||
case MATH_INT: {
|
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 first_thing = first_val->to_gpr(env);
|
||||||
auto result = env->make_gpr(first_type);
|
auto result = env->make_gpr(first_type);
|
||||||
env->emit(std::make_unique<IR_RegSet>(result, first_thing));
|
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>(result, in));
|
||||||
env->emit(std::make_unique<IR_RegSet>(sa_in, sa));
|
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;
|
IRegConstraint sa_con;
|
||||||
sa_con.ireg = sa_in->ireg();
|
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, {{}, {}}, {});
|
va_check(form, args, {{}, {}}, {});
|
||||||
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
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 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 ||
|
if (get_math_mode(first->type()) != MathMode::MATH_INT ||
|
||||||
get_math_mode(second->type()) != MathMode::MATH_INT) {
|
get_math_mode(second->type()) != MathMode::MATH_INT) {
|
||||||
|
|
|
@ -73,8 +73,7 @@ Val* Compiler::compile_define_state_hook(const goos::Object& form,
|
||||||
state_name, existing_var->second.print(), state_type.print());
|
state_name, existing_var->second.print(), state_type.print());
|
||||||
}
|
}
|
||||||
m_symbol_types[state_name] = state_type;
|
m_symbol_types[state_name] = state_type;
|
||||||
auto sym_val =
|
auto sym_val = env->function_env()->alloc_val<SymbolVal>(state_name, state_type);
|
||||||
get_parent_env_of_type<FunctionEnv>(env)->alloc_val<SymbolVal>(state_name, state_type);
|
|
||||||
env->emit(std::make_unique<IR_SetSymbolValue>(sym_val, state_object));
|
env->emit(std::make_unique<IR_SetSymbolValue>(sym_val, state_object));
|
||||||
|
|
||||||
return get_none();
|
return get_none();
|
||||||
|
|
|
@ -265,7 +265,7 @@ StaticResult Compiler::compile_new_static_structure(const goos::Object& form,
|
||||||
|
|
||||||
obj->data.resize(type_info->get_size_in_memory());
|
obj->data.resize(type_info->get_size_in_memory());
|
||||||
compile_static_structure_inline(form, type, _field_defs, obj.get(), 0, env);
|
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);
|
auto result = StaticResult::make_structure_reference(obj.get(), type);
|
||||||
fie->add_static(std::move(obj));
|
fie->add_static(std::move(obj));
|
||||||
return result;
|
return result;
|
||||||
|
@ -444,7 +444,7 @@ Val* Compiler::compile_bitfield_definition(const goos::Object& form,
|
||||||
if (use_128) {
|
if (use_128) {
|
||||||
auto integer_lo = compile_integer(constant_integer_part.lo, env)->to_gpr(env);
|
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 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 rv = fe->make_ireg(type, RegClass::INT_128);
|
||||||
auto xmm_temp = fe->make_ireg(TypeSpec("object"), 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
|
* - Strings
|
||||||
*/
|
*/
|
||||||
StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form, Env* env) {
|
StaticResult Compiler::compile_static_no_eval_for_pairs(const goos::Object& form, Env* env) {
|
||||||
auto fie = get_parent_env_of_type<FileEnv>(env);
|
auto fie = env->file_env();
|
||||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
auto fe = env->function_env();
|
||||||
auto segment = fe->segment;
|
auto segment = fe->segment;
|
||||||
if (segment == TOP_LEVEL_SEGMENT) {
|
if (segment == TOP_LEVEL_SEGMENT) {
|
||||||
segment = MAIN_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) {
|
StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env* env) {
|
||||||
auto form = expand_macro_completely(form_before_macro, env);
|
auto form = expand_macro_completely(form_before_macro, env);
|
||||||
auto fie = get_parent_env_of_type<FileEnv>(env);
|
auto fie = env->file_env();
|
||||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
auto fe = env->function_env();
|
||||||
auto segment = fe->segment;
|
auto segment = fe->segment;
|
||||||
if (segment == TOP_LEVEL_SEGMENT) {
|
if (segment == TOP_LEVEL_SEGMENT) {
|
||||||
segment = MAIN_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,
|
StaticResult Compiler::fill_static_array(const goos::Object& form,
|
||||||
const goos::Object& rest,
|
const goos::Object& rest,
|
||||||
Env* env) {
|
Env* env) {
|
||||||
auto fie = get_parent_env_of_type<FileEnv>(env);
|
auto fie = env->file_env();
|
||||||
// (new 'static 'boxed-array ...)
|
// (new 'static 'boxed-array ...)
|
||||||
// get all arguments now
|
// get all arguments now
|
||||||
auto args = get_list_as_vector(rest);
|
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,
|
StaticResult Compiler::fill_static_boxed_array(const goos::Object& form,
|
||||||
const goos::Object& rest,
|
const goos::Object& rest,
|
||||||
Env* env) {
|
Env* env) {
|
||||||
auto fie = get_parent_env_of_type<FileEnv>(env);
|
auto fie = env->file_env();
|
||||||
// (new 'static 'boxed-array ...)
|
// (new 'static 'boxed-array ...)
|
||||||
// get all arguments now
|
// get all arguments now
|
||||||
// auto args = get_list_as_vector(rest);
|
// 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,
|
StaticResult Compiler::fill_static_inline_array(const goos::Object& form,
|
||||||
const goos::Object& rest,
|
const goos::Object& rest,
|
||||||
Env* env) {
|
Env* env) {
|
||||||
auto fie = get_parent_env_of_type<FileEnv>(env);
|
auto fie = env->file_env();
|
||||||
// (new 'static 'inline-array ...)
|
// (new 'static 'inline-array ...)
|
||||||
// get all arguments now
|
// get all arguments now
|
||||||
auto args = get_list_as_vector(rest);
|
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)
|
assert(form.is_pair()); // (quote PAIR)
|
||||||
auto result = compile_static_no_eval_for_pairs(form, env);
|
auto result = compile_static_no_eval_for_pairs(form, env);
|
||||||
assert(result.is_reference());
|
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());
|
auto static_result = fe->alloc_val<StaticVal>(result.reference(), result.typespec());
|
||||||
return static_result;
|
return static_result;
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1020,7 @@ Val* Compiler::compile_new_static_structure_or_basic(const goos::Object& form,
|
||||||
const TypeSpec& type,
|
const TypeSpec& type,
|
||||||
const goos::Object& field_defs,
|
const goos::Object& field_defs,
|
||||||
Env* env) {
|
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 sr = compile_new_static_structure(form, type, field_defs, env);
|
||||||
auto result = fe->alloc_val<StaticVal>(sr.reference(), type);
|
auto result = fe->alloc_val<StaticVal>(sr.reference(), type);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -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);
|
auto offset_of_method = get_offset_of_method(info.id);
|
||||||
assert(type->type() == TypeSpec("type"));
|
assert(type->type() == TypeSpec("type"));
|
||||||
|
|
||||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
auto fe = env->function_env();
|
||||||
|
|
||||||
MemLoadInfo load_info;
|
MemLoadInfo load_info;
|
||||||
load_info.sign_extend = false;
|
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());
|
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;
|
RegVal* runtime_type = nullptr;
|
||||||
if (m_ts.should_use_virtual_methods(compile_time_type, method_info.id)) {
|
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) {
|
const std::string& out_stream) {
|
||||||
// Add first two format args
|
// Add first two format args
|
||||||
args.insert(args.begin(),
|
args.insert(args.begin(),
|
||||||
compile_string(fmt_template, env, get_parent_env_of_type<FunctionEnv>(env)->segment)
|
compile_string(fmt_template, env, env->function_env()->segment)->to_gpr(env));
|
||||||
->to_gpr(env));
|
|
||||||
args.insert(args.begin(), compile_get_sym_obj(out_stream, env)->to_gpr(env));
|
args.insert(args.begin(), compile_get_sym_obj(out_stream, env)->to_gpr(env));
|
||||||
|
|
||||||
// generate code in the method_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());
|
emitter::gRegInfo.get_gpr_ret_reg());
|
||||||
|
|
||||||
// add this function to the object file
|
// 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"));
|
auto method = fe->alloc_val<LambdaVal>(m_ts.make_typespec("function"));
|
||||||
method->func = method_env.get();
|
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));
|
obj_env_inspect->add_function(std::move(method_env));
|
||||||
|
|
||||||
// call method-set!
|
// 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
|
// 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"));
|
auto method = fe->alloc_val<LambdaVal>(m_ts.make_typespec("function"));
|
||||||
method->func = method_env.get();
|
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));
|
obj_env_inspect->add_function(std::move(method_env));
|
||||||
|
|
||||||
// call method-set!
|
// call method-set!
|
||||||
|
@ -407,7 +406,7 @@ Val* Compiler::compile_deftype(const goos::Object& form, const goos::Object& res
|
||||||
* Compile a (defmethod ...) form
|
* Compile a (defmethod ...) form
|
||||||
*/
|
*/
|
||||||
Val* Compiler::compile_defmethod(const goos::Object& form, const goos::Object& _rest, Env* env) {
|
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* rest = &_rest;
|
||||||
|
|
||||||
auto& method_name = pair_car(*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->emit(std::make_unique<IR_Null>());
|
||||||
new_func_env->finish();
|
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);
|
assert(obj_env);
|
||||||
if (new_func_env->settings.save_code) {
|
if (new_func_env->settings.save_code) {
|
||||||
obj_env->add_function(std::move(new_func_env));
|
obj_env->add_function(std::move(new_func_env));
|
||||||
|
@ -600,7 +599,7 @@ Val* Compiler::get_field_of_structure(const StructureType* type,
|
||||||
Val* object,
|
Val* object,
|
||||||
const std::string& field_name,
|
const std::string& field_name,
|
||||||
Env* env) {
|
Env* env) {
|
||||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
auto fe = env->function_env();
|
||||||
Val* result = nullptr;
|
Val* result = nullptr;
|
||||||
int offset = -type->get_offset();
|
int offset = -type->get_offset();
|
||||||
auto field = m_ts.lookup_field_info(type->get_name(), field_name);
|
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,
|
Val* object,
|
||||||
const std::string& field_name,
|
const std::string& field_name,
|
||||||
Env* env) {
|
Env* env) {
|
||||||
auto fe = get_parent_env_of_type<FunctionEnv>(env);
|
auto fe = env->function_env();
|
||||||
Val* result = nullptr;
|
Val* result = nullptr;
|
||||||
auto bitfield_info = m_ts.lookup_bitfield_info(type->get_name(), field_name);
|
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,
|
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.
|
* location. Otherwise set! or & won't work.
|
||||||
*/
|
*/
|
||||||
Val* Compiler::compile_deref(const goos::Object& form, const goos::Object& _rest, Env* env) {
|
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()) {
|
if (_rest.is_empty_list()) {
|
||||||
throw_compiler_error(form, "-> must get at least one argument");
|
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, {{}, {}}, {});
|
va_check(form, args, {{}, {}}, {});
|
||||||
auto desired_ts = parse_typespec(args.unnamed.at(0));
|
auto desired_ts = parse_typespec(args.unnamed.at(0));
|
||||||
auto base = compile_error_guard(args.unnamed.at(1), env);
|
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()) {
|
if (base->settable()) {
|
||||||
result->mark_as_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);
|
result->set_type(desired_ts);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} 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;
|
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()) {
|
if (base->settable()) {
|
||||||
result->mark_as_settable();
|
result->mark_as_settable();
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1019,7 @@ Val* Compiler::compile_static_new(const goos::Object& form,
|
||||||
if (unquoted.is_symbol() &&
|
if (unquoted.is_symbol() &&
|
||||||
(unquoted.as_symbol()->name == "boxed-array" || unquoted.as_symbol()->name == "array" ||
|
(unquoted.as_symbol()->name == "boxed-array" || unquoted.as_symbol()->name == "array" ||
|
||||||
unquoted.as_symbol()->name == "inline-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 sr = compile_static(form, env);
|
||||||
auto result = fe->alloc_val<StaticVal>(sr.reference(), sr.typespec());
|
auto result = fe->alloc_val<StaticVal>(sr.reference(), sr.typespec());
|
||||||
return result;
|
return result;
|
||||||
|
@ -1045,7 +1044,7 @@ Val* Compiler::compile_stack_new(const goos::Object& form,
|
||||||
Env* env,
|
Env* env,
|
||||||
bool call_constructor) {
|
bool call_constructor) {
|
||||||
auto type_of_object = parse_typespec(unquote(type));
|
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 (type_of_object == TypeSpec("inline-array") || type_of_object == TypeSpec("array")) {
|
||||||
if (call_constructor) {
|
if (call_constructor) {
|
||||||
throw_compiler_error(form, "Constructing stack arrays is not yet supported");
|
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) {
|
Val* Compiler::compile_car(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||||
auto args = get_va(form, rest);
|
auto args = get_va(form, rest);
|
||||||
va_check(form, args, {{}}, {});
|
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);
|
auto pair = compile_error_guard(args.unnamed.at(0), env);
|
||||||
if (pair->type() != m_ts.make_typespec("object")) {
|
if (pair->type() != m_ts.make_typespec("object")) {
|
||||||
typecheck(form, m_ts.make_typespec("pair"), pair->type(), "Type of argument to car");
|
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) {
|
Val* Compiler::compile_cdr(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||||
auto args = get_va(form, rest);
|
auto args = get_va(form, rest);
|
||||||
va_check(form, args, {{}}, {});
|
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);
|
auto pair = compile_error_guard(args.unnamed.at(0), env);
|
||||||
if (pair->type() != m_ts.make_typespec("object")) {
|
if (pair->type() != m_ts.make_typespec("object")) {
|
||||||
typecheck(form, m_ts.make_typespec("pair"), pair->type(), "Type of argument to cdr");
|
typecheck(form, m_ts.make_typespec("pair"), pair->type(), "Type of argument to cdr");
|
||||||
|
|
|
@ -65,7 +65,7 @@ void MakeSystem::load_project_file(const std::string& file_path) {
|
||||||
// read the file
|
// read the file
|
||||||
auto data = m_goos.reader.read_from_file({file_path});
|
auto data = m_goos.reader.read_from_file({file_path});
|
||||||
// interpret it, which will call various handlers.
|
// 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,
|
goos::Object MakeSystem::handle_defstep(const goos::Object& form,
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
class IRegSet {
|
class IRegSet {
|
||||||
public:
|
public:
|
||||||
IRegSet() = default;
|
IRegSet() { m_data.reserve(4); }
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Add the given ireg to the set.
|
* Add the given ireg to the set.
|
||||||
|
|
|
@ -11,7 +11,7 @@ using namespace goos;
|
||||||
namespace {
|
namespace {
|
||||||
// helper to evaluate a string as a goos expression.
|
// helper to evaluate a string as a goos expression.
|
||||||
std::string e(Interpreter& interp, const std::string& in) {
|
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();
|
.print();
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -349,8 +349,6 @@ TEST(GoosReader, TextDb) {
|
||||||
.as_pair()
|
.as_pair()
|
||||||
->cdr.as_pair()
|
->cdr.as_pair()
|
||||||
->car;
|
->car;
|
||||||
std::string expected = "text from " +
|
std::string expected = "test/test_data/test_reader_file0.gc, line: 5\n(1 2 3 4)\n ^\n";
|
||||||
file_util::get_file_path({"test", "test_data", "test_reader_file0.gc"}) +
|
|
||||||
", line: 5\n(1 2 3 4)\n";
|
|
||||||
EXPECT_EQ(expected, reader.db.get_info_for(result));
|
EXPECT_EQ(expected, reader.db.get_info_for(result));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue