Files
jak-project/goalc/compiler/compilation/Define.cpp
T
2020-09-07 13:28:16 -04:00

42 lines
1.8 KiB
C++

#include "goalc/compiler/Compiler.h"
Val* Compiler::compile_define(const goos::Object& form, const goos::Object& rest, Env* env) {
auto args = get_va(form, rest);
va_check(form, args, {goos::ObjectType::SYMBOL, {}}, {});
auto& sym = args.unnamed.at(0);
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()) {
throw_compile_error(
form, "it is illegal to define a GOAL symbol with the same name as a GOAL global constant");
}
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto sym_val = fe->alloc_val<SymbolVal>(symbol_string(sym), m_ts.make_typespec("symbol"));
auto compiled_val = compile_error_guard(val, env);
auto as_lambda = dynamic_cast<LambdaVal*>(compiled_val);
if (as_lambda) {
// there are two cases in which we save a function body that is passed to a define:
// 1. It generated code [so went through the compiler] and the allow_inline flag is set.
// 2. It didn't generate code [so explicitly with :inline-only lambdas]
// The third case - immediate lambdas - don't get passed to a define,
// so this won't cause those to live for longer than they should
if ((as_lambda->func && as_lambda->func->settings.allow_inline) || !as_lambda->func) {
m_inlineable_functions[sym.as_symbol()] = as_lambda;
}
}
auto in_gpr = compiled_val->to_gpr(fe);
auto existing_type = m_symbol_types.find(sym.as_symbol()->name);
if (existing_type == m_symbol_types.end()) {
m_symbol_types[sym.as_symbol()->name] = in_gpr->type();
} else {
typecheck(form, existing_type->second, in_gpr->type(), "define on existing symbol");
}
fe->emit(std::make_unique<IR_SetSymbolValue>(sym_val, in_gpr));
return in_gpr;
}