void CodeExpander::stub(Function* func, Attribute* attr) { // Create a stub which calls through to the nested class function. std::string name = func->name()->string(); if (name == "@init" || name == "@destroy" || name == "@copy") { return; } if ((class_->feature(func->name()) != func) || func->is_private()) { return; } if (class_->is_interface()) { return; } String::Ptr nm = func->name(); Feature::Flags flags = func->flags() & ~(Feature::NATIVE); Formal::Ptr f = func->formals(); Type::Ptr type = func->type(); Location loc = class_->location(); Expression::Ptr args; Expression::Ptr self(new IdentifierRef(loc, env_->name(""), attr->name())); for (Formal::Ptr f = func->formals(); f; f = f->next()) { Expression::Ptr arg; if (f->name()->string() == "__self") { arg = self; } else { arg = new IdentifierRef(loc, env_->name(""), f->name()); } arg->type(f->type()); args = append(args.pointer(), arg.pointer()); } Expression::Ptr mem(new Member(loc, self, func->name())); Call::Ptr call(new Call(loc, mem, args)); call->function(func); call->type(func->type()); Expression::Ptr stmt; if (func->type()->is_void()) { stmt = call.pointer(); } else { stmt = new Return(loc, call); stmt->type(env_->void_type()); call->type(func->type()); } Block::Ptr block(new Block(loc, 0, stmt)); block->type(env_->void_type()); Function::Ptr stub(new Function(loc, env_, nm, f, flags, type, block)); class_->feature(stub); semant_->operator()(stub); }
void CCodeGenerator::ctor_preamble(Class* clazz) { // Emits the memory alloc/vtable setup for the class. Also initializes // the reference count for dynamically allocated types. if (clazz->is_object()) { line(); operator()(clazz->type()); out_ << " self = Boot_calloc(sizeof(struct "; operator()(clazz->type()); out_ << "));\n"; line(); out_ << "self->_refcount = 1;\n"; line(); out_ << "self->_vtable = "; operator()(clazz->type()); out_ << "__vtable;\n"; } // Emit initializer code for initialized attributes for (Feature::Ptr f = clazz->features(); f; f = f->next()) { if (Attribute::Ptr attr = dynamic_cast<Attribute*>(f.pointer())) { Expression::Ptr init = attr->initializer(); if (!init || dynamic_cast<Empty*>(init.pointer())) { continue; } line(); Operand value = emit(init); out_ << "self->" << attr->name() << " = " << value << ";\n"; //free_temps(); } } }
void CCodeGenerator::operator()(Assignment* expr) { // Handle all types of assignment, including member assignment Expression::Ptr init = expr->initializer(); if (dynamic_cast<Empty*>(init.pointer())) { return_ = Operand(env_->integer("0")); } else { return_ = emit(init); } String::Ptr id = expr->identifier(); Variable::Ptr var = variable(id); Attribute::Ptr attr = class_ ? class_->attribute(id) : 0; if (var) { // Assignment to a local var that has already been initialized once in // the current scope. Type::Ptr type = var->type(); if (!type->is_value()) { refcount_dec(Operand(var->name())); } line(); out_ << id->string() << " = " << return_ << ";\n"; if (!type->is_value()) { refcount_inc(Operand(var->name())); } } else if (attr) { // Assignment to an attribute within a class /* Type::Ptr type = expr->type(); Variable::Ptr self = variable(env_->name("__self")); Operand addr = Operand::addr(, attr->slot()); Operand old = load(addr); if (!type->is_value() && !attr->is_weak()) { refcount_dec(old); } store(addr, return_); if (!type->is_value() && !attr->is_weak()) { refcount_inc(return_); } */ assert(!"not impl"); } else { // Assignment to a local var that has not yet been initialized in the // current scope. Type::Ptr declared = expr->declared_type(); if (declared->is_top()) { declared = expr->type(); } line(); brace(); operator()(declared); out_ << " " << id->string() << " = " << return_ << "; "; out_ << "(void)" << id->string() << ";\n"; variable(new Variable(id, declared)); if (!declared->is_value()) { refcount_inc(return_); } } }
void CCodeGenerator::operator()(Return* statement) { Expression::Ptr expr = statement->expression(); source_line(statement); if (!dynamic_cast<Empty*>(expr.pointer())) { Operand ret = emit(expr); return_val_ = ret; // Increment the refcount if the returned value is an object. The // refcount must be incremented so that the object won't be freed // when the function returns. It is the caller's responsibility to // correctly free the returned object. if (!expr->type()->is_value()) { refcount_inc(ret); } } block_has_return_ = true; }
void CodeExpander::functor(Class* clazz) { // Generate the @call method for the functor, which contains a switch on // the type of the arugment passed to @call method. Function::Ptr func = clazz->function(env_->name("@call")); Location loc = clazz->location(); String::Ptr fn = func->formals()->next()->name(); IdentifierRef::Ptr guard(new IdentifierRef(loc, env_->name(""), fn)); Expression::Ptr stmt; for (Feature::Ptr feat = clazz->features(); feat; feat = feat->next()) { if (Function* func = dynamic_cast<Function*>(feat.pointer())) { String* nm = func->name(); if (nm->string().find("@case") == 0) { // This is a functor case, so generate a branch for it. Each // branch looks like this: self.@case_Type(obj) Type::Ptr type = func->formals()->next()->type(); Expression::Ptr arg0(new IdentifierRef(loc, env_->name(""), env_->name("__self"))); Expression::Ptr arg1(new Cast(loc, type, new IdentifierRef(loc, env_->name(""), fn))); arg0->type(func->formals()->type()); arg1->type(func->formals()->next()->type()); Expression::Ptr arg; arg = append(arg.pointer(), arg0.pointer()); arg = append(arg.pointer(), arg1.pointer()); IdentifierRef::Ptr id(new IdentifierRef(loc, env_->name(""), nm)); Call::Ptr expr(new Call(loc, id, arg)); expr->function(func); Is::Ptr is(new Is(loc, guard, type)); stmt = new Conditional(loc, is, expr, stmt); } } } Block::Ptr block = new Block(loc, env_->string(""), stmt); func->block(block); func->is_checked(false); semant_->operator()(func); }