Example #1
0
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);
}
Example #2
0
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();
        }
    }
}
Example #3
0
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_);
        }
    }
}
Example #4
0
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;
}
Example #5
0
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);
}