void CCodeGenerator::operator()(Construct* expr) { // Look up the function by name in the current context. String::Ptr id = env_->name("@init"); Class::Ptr clazz = expr->type()->clazz(); Function::Ptr func = clazz->function(id); std::vector<Operand> args; for (Expression::Ptr a = expr->arguments(); a; a = a->next()) { args.push_back(emit(a)); } return_ = alloc_temp(clazz->type()); out_ << func->label() << "("; Formal::Ptr formal = func->formals(); Expression::Ptr arg = expr->arguments(); for (int i = 0; i < args.size(); i++) { if(!formal->is_self() && !formal->type()->equals(arg->type())) { // Cast to the appropriate C-type, since C doesn't know anything // about subtypes, etc.. out_ << "("; operator()(formal->type()); out_ << ")"; } out_ << args[i]; if (i < args.size() - 1) { out_ << ", "; } formal = formal->next(); arg = arg->next(); } out_ << ");\n"; }
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); }