From cc8801a27b41b7cc03b9d086cb79986a5c2a98fe Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:01:17 -0400 Subject: [PATCH] [goalc] speed up jak3 compilation (#3454) I noticed that jak 3's compilation was spending a lot of time accessing the `unordered_map`s we use to store constants and symbol types. I repurposed the `EnvironmentMap` originally made for GOOS for this. It turns out that we were copying the entire constant map whenever we encountered a `deftype`, and fixed that too. This speeds up jak3 compiles from ~16 to 11 seconds for me. --- common/goos/Interpreter.cpp | 98 ---------------- common/goos/Object.h | 109 ++++++++++++++++-- common/type_system/deftype.cpp | 48 +++----- common/type_system/deftype.h | 8 +- common/util/crc32.h | 2 + goalc/compiler/Compiler.h | 6 +- goalc/compiler/Util.cpp | 2 +- goalc/compiler/compilation/Asm.cpp | 7 +- goalc/compiler/compilation/Atoms.cpp | 16 +-- .../compiler/compilation/CompilerControl.cpp | 17 +-- .../compilation/ConstantPropagation.cpp | 10 +- goalc/compiler/compilation/Define.cpp | 27 +++-- goalc/compiler/compilation/Function.cpp | 3 +- goalc/compiler/compilation/Macro.cpp | 12 +- goalc/compiler/compilation/State.cpp | 10 +- goalc/compiler/compilation/Static.cpp | 6 +- goalc/compiler/compilation/Type.cpp | 27 +++-- goalc/compiler/symbol_info.cpp | 2 +- 18 files changed, 192 insertions(+), 218 deletions(-) diff --git a/common/goos/Interpreter.cpp b/common/goos/Interpreter.cpp index cdee3d2929..40a4103620 100644 --- a/common/goos/Interpreter.cpp +++ b/common/goos/Interpreter.cpp @@ -571,104 +571,6 @@ Object Interpreter::eval(Object obj, const std::shared_ptr& e } } -EnvironmentMap::EnvironmentMap() { - clear(); -} - -void EnvironmentMap::clear() { - m_entries.clear(); - m_power_of_two_size = 3; // 2 ^ 3 = 8 - m_entries.resize(8); - m_used_entries = 0; - m_next_resize = (m_entries.size() * kMaxUsed); - m_mask = 0b111; -} - -Object* EnvironmentMap::lookup(InternedSymbolPtr str) { - if (m_entries.size() < 10) { - for (auto& e : m_entries) { - if (e.key == str.name_ptr) { - return &e.value; - } - } - return nullptr; - } - u32 hash = crc32((const u8*)&str.name_ptr, sizeof(const char*)); - - // probe - for (u32 i = 0; i < m_entries.size(); i++) { - u32 slot_addr = (hash + i) & m_mask; - auto& slot = m_entries[slot_addr]; - if (!slot.key) { - return nullptr; - } else { - if (slot.key != str.name_ptr) { - continue; // bad hash - } - return &slot.value; - } - } - - // should be impossible to reach. - ASSERT_NOT_REACHED(); -} - -void EnvironmentMap::set(InternedSymbolPtr ptr, const Object& obj) { - u32 hash = crc32((const u8*)&ptr.name_ptr, sizeof(const char*)); - - // probe - for (u32 i = 0; i < m_entries.size(); i++) { - u32 slot_addr = (hash + i) & m_mask; - auto& slot = m_entries[slot_addr]; - if (!slot.key) { - // not found, insert! - slot.key = ptr.name_ptr; - slot.value = obj; - m_used_entries++; - - if (m_used_entries >= m_next_resize) { - resize(); - } - return; - } else { - if (slot.key == ptr.name_ptr) { - slot.value = obj; - return; - } - } - } - - // should be impossible to reach. - ASSERT_NOT_REACHED(); -} - -void EnvironmentMap::resize() { - m_power_of_two_size++; - m_mask = (1U << m_power_of_two_size) - 1; - - std::vector new_entries(m_entries.size() * 2); - for (const auto& old_entry : m_entries) { - if (old_entry.key) { - bool done = false; - u32 hash = crc32((const u8*)&old_entry.key, sizeof(const char*)); - for (u32 i = 0; i < new_entries.size(); i++) { - u32 slot_addr = (hash + i) & m_mask; - auto& slot = new_entries[slot_addr]; - if (!slot.key) { - slot.key = old_entry.key; - slot.value = std::move(old_entry.value); - done = true; - break; - } - } - ASSERT(done); - } - } - - m_entries = std::move(new_entries); - m_next_resize = kMaxUsed * m_entries.size(); -} - namespace { /*! diff --git a/common/goos/Object.h b/common/goos/Object.h index b01efc036c..6aac254eb4 100644 --- a/common/goos/Object.h +++ b/common/goos/Object.h @@ -55,6 +55,7 @@ #include "common/common_types.h" #include "common/util/Assert.h" +#include "common/util/crc32.h" namespace goos { @@ -456,23 +457,111 @@ class PairObject : public HeapObject { ~PairObject() = default; }; -class EnvironmentMap { +template +class InternedPtrMap { public: - EnvironmentMap(const EnvironmentMap&) = delete; - EnvironmentMap& operator=(const EnvironmentMap&) = delete; - EnvironmentMap(); - Object* lookup(InternedSymbolPtr ptr); - void set(InternedSymbolPtr ptr, const Object& obj); - void clear(); + InternedPtrMap(const InternedPtrMap&) = delete; + InternedPtrMap& operator=(const InternedPtrMap&) = delete; + InternedPtrMap() { clear(); } + + T* lookup(InternedSymbolPtr str) { + if (m_entries.size() < 10) { + for (auto& e : m_entries) { + if (e.key == str.name_ptr) { + return &e.value; + } + } + return nullptr; + } + u32 hash = crc32((const u8*)&str.name_ptr, sizeof(const char*)); + + // probe + for (u32 i = 0; i < m_entries.size(); i++) { + u32 slot_addr = (hash + i) & m_mask; + auto& slot = m_entries[slot_addr]; + if (!slot.key) { + return nullptr; + } else { + if (slot.key != str.name_ptr) { + continue; // bad hash + } + return &slot.value; + } + } + + // should be impossible to reach. + ASSERT_NOT_REACHED(); + } + void set(InternedSymbolPtr ptr, const T& obj) { + u32 hash = crc32((const u8*)&ptr.name_ptr, sizeof(const char*)); + + // probe + for (u32 i = 0; i < m_entries.size(); i++) { + u32 slot_addr = (hash + i) & m_mask; + auto& slot = m_entries[slot_addr]; + if (!slot.key) { + // not found, insert! + slot.key = ptr.name_ptr; + slot.value = obj; + m_used_entries++; + + if (m_used_entries >= m_next_resize) { + resize(); + } + return; + } else { + if (slot.key == ptr.name_ptr) { + slot.value = obj; + return; + } + } + } + + // should be impossible to reach. + ASSERT_NOT_REACHED(); + } + void clear() { + m_entries.clear(); + m_power_of_two_size = 3; // 2 ^ 3 = 8 + m_entries.resize(8); + m_used_entries = 0; + m_next_resize = (m_entries.size() * kMaxUsed); + m_mask = 0b111; + } private: struct Entry { const char* key = nullptr; - Object value; + T value; }; std::vector m_entries; - void resize(); + void resize() { + m_power_of_two_size++; + m_mask = (1U << m_power_of_two_size) - 1; + + std::vector new_entries(m_entries.size() * 2); + for (const auto& old_entry : m_entries) { + if (old_entry.key) { + bool done = false; + u32 hash = crc32((const u8*)&old_entry.key, sizeof(const char*)); + for (u32 i = 0; i < new_entries.size(); i++) { + u32 slot_addr = (hash + i) & m_mask; + auto& slot = new_entries[slot_addr]; + if (!slot.key) { + slot.key = old_entry.key; + slot.value = std::move(old_entry.value); + done = true; + break; + } + } + ASSERT(done); + } + } + + m_entries = std::move(new_entries); + m_next_resize = kMaxUsed * m_entries.size(); + } int m_power_of_two_size = 0; int m_used_entries = 0; int m_next_resize = 0; @@ -480,6 +569,8 @@ class EnvironmentMap { static constexpr float kMaxUsed = 0.7; }; +using EnvironmentMap = InternedPtrMap; + class EnvironmentObject : public HeapObject { public: std::string name; diff --git a/common/type_system/deftype.cpp b/common/type_system/deftype.cpp index 513dd99405..6c844025f2 100644 --- a/common/type_system/deftype.cpp +++ b/common/type_system/deftype.cpp @@ -84,12 +84,10 @@ double get_float(const goos::Object& obj) { throw std::runtime_error(obj.print() + " was supposed to be an number, but isn't"); } -void add_field( - StructureType* structure, - TypeSystem* ts, - const goos::Object& def, - std::unordered_map& - constants) { +void add_field(StructureType* structure, + TypeSystem* ts, + const goos::Object& def, + goos::EnvironmentMap* constants) { auto rest = &def; auto name = symbol_string(car(rest)); @@ -113,9 +111,8 @@ void add_field( if (car(rest).is_int()) { array_size = car(rest).integer_obj.value; rest = cdr(rest); - } else if (car(rest).is_symbol() && - constants.find((car(rest)).as_symbol()) != constants.end()) { - array_size = get_int(constants[(car(rest)).as_symbol()]); + } else if (car(rest).is_symbol() && constants && constants->lookup((car(rest)).as_symbol())) { + array_size = get_int(*constants->lookup((car(rest)).as_symbol())); rest = cdr(rest); } @@ -543,13 +540,11 @@ void declare_state(Type* type, }); } -StructureDefResult parse_structure_def( - StructureType* type, - TypeSystem* ts, - const goos::Object& fields, - const goos::Object& options, - std::unordered_map& - constants) { +StructureDefResult parse_structure_def(StructureType* type, + TypeSystem* ts, + const goos::Object& fields, + const goos::Object& options, + goos::EnvironmentMap* constants) { StructureDefResult result; for_each_in_list(fields, [&](const goos::Object& o) { add_field(type, ts, o, constants); }); TypeFlags flags; @@ -811,18 +806,11 @@ TypeSpec parse_typespec(const TypeSystem* type_system, const goos::Object& src) return {}; } -DeftypeResult parse_deftype( - const goos::Object& deftype, - TypeSystem* ts, - std::unordered_map* - constants) { +DeftypeResult parse_deftype(const goos::Object& deftype, + TypeSystem* ts, + goos::EnvironmentMap* constants) { DefinitionMetadata symbol_metadata; - std::unordered_map - no_consts; - auto& constants_to_use = no_consts; - if (constants != nullptr) { - constants_to_use = *constants; - } + goos::EnvironmentMap no_consts; auto iter = &deftype; @@ -861,8 +849,7 @@ DeftypeResult parse_deftype( } new_type->inherit(pto); ts->forward_declare_type_as(name, pto->get_name()); - auto sr = - parse_structure_def(new_type.get(), ts, field_list_obj, options_obj, constants_to_use); + auto sr = parse_structure_def(new_type.get(), ts, field_list_obj, options_obj, constants); result.flags = sr.flags; result.create_runtime_type = sr.generate_runtime_type; structure_result = sr; @@ -891,8 +878,7 @@ DeftypeResult parse_deftype( ASSERT(pto); new_type->inherit(pto); ts->forward_declare_type_as(name, pto->get_name()); - auto sr = - parse_structure_def(new_type.get(), ts, field_list_obj, options_obj, constants_to_use); + auto sr = parse_structure_def(new_type.get(), ts, field_list_obj, options_obj, constants); result.flags = sr.flags; result.create_runtime_type = sr.generate_runtime_type; structure_result = sr; diff --git a/common/type_system/deftype.h b/common/type_system/deftype.h index a8270216e2..6c65117a20 100644 --- a/common/type_system/deftype.h +++ b/common/type_system/deftype.h @@ -17,9 +17,7 @@ struct DeftypeResult { bool create_runtime_type = true; }; -DeftypeResult parse_deftype( - const goos::Object& deftype, - TypeSystem* ts, - std::unordered_map* - constants = nullptr); +DeftypeResult parse_deftype(const goos::Object& deftype, + TypeSystem* ts, + goos::EnvironmentMap* constants = nullptr); TypeSpec parse_typespec(const TypeSystem* type_system, const goos::Object& src); diff --git a/common/util/crc32.h b/common/util/crc32.h index a874fe1888..4ce43c7cba 100644 --- a/common/util/crc32.h +++ b/common/util/crc32.h @@ -1,3 +1,5 @@ +#pragma once + #include #include "common/common_types.h" diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index 4f9ae87547..507455e353 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -125,10 +125,8 @@ class Compiler { // TODO - this should be able to be removed, these are stored in `m_symbol_info` std::unordered_map m_macro_specs; // TODO - this should be able to be removed, these are stored in `m_symbol_info` - std::unordered_map - m_symbol_types; - std::unordered_map - m_global_constants; + goos::InternedPtrMap m_symbol_types; + goos::InternedPtrMap m_global_constants; std::unordered_map m_inlineable_functions; CompilerSettings m_settings; diff --git a/goalc/compiler/Util.cpp b/goalc/compiler/Util.cpp index c37006966f..4400533eb1 100644 --- a/goalc/compiler/Util.cpp +++ b/goalc/compiler/Util.cpp @@ -314,7 +314,7 @@ bool Compiler::is_local_symbol(const goos::Object& obj, Env* env) { } // check global constants - if (m_global_constants.find(obj.as_symbol()) != m_global_constants.end()) { + if (m_global_constants.lookup(obj.as_symbol())) { return true; } diff --git a/goalc/compiler/compilation/Asm.cpp b/goalc/compiler/compilation/Asm.cpp index da831286b6..afc959481b 100644 --- a/goalc/compiler/compilation/Asm.cpp +++ b/goalc/compiler/compilation/Asm.cpp @@ -219,12 +219,11 @@ Val* Compiler::compile_asm_load_sym(const goos::Object& form, const goos::Object form, args, {{}, {goos::ObjectType::SYMBOL}}, {{"sext", {false, goos::ObjectType::SYMBOL}}, {"color", {false, goos::ObjectType::SYMBOL}}}); auto& sym_name = args.unnamed.at(1).as_symbol(); - auto sym_kv = m_symbol_types.find(sym_name); - if (sym_kv == m_symbol_types.end()) { + const auto* sym_ts = m_symbol_types.lookup(sym_name); + if (!sym_ts) { throw_compiler_error(form, "Cannot find a symbol named {}.", sym_name.name_ptr); } - auto ts = sym_kv->second; - bool sext = m_ts.lookup_type(ts)->get_load_signed(); + bool sext = m_ts.lookup_type(*sym_ts)->get_load_signed(); if (args.has_named("sext")) { sext = get_true_or_false(form, args.named.at("sext")); } diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index bdbcc8a4d6..90ab5de78d 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -388,13 +388,13 @@ SymbolVal* Compiler::compile_get_sym_obj(const std::string& name, Env* env) { Val* Compiler::compile_get_symbol_value(const goos::Object& form, const std::string& name, Env* env) { - auto existing_symbol = m_symbol_types.find(m_goos.intern_ptr(name)); - if (existing_symbol == m_symbol_types.end()) { + auto existing_symbol = m_symbol_types.lookup(m_goos.intern_ptr(name)); + if (!existing_symbol) { throw_compiler_error( form, "The symbol {} was looked up as a global variable, but it does not exist.", name); } - auto ts = existing_symbol->second; + const auto& ts = *existing_symbol; auto sext = m_ts.lookup_type_allow_partial_def(ts)->get_load_signed(); auto fe = env->function_env(); auto sym = fe->alloc_val(name, m_ts.make_typespec("symbol")); @@ -431,20 +431,20 @@ Val* Compiler::compile_symbol(const goos::Object& form, Env* env) { return lexical; } - auto global_constant = m_global_constants.find(form.as_symbol()); - auto existing_symbol = m_symbol_types.find(form.as_symbol()); + auto global_constant = m_global_constants.lookup(form.as_symbol()); + auto existing_symbol = m_symbol_types.lookup(form.as_symbol()); // see if it's a constant - if (global_constant != m_global_constants.end()) { + if (global_constant) { // check there is no symbol with the same name - if (existing_symbol != m_symbol_types.end()) { + if (existing_symbol) { throw_compiler_error(form, "Ambiguous symbol: {} is both a global variable and a constant and it " "is not clear which should be used here."); } // got a global constant - return compile_error_guard(global_constant->second, env); + return compile_error_guard(*global_constant, env); } // none of those, so get a global symbol. diff --git a/goalc/compiler/compilation/CompilerControl.cpp b/goalc/compiler/compilation/CompilerControl.cpp index f225eab41a..383ff92b80 100644 --- a/goalc/compiler/compilation/CompilerControl.cpp +++ b/goalc/compiler/compilation/CompilerControl.cpp @@ -362,7 +362,7 @@ std::string Compiler::make_symbol_info_description(const symbol_info::SymbolInfo switch (info->m_kind) { case symbol_info::Kind::GLOBAL_VAR: return fmt::format("[Global Variable] Type: {} Defined: {}", - m_symbol_types.at(m_goos.intern_ptr(info->m_name)).print(), + m_symbol_types.lookup(m_goos.intern_ptr(info->m_name))->print(), m_goos.reader.db.get_info_for(info->m_def_form)); case symbol_info::Kind::LANGUAGE_BUILTIN: return fmt::format("[Built-in Form] {}\n", info->m_name); @@ -379,7 +379,8 @@ std::string Compiler::make_symbol_info_description(const symbol_info::SymbolInfo case symbol_info::Kind::CONSTANT: return fmt::format( "[Constant] Name: {} Value: {} Defined: {}", info->m_name, - m_global_constants.at(m_goos.reader.symbolTable.intern(info->m_name.c_str())).print(), + m_global_constants.lookup(m_goos.reader.symbolTable.intern(info->m_name.c_str())) + ->print(), m_goos.reader.db.get_info_for(info->m_def_form)); case symbol_info::Kind::FUNCTION: return fmt::format("[Function] Name: {} Defined: {}", info->m_name, @@ -615,9 +616,9 @@ std::vector Compiler::lookup_exact_name_info( } std::optional Compiler::lookup_typespec(const std::string& symbol_name) { - const auto& it = m_symbol_types.find(m_goos.intern_ptr(symbol_name)); - if (it != m_symbol_types.end()) { - return it->second; + const auto it = m_symbol_types.lookup(m_goos.intern_ptr(symbol_name)); + if (it) { + return *it; } return {}; } @@ -686,7 +687,7 @@ Compiler::generate_per_file_symbol_info() { if (sym_info->m_kind == symbol_info::Kind::CONSTANT) { var.type = "unknown"; // Unfortunately, constants are not properly typed } else { - var.type = m_symbol_types.at(m_goos.intern_ptr(var.name)).base_type(); + var.type = m_symbol_types.lookup(m_goos.intern_ptr(var.name))->base_type(); } var.def_location = def_loc; if (sym_info->m_kind == symbol_info::Kind::GLOBAL_VAR) { @@ -701,8 +702,8 @@ Compiler::generate_per_file_symbol_info() { func.def_location = def_loc; func.args = Docs::get_args_from_docstring(sym_info->m_args, func.description); // The last arg in the typespec is the return type - const auto& func_type = m_symbol_types.at(m_goos.intern_ptr(func.name)); - func.return_type = func_type.last_arg().base_type(); + const auto func_type = m_symbol_types.lookup(m_goos.intern_ptr(func.name)); + func.return_type = func_type->last_arg().base_type(); file_doc.functions.push_back(func); } else if (sym_info->m_kind == symbol_info::Kind::TYPE) { Docs::TypeDocumentation type; diff --git a/goalc/compiler/compilation/ConstantPropagation.cpp b/goalc/compiler/compilation/ConstantPropagation.cpp index a63c096876..2a630005c8 100644 --- a/goalc/compiler/compilation/ConstantPropagation.cpp +++ b/goalc/compiler/compilation/ConstantPropagation.cpp @@ -187,13 +187,13 @@ Compiler::ConstPropResult Compiler::constant_propagation_dispatch(const goos::Ob } // it can either be a global or symbol - const auto& global_constant = m_global_constants.find(expanded.as_symbol()); - const auto& existing_symbol = m_symbol_types.find(expanded.as_symbol()); + const auto* global_constant = m_global_constants.lookup(expanded.as_symbol()); + const auto* existing_symbol = m_symbol_types.lookup(expanded.as_symbol()); // see if it's a constant - if (global_constant != m_global_constants.end()) { + if (global_constant) { // check there is no symbol with the same name, this is likely a bug and complain. - if (existing_symbol != m_symbol_types.end()) { + if (existing_symbol) { throw_compiler_error( code, "Ambiguous symbol: {} is both a global variable and a constant and it " @@ -201,7 +201,7 @@ Compiler::ConstPropResult Compiler::constant_propagation_dispatch(const goos::Ob } // got a global constant - return try_constant_propagation(global_constant->second, env); + return try_constant_propagation(*global_constant, env); } else { // return to the compiler, we can't figure it out. return {expanded, true}; diff --git a/goalc/compiler/compilation/Define.cpp b/goalc/compiler/compilation/Define.cpp index a91e515593..420961c58f 100644 --- a/goalc/compiler/compilation/Define.cpp +++ b/goalc/compiler/compilation/Define.cpp @@ -24,11 +24,11 @@ Val* Compiler::compile_define(const goos::Object& form, const goos::Object& rest auto& val = args.unnamed.at(1); // check we aren't duplicated a name as both a symbol and global constant - auto global_constant = m_global_constants.find(sym.as_symbol()); - if (global_constant != m_global_constants.end()) { + auto global_constant = m_global_constants.lookup(sym.as_symbol()); + if (global_constant) { throw_compiler_error( form, "Cannot define a symbol named {}, it already exists as a global constant (value {}).", - sym.print(), global_constant->second.print()); + sym.print(), global_constant->print()); } auto fe = env->function_env(); @@ -66,16 +66,16 @@ Val* Compiler::compile_define(const goos::Object& form, const goos::Object& rest throw_compiler_error(form, "Cannot define {} because it cannot be set.", sym_val->print()); } - auto existing_type = m_symbol_types.find(sym.as_symbol()); - if (existing_type == m_symbol_types.end()) { - m_symbol_types[sym.as_symbol()] = in_gpr->type(); + auto existing_type = m_symbol_types.lookup(sym.as_symbol()); + if (!existing_type) { + m_symbol_types.set(sym.as_symbol(), in_gpr->type()); } else { bool do_typecheck = true; if (args.has_named("no-typecheck")) { do_typecheck = !get_true_or_false(form, args.named.at("no-typecheck")); } if (do_typecheck) { - typecheck(form, existing_type->second, in_gpr->type(), + typecheck(form, *existing_type, in_gpr->type(), fmt::format("define on existing symbol {}", sym.as_symbol().name_ptr)); } } @@ -107,27 +107,26 @@ Val* Compiler::compile_define_extern(const goos::Object& form, const goos::Objec auto new_type = parse_typespec(typespec, env); - auto existing_type = m_symbol_types.find(sym.as_symbol()); + auto existing_type = m_symbol_types.lookup(sym.as_symbol()); // symbol already declared, and doesn't match existing definition. do more checks... - if (existing_type != m_symbol_types.end() && existing_type->second != new_type) { + if (existing_type && *existing_type != new_type) { if (m_allow_inconsistent_definition_symbols.find(symbol_string(sym)) == m_allow_inconsistent_definition_symbols.end()) { // throw if we have throws enabled, and new definition is NOT just more generic // (that case is fine in goal) - if (!m_ts.tc(new_type, existing_type->second) && m_throw_on_define_extern_redefinition) { + if (!m_ts.tc(new_type, *existing_type) && m_throw_on_define_extern_redefinition) { throw_compiler_error(form, "define-extern would redefine the type of symbol {} from {} to {}.", - symbol_string(sym), existing_type->second.print(), new_type.print()); + symbol_string(sym), existing_type->print(), new_type.print()); } else { print_compiler_warning( "define-extern has redefined the type of symbol {}\npreviously: {}\nnow: {}\n", - symbol_string(sym).c_str(), existing_type->second.print().c_str(), - new_type.print().c_str()); + symbol_string(sym).c_str(), existing_type->print().c_str(), new_type.print().c_str()); } } } - m_symbol_types[sym.as_symbol()] = new_type; + m_symbol_types.set(sym.as_symbol(), new_type); m_symbol_info.add_fwd_dec(symbol_string(sym), form); return get_none(); } diff --git a/goalc/compiler/compilation/Function.cpp b/goalc/compiler/compilation/Function.cpp index 838f2bb4c3..f88e1b50f6 100644 --- a/goalc/compiler/compilation/Function.cpp +++ b/goalc/compiler/compilation/Function.cpp @@ -346,8 +346,7 @@ Val* Compiler::compile_function_or_method_call(const goos::Object& form, Env* en if (uneval_head.as_symbol() == "inspect" || uneval_head.as_symbol() == "print") { is_method_call = true; } else { - if (is_local_symbol(uneval_head, env) || - m_symbol_types.find(uneval_head.as_symbol()) != m_symbol_types.end()) { + if (is_local_symbol(uneval_head, env) || m_symbol_types.lookup(uneval_head.as_symbol())) { // the local environment (mlets, lexicals, constants, globals) defines this symbol. // this will "win" over a method name lookup, so we should compile as normal head = compile_error_guard(args.unnamed.front(), env); diff --git a/goalc/compiler/compilation/Macro.cpp b/goalc/compiler/compilation/Macro.cpp index 01115b860d..52d5c436a4 100644 --- a/goalc/compiler/compilation/Macro.cpp +++ b/goalc/compiler/compilation/Macro.cpp @@ -196,19 +196,19 @@ Val* Compiler::compile_define_constant(const goos::Object& form, // GOAL constant if (goal) { - if (m_symbol_types.find(sym) != m_symbol_types.end()) { + if (m_symbol_types.lookup(sym)) { throw_compiler_error(form, "Cannot define {} as a constant because " "it is already the name of a symbol of type {}", - sym.name_ptr, m_symbol_types.at(sym).print()); + sym.name_ptr, m_symbol_types.lookup(sym)->print()); } - auto existing = m_global_constants.find(sym); - if (existing != m_global_constants.end() && existing->second != value) { + auto existing = m_global_constants.lookup(sym); + if (existing && *existing != value) { print_compiler_warning("Constant {} has been redefined {} -> {}", sym.name_ptr, - existing->second.print(), value.print()); + existing->print(), value.print()); } - m_global_constants[sym] = value; + m_global_constants.set(sym, value); } // GOOS constant diff --git a/goalc/compiler/compilation/State.cpp b/goalc/compiler/compilation/State.cpp index e47c346561..9f7eb989eb 100644 --- a/goalc/compiler/compilation/State.cpp +++ b/goalc/compiler/compilation/State.cpp @@ -98,10 +98,10 @@ Val* Compiler::compile_define_state_hook(const goos::Object& form, } auto& state_name = args.unnamed.at(0).as_symbol(); - auto existing_var = m_symbol_types.find(state_name); + auto existing_var = m_symbol_types.lookup(state_name); TypeSpec type_to_use; - if (existing_var == m_symbol_types.end()) { + if (!existing_var) { // we're a new state. we must have a type. if (!state_type) { throw_compiler_error(form, @@ -110,11 +110,11 @@ Val* Compiler::compile_define_state_hook(const goos::Object& form, state_name.name_ptr); } type_to_use = *state_type; - m_symbol_types[state_name] = *state_type; + m_symbol_types.set(state_name, *state_type); } else { - type_to_use = existing_var->second; + type_to_use = *existing_var; if (state_type) { - typecheck(form, existing_var->second, *state_type, + typecheck(form, *existing_var, *state_type, fmt::format("type of state {}", state_name.name_ptr)); } } diff --git a/goalc/compiler/compilation/Static.cpp b/goalc/compiler/compilation/Static.cpp index ba2a784fab..d20c8b75cc 100644 --- a/goalc/compiler/compilation/Static.cpp +++ b/goalc/compiler/compilation/Static.cpp @@ -700,10 +700,10 @@ StaticResult Compiler::compile_static(const goos::Object& form_before_macro, Env } // as a constant - auto kv = m_global_constants.find(form.as_symbol()); - if (kv != m_global_constants.end()) { + auto kv = m_global_constants.lookup(form.as_symbol()); + if (kv) { // expand constant and compile again. - return compile_static(kv->second, env); + return compile_static(*kv, env); } else { throw_compiler_error(form, "The symbol {} could not be evaluated at compile time", form.print()); diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index c871f916a5..f110390d67 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -386,33 +386,32 @@ Val* Compiler::compile_deftype(const goos::Object& form, const goos::Object& res auto result = parse_deftype(rest, &m_ts, &m_global_constants); // look up the type name - auto kv = m_symbol_types.find(m_goos.intern_ptr(result.type.base_type())); - if (kv != m_symbol_types.end() && kv->second.base_type() != "type") { + auto kv = m_symbol_types.lookup(m_goos.intern_ptr(result.type.base_type())); + if (kv && kv->base_type() != "type") { // we already have something that's not a type with the same name, this is bad. lg::print("[Warning] deftype will redefine {} from {} to a type.\n", result.type.base_type(), - kv->second.print()); + kv->print()); } // remember that this is a type - m_symbol_types[m_goos.intern_ptr(result.type.base_type())] = m_ts.make_typespec("type"); + m_symbol_types.set(m_goos.intern_ptr(result.type.base_type()), m_ts.make_typespec("type")); // add declared states for (auto& state : result.type_info->get_states_declared_for_type()) { auto interned_state_first = m_goos.intern_ptr(state.first); - auto existing_type = m_symbol_types.find(interned_state_first); - if (existing_type != m_symbol_types.end() && existing_type->second != state.second) { + auto existing_type = m_symbol_types.lookup(interned_state_first); + if (existing_type && *existing_type != state.second) { if (m_throw_on_define_extern_redefinition) { throw_compiler_error(form, "deftype would redefine the type of state {} from {} to {}.", - state.first, existing_type->second.print(), state.second.print()); + state.first, existing_type->print(), state.second.print()); } else { print_compiler_warning( "[Warning] deftype has redefined the type of state {}\npreviously: {}\nnow: " "{}\n", - state.first.c_str(), existing_type->second.print().c_str(), - state.second.print().c_str()); + state.first.c_str(), existing_type->print().c_str(), state.second.print().c_str()); } } - m_symbol_types[interned_state_first] = state.second; + m_symbol_types.set(interned_state_first, state.second); m_symbol_info.add_fwd_dec(state.first, form); } @@ -1444,12 +1443,12 @@ Val* Compiler::compile_declare_type(const goos::Object& form, const goos::Object m_ts.forward_declare_type_as(type_name.name_ptr, kind); - auto existing_type = m_symbol_types.find(type_name); - if (existing_type != m_symbol_types.end() && existing_type->second != TypeSpec("type")) { + auto existing_type = m_symbol_types.lookup(type_name); + if (existing_type && *existing_type != TypeSpec("type")) { throw_compiler_error(form, "Cannot forward declare {} as a type: it is already a {}", - type_name.name_ptr, existing_type->second.print()); + type_name.name_ptr, existing_type->print()); } - m_symbol_types[type_name] = TypeSpec("type"); + m_symbol_types.set(type_name, TypeSpec("type")); return get_none(); } diff --git a/goalc/compiler/symbol_info.cpp b/goalc/compiler/symbol_info.cpp index 2930ad9da7..d5832b7c94 100644 --- a/goalc/compiler/symbol_info.cpp +++ b/goalc/compiler/symbol_info.cpp @@ -239,7 +239,7 @@ void SymbolInfoMap::add_builtin(const std::string& name, const std::string& docs void SymbolInfoMap::add_method(const std::string& method_name, const std::vector& args, const MethodInfo& method_info, - const goos::Object& defining_form) { + const goos::Object& /*defining_form*/) { SymbolInfo info = { .m_kind = Kind::METHOD, .m_name = method_name,