Add auto-generated inspect methods to deftypes

This commit is contained in:
Tyler Wilding
2020-10-15 00:34:52 -04:00
parent 8d91b47d00
commit c72ca18f00
2 changed files with 78 additions and 0 deletions
+6
View File
@@ -116,6 +116,12 @@ class Compiler {
Val* compile_variable_shift(const RegVal* in, const RegVal* sa, Env* env, IntegerMathKind kind);
Val* compile_format_string(const goos::Object& form,
Env* env,
std::string& fmt_template,
std::vector<RegVal*> args,
const std::string& out_stream = "#t");
Val* generate_inspector_for_type(const goos::Object& form, Env* env, Type* type);
RegVal* compile_get_method_of_type(const TypeSpec& type,
const std::string& method_name,
Env* env);
+72
View File
@@ -85,6 +85,75 @@ RegVal* Compiler::compile_get_method_of_object(RegVal* object,
return deref->to_reg(env);
}
Val* Compiler::compile_format_string(const goos::Object& form,
Env* env,
std::string& fmt_template,
std::vector<RegVal*> args,
const std::string& out_stream) {
// Add first two format args
args.insert(args.begin(), compile_string(fmt_template, env, DEBUG_SEGMENT)->to_reg(env));
args.insert(args.begin(), compile_get_sym_obj(out_stream, env)->to_reg(env));
// generate code in the method_env
auto format_function = compile_get_symbol_value("_format", env)->to_gpr(env);
return compile_real_function_call(form, format_function, args, env);
}
Val* Compiler::generate_inspector_for_type(const goos::Object& form, Env* env, Type* type) {
auto as_structure_type = dynamic_cast<StructureType*>(type);
if (!as_structure_type) { // generate the inspect method
return get_none();
}
StructureType* structured_type = as_structure_type;
// Create a function environment to hold the code for the inspect method. The name is just for
// debugging.
auto method_env = std::make_unique<FunctionEnv>(env, "autogenerated-inspect-method");
// put the method in the debug segment.
method_env->set_segment(DEBUG_SEGMENT);
// Create a register which will hold the input to the inspect method
auto input = method_env->make_ireg(structured_type->get_name(), emitter::RegKind::GPR);
// "Constraint" this register to be the register that the function argument is passed in
IRegConstraint constraint;
constraint.instr_idx = 0; // constraint at the start of the function
constraint.ireg = input->ireg(); // constrain this register
constraint.desired_register = emitter::gRegInfo.get_arg_reg(0); // to the first argument
method_env->constrain(constraint);
std::string str_template = "";
std::vector<RegVal*> formatArgs = {};
// Check if there are no fields
if (structured_type->fields().empty()) {
str_template = "Type has no fields!~%";
} else {
for (Field f : structured_type->fields()) {
str_template += "~A~%";
formatArgs.push_back(
compile_string(f.print(), method_env.get(), DEBUG_SEGMENT)->to_reg(method_env.get()));
}
}
compile_format_string(form, method_env.get(), str_template, formatArgs);
// add this function to the object file
auto fe = get_parent_env_of_type<FunctionEnv>(env);
auto method = fe->alloc_val<LambdaVal>(m_ts.make_typespec("function"));
method->func = method_env.get();
auto obj_env_inspect = get_parent_env_of_type<FileEnv>(method_env.get());
obj_env_inspect->add_function(std::move(method_env));
// call method-set!
auto type_obj = compile_get_symbol_value(structured_type->get_name(), env)->to_gpr(env);
auto id_val = compile_integer(m_ts.lookup_method(structured_type->get_name(), "inspect").id, env)
->to_gpr(env);
auto method_set_val = compile_get_symbol_value("method-set!", env)->to_gpr(env);
return compile_real_function_call(form, method_set_val, {type_obj, id_val, method->to_gpr(env)},
env);
}
/*!
* Compile a (deftype ... form)
*/
@@ -113,6 +182,9 @@ Val* Compiler::compile_deftype(const goos::Object& form, const goos::Object& res
auto flags_int = compile_integer(result.flags.flag, env)->to_gpr(env);
compile_real_function_call(form, new_type_method, {new_type_symbol, parent_type, flags_int}, env);
// Auto-generate (inspect) method
generate_inspector_for_type(form, env, result.type_info);
// return none, making the value of (deftype..) unusable
return get_none();
}