📄 function.cpp.svn-base
字号:
{
int mfb = Parser::global().alloc(sizeof(FBlock),NULL);
FBlock *pf = (FBlock *)Parser::global().addr(mfb);
pf->context = NULL;
pf->nlocal = 0;
pf->nargs = 0;
pf->ntotal = 0;
pf->entry = pe;
pf->pstart = NULL;
pf->class_ptr = pc;
pf->data = NULL;
pf->trace = NULL;
return pf;
}
void FBlock::finalize(int sz)
{
pstart = Parser::code().end_code();
nlocal = sz/sizeof(int); // our _total_ context size in _dwords_!
ntotal = nlocal + nargs; // add args to get total size
//class_ptr = NULL; // for now!!
}
int NFBlock::create(Function *pfn, CALLFN fn)
{
PFBlock pfb = pfn->fun_block();
// set up native code call block;
NFBlock fblk;
fblk.pfn = fn;
fblk.nargs = pfn->stdarg() ? -1 : pfb->nargs;
fblk.flags = pfn->is_cdecl() ? DC_CDECL : 0;
// *add 1.1.0 Sometimes imported methods use the cdecl calling convention;
// the 'this' pointer becomes a hidden extra argument.
if (pfn->is_method() && pfn->is_cdecl())
fblk.nargs++;
Type rt = pfn->return_type(); //sig.m_type;
// Some schemes use half-assed cdecl convention for returning objects
// *add 1.2.6 add support for true return by value (GCC3)
ImportScheme* import = pfn->import_scheme();
if (import && rt.is_object() && import->ret_obj_popped()) {
if (! import->true_return_by_value(rt))
fblk.flags += DC_RET_OBJ;
else
fblk.flags += DC_RET_VAL | DC_NOWORD;
}
else
if (! rt.is_pointer()) {
fblk.flags += rt.is_double() ? DC_QWORD : 0;
fblk.flags += rt.is_void() ? DC_NOWORD : 0;
} // otherwise a pointer is of course the default: 4 bytes.
return Parser::global().alloc(sizeof(fblk),&fblk);
}
////
Function::Function(Signature *sig, FunctionEntry *pfe)
: m_sig(sig),m_context(NULL),m_slot_id(0),m_fun_entry(pfe),
m_default_args(NULL),m_stdarg(false),m_builtin(false),
m_line_nos(NULL),m_templ_info(NULL),m_import_scheme(NULL)
{
m_fun_block = FBlock::create(pfe->reference(),class_context());
m_fun_block->function = this;
m_line = Input::lineno();
Module* pm = Module::current();
m_mod = pm ? pm->id() : -1;
}
Function::~Function()
{
delete m_line_nos;
}
bool Function::undefined()
{
return m_fun_block->pstart == NULL;
}
void
Function::set_construct_destruct(int ftype, bool no_implicit_type_conversion)
{
m_ftype = ftype;
Class *pc = class_context();
//if (!is_plain() && pc) fail("must be within class definition");
if (is_destructor()) {
if(signature()->size() > 0) fail("destructor cannot be passed parameters");
pc->destructor(this);
} else
if (is_constructor()) pc->add_constructor(this,no_implicit_type_conversion);
}
string
Function::name()
{
return fun_entry()->reference()->name;
}
void Function::attach_context(FunctionContext *context)
{
// since this happens whenever a function is being redefined, we call clear()!!
clear();
m_context = context;
m_fun_block->context = m_context;
}
void Function::clear()
// this is used when we are interactively redefining a function;
// an opportunity to dispose of code, etc
{
// *NOTE* blew up trying to delete this....how was it alloc?
//delete m_fun_block->context;
// line number info
delete m_line_nos;
m_line_nos = new LineNumbers;
// function block
m_fun_block->nargs = 0;
}
void Function::slot_id(int i)
{
m_slot_id = i;
}
void
Function::set_default_args(PExprList pel)
// ONLY called if there _were_ any default values for arguments
// Hmm...we must watch out here!
{
int k=0;
m_default_args = new ExprArray(0 /*pel->size()*/);
m_default_index = -1;
ExprList::iterator eli;
for (eli = pel->begin(); eli != pel->end(); ++eli,++k)
if (*eli != NULL) {
if (m_default_index == -1) m_default_index = k;
m_default_args->push_back(*eli);
}
}
bool
Function::can_match(int size)
// can this function in principle match an argument list of a particular size?
{
int asz = signature()->size();
if (!m_default_args) {
if (stdarg()) return size >= asz;
else return size == asz;
} else
return size >= m_default_index && size <= asz;
}
PExprList
Function::complete_arg_list(PExprList args)
{
if (!m_default_args) return NULL;
if (args->size() < signature()->size()) {
PExprList pdef = new ExprList(m_default_args->begin() + args->size()-m_default_index,
m_default_args->end());
args->insert(args->end(),pdef->begin(),pdef->end());
return pdef;
} else return NULL;
}
void Function::dump(ostream& os)
{
Signature::set_fun_name(name(),is_constructor(),is_destructor());
os << *signature();
}
string Function::as_str()
{
char buffer[MAX_FUN_NAME];
ostrstream out(buffer,MAX_FUN_NAME);
dump(out);
out << ends;
return buffer;
}
Function *
Function::from_fun_block(FBlock *pfb)
{
FunctionEntry *pfe = (FunctionEntry *) pfb->entry->data;
return pfe->fun_from_fblock(pfb);
}
// do note that this version only works for non-overloaded functions!
Function *
Function::lookup(const string& nm)
{
PEntry pe = Parser::symbol_lookup(nm);
if (!pe || !pe->type.is_signature()) return NULL;
FunctionEntry *pfe = (FunctionEntry *)pe->data; // shd be a method, really
return pfe->back();
}
void FunctionEntry::dump (ostream& os)
{
iterator ife;
int idx = 1;
for (ife = begin(); ife != end(); ++ife) {
Function *pf = *ife;
os << idx++ << ' ';
pf->dump(os);
if (pf->is_virtual()) os << " - slot " << pf->slot_id();
os << endl;
}
Signature::set_fun_name("");
}
Function *
FunctionEntry::nth_fun(int idx)
{
iterator fei = begin();
Function *fn;
if (idx == 0) idx = 1;
if (idx >= size()) idx = size();
for(int i = 1; i <= size(); ++i, ++fei)
if (i == idx) { fn = *fei; break; }
return fn;
}
Function *
FunctionEntry::fun_from_fblock(FBlock *pfb)
{
for(iterator fei = begin(); fei != end(); ++fei)
if ((*fei)->fun_block()==pfb) return *fei;
return NULL;
}
// these odd little functions are useful when debugging the system,
// since Visual Studio and GDB will happily execute them for you on request.
static char buff[60];
char *sh_sig(Signature& s)
{
*buff = 0;
ostrstream outs(buff,60);
outs << s << ends;
return buff;
}
char *sh_type(Type& t)
{
*buff = 0;
ostrstream outs(buff,60);
outs << t << ends;
return buff;
}
// *change 1.2.3a 'do_strict' insists that the signatures match exactly; otherwise
// we allow for looser matches (particularly method signatures)
bool Signature::match(const Signature& sig, bool do_strict) const
{
// Comparing signatures
// *fix 1.2.2b (Eric) Functions w/ no args can be incorrectly matched
if (this == &sig) return true;
if (size() != sig.size() || !class_ptr() != !sig.class_ptr()) return false;
// *fix 1.2.3 Method signatures made tighter in 'exact match' mode
if (class_ptr() != NULL && sig.class_ptr() != NULL) {
if ((do_strict && class_ptr() != sig.class_ptr())
|| !sig.class_ptr()->inherits_from(class_ptr()))
return false; // *fix 1.2.1 Member function signatures are distinct!
}
if (is_const() != sig.is_const())
return false; // *fix 0.9.6 constness makes signatures distinct
if (stdarg() != sig.stdarg())
return false; // *fix 1.2.3 (Eric) And so does whether this is stdarg or not
Signature::iterator ti,tio;
try {
for(ti = begin(), tio = sig.begin(); ti != end(); ++ti,++tio)
if (!(*ti == *tio)) return false;
} catch(...) {
return false;
}
//* return tio == sig.end() && ti == end(); //true;
return true;
}
#pragma optimize( "", off )
static Function *_fn;
Function *
FunctionEntry::simple_match(Signature *sig)
{
iterator ife;
for (ife = begin(); ife != end(); ++ife) {
_fn = *ife;
if (_fn == NULL)
return NULL;
if (_fn->signature()->match(*sig)) return *ife;
}
return NULL; // for now...
}
Function *
FunctionEntry::full_match(Signature *)
{
// basically not implemented!
return back();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -