// Resolve a name that refers to a type. Type& make_type(Context& cxt, Name& n) { if (Simple_id* id = as<Simple_id>(&n)) return make_type(cxt, *id); lingo_unhandled(n); }
// Resolve a name that refers to a type. Type& resolve_id_type(Context& cxt, Name& n) { if (Simple_id* id = as<Simple_id>(&n)) return resolve_simple_id_type(cxt, *id); lingo_unhandled(n); }
// The identifier is not an object or function. static Expr& make_error_ref(Context& cxt, Decl& d) { // Here are some things that lookup can find that are not // valid expressions. // // TODO: Diagnose the error and point to the declaration. if (Type_decl* t = as<Type_decl>(&d)) throw Type_error("'{}' is not an object or function", t->name()); lingo_unhandled(d); }
// FIXME: Can we actually have variables in a member? Probably, if it's a // static member variable. Same goes for member functions. Expr& make_member_reference(Context& cxt, Expr& obj, Decl& decl) { // References to non-static members. if (Field_decl* v = as<Field_decl>(&decl)) return cxt.make_member_reference(obj, *v); if (Method_decl* f = as<Method_decl>(&decl)) return cxt.make_member_reference(obj, *f); // References to static members. if (Variable_decl* v = as<Variable_decl>(&decl)) return cxt.make_reference(*v); if (Function_decl* f = as<Function_decl>(&decl)) return cxt.make_reference(*f); if (is<Type_decl>(&decl)) { error(cxt, "'{}' does not name a member variable or member function", decl.name()); throw Type_error("invalid reference"); } lingo_unhandled(decl); }
// Determine if e can be contextually converted to bool, and if so, // returns the expression that produces a boolean value from `e`. // // Contextual conversion to bool tries to do this: // // var b : bool = e; // // so we preform copy initialization, and then yield the converted // expression that will be used to initialize b. Expr& contextual_conversion_to_bool(Context& cxt, Expr& e) { // Synthesize a declaration. // // TODO: This epitomizes our need for smarter memory management. I // really want this declaration and its associated nodes to evaporate // when the function returns. Note that the initialization and // conversion are allocated in the main arena. Variable_decl& var = cxt.make_variable_declaration("b", cxt.get_bool_type()); // Actually perform the copy initialization. Expr& init = copy_initialize(cxt, var, e); // Based on the initializer selected, we can either: // 1. return the converted value directly // 2. synthesize an object using a constructor // 3. invoke a user-defined conversion if (Copy_init* i = as<Copy_init>(&init)) return i->expression(); lingo_unhandled(init); }
void operator()(Decl const& d) { lingo_unhandled(d); }
char const* operator()(Decl const& d) { lingo_unhandled(d); }
Expr& operator()(Name& n) { lingo_unhandled(n); }
Expr& operator()(Decl& d) { lingo_unhandled(d); }
void operator()(Def& d) { lingo_unhandled(d); }
std::size_t operator()(Type const& t) const { lingo_unhandled(t); }
Type& operator()(Type& t) { lingo_unhandled(t); }
bool operator()(Type const& t) { lingo_unhandled(t); }
void operator()(Tuple_type const& t) { lingo_unhandled(t); }
void operator()(Array_type const& t) { lingo_unhandled(t); }
llvm::Type* operator()(Type const& t) { lingo_unhandled(t); }