/*! * @file GoalBlockForms.cpp * GOAL Compiler Forms related to blocks. */ #include "Goal.h" #include "GoalEnv.h" #include "util.h" /*! * Compile a list of forms. The top-level form is the same as a begin, but top-levels are generated * by the reader when reading a file. */ std::shared_ptr Goal::compile_top_level(const Object& form, Object rest, std::shared_ptr env) { return compile_begin(form, rest, env); } /*! * Compile begin statement. Just compile everything in order and return the last thing. * If there's nothing in it, return none. */ std::shared_ptr Goal::compile_begin(const Object& form, Object rest, std::shared_ptr env) { (void)form; std::shared_ptr result = get_none(); for_each_in_list(rest, [&](Object o) { result = compile_error_guard(o, env); }); return result; } /*! * Compile a block statement. * This pushes a block environment and is like a begin. * It returns the last thing in the list, unless you jump to the end with a return-from. * The type of the return-from's are checked! */ std::shared_ptr Goal::compile_block(const Object& form, Object rest, std::shared_ptr env) { auto name = pair_car(rest); rest = pair_cdr(rest); if (rest.type != PAIR) { throw_compile_error(form, "Block form has an empty body"); } // create environment auto block_env = std::make_shared(env, symbol_string(name)); // we need to create a return value register, as a "return-from" statement inside the block may // set it. for now it has a type of none, but we will set it more accurate after compiling the // block. block_env->return_value = env->alloc_reg(get_base_typespec("none")); // create label to the end of the block (we don't yet know where it is...) block_env->end_label = std::make_shared