⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mal_instruction.mx

📁 一个内存数据库的源代码这是服务器端还有客户端
💻 MX
📖 第 1 页 / 共 5 页
字号:
			mb->stmt[i] = mb->stmt[i - 1];		mb->stmt[i] = p;	}}voidinsertInstruction(MalBlkPtr mb, InstrPtr p, int pc){	pushInstruction(mb, p);	/* to ensure room */	moveInstruction(mb, mb->stop - 1, pc);}@-Beware that the first argument of a signature is reserved for the functionreturn type , which should be equal to the destination variable type.VarRecords are allocated on the variable stack.Their index is returned for future reference.@-Use the information that a variable is at least one characterwide and terminated by a null-byte.This means that we can speed up search when the variablesdiffer in the first two charactersFurthermore, temporary variables are already assigned to a specificposition in the variable table. This information can only be usedunder the assumption that the code base is not modified on thefly. Then the expensive search is started anyway.It also means that input which does not comply with the intendedlocation of a temporary variable should be flagged as an error.@= chkTemporary    if( isTmpName(name)){		int j;        i= atol(name+1);        /* quick test validity*/        if( i< mb->vtop && isTmpVar(mb,i) && getVarTmp(mb,i) == i)            return i;		for(j=0; j< mb->vtop; j++)			if( getVarTmp(mb,j)== i && isTmpVar(mb,j)) return j;        return -1;    }@-Temporary names are not materialized as strings unless necessary.@cINLINE strgetVarName(MalBlkPtr mb, int i){	str nme;	char buf[PATHLENGTH];	nme = mb->var[i]->name;	if (nme == 0) {		snprintf(buf, PATHLENGTH, "%c%d", TMPMARKER, mb->var[i]->tmpindex);		nme = mb->var[i]->name = GDKstrdup(buf);	}	return nme;}INLINE strgetRefName(MalBlkPtr mb, int i){	str nme;	char buf[PATHLENGTH];	nme = mb->var[i]->name;	if (nme == 0) {		snprintf(buf, PATHLENGTH, "%c%d", REFMARKER, mb->var[i]->tmpindex);		nme = mb->var[i]->name = GDKstrdup(buf);	}	return nme;}@cintfindVariable(MalBlkPtr mb, str name){	int i;	@:chkTemporary@	if (name == NULL)		return -1;	for (i = mb->vtop - 1; i >= 0; i--)		if (!isTmpVar(mb, i) && idcmp(name, getVarName(mb, i)) == 0)			return i;	return -1;}intfindTmpVariable(MalBlkPtr mb, int type){	int i;	for (i = 0; i < mb->vtop; i++)		if (isTmpVar(mb, i) && getVarType(mb, i) == type)			return i;	return -1;}@-The second version of findVariable assumes you have notyet allocated a private structure. This is particularlyusefull during parsing, because most variables are alreadydefined. This way we safe GDKmalloc/GDKfree.@cintfindVariableLength(MalBlkPtr mb, str name, int len){	int i;	int j;	for (i = mb->vtop - 1; i >= 0; i--)		if (mb->var[i]->name && !isTmpVar(mb, i)) {			str s = mb->var[i]->name;			j = 0;			if (s)				for (j = 0; j < len; j++)					if (name[j] != s[j])						break;			if (j == len && s && s[j] == 0)				return i;		}	/* most variables are not temporary */	@:chkTemporary@	return -1;}@-Note that getType also checks for type names directly.They have preference over variable names.@cmalTypegetType(MalBlkPtr mb, str nme){	int i;	i = findVariable(mb, nme);	if (i < 0)		return getTypeIndex(nme, -1, TYPE_any);	if (i >= 0)		return getVarType(mb, i);	return TYPE_any;}strgetArgDefault(MalBlkPtr mb, InstrPtr p, int idx){	ValPtr v = &getVarConstant(mb, getArg(p, idx));	if (v->vtype == TYPE_str)		return v->val.sval;	return NULL;}@-All variables are implicitly declared upon their first assignment.Lexical constants require some care. They typically appear as argumentsin operator/function calls. To simplify program analysis later on,we stick to the situation that function/operator arguments are alwaysreferences to by variables.@- Reserved wordsAlthough MAL has been designed as a minimal language, severalidentifiers are not eligible as variables. The encoding belowis geared at simple and speed.@cintisReserved(str nme){	switch (*nme) {	case 'A':	case 'a':		if (idcmp("atom", nme) == 0)			return 1;		break;	case 'B':	case 'b':		if (idcmp("barrier", nme) == 0)			return 1;		break;	case 'C':	case 'c':		if (idcmp("command", nme) == 0)			return 1;		break;	case 'E':	case 'e':		if (idcmp("exit", nme) == 0)			return 1;		if (idcmp("end", nme) == 0)			return 1;		break;	case 'F':	case 'f':		if (idcmp("false", nme) == 0)			return 1;		if (idcmp("function", nme) == 0)			return 1;		if (idcmp("factory", nme) == 0)			return 1;		break;	case 'I':	case 'i':		if (idcmp("include", nme) == 0)			return 1;		break;	case 'M':	case 'm':		if (idcmp("module", nme) == 0)			return 1;		if (idcmp("macro", nme) == 0)			return 1;		break;	case 'O':	case 'o':		if (idcmp("orcam", nme) == 0)			return 1;		break;	case 'P':	case 'p':		if (idcmp("pattern", nme) == 0)			return 1;		break;	case 'T':	case 't':		if (idcmp("thread", nme) == 0)			return 1;		if (idcmp("true", nme) == 0)			return 1;		break;	}	return 0;}@-Beware, the symbol table structure assumes that it is relativelycheap to perform a linear search to a variable or constant.@= makeVarSpace	if( mb->vtop >= (1<<15)-2 ){		mb->vtop = (1<<15)-2 ;		GDKerror("newVariable: too many variables\n");	} else	if( mb->vtop >= mb->vsize){		VarPtr *new;        int s= mb->vtop + MAXVARS;		if (mb->vtop >mb->vsize)			GDKfatal("newVariable:variable administration\n");        new= (VarPtr *) GDKzalloc(s * sizeof(VarPtr));        /*printf("generate new variable block %d\n",s);*/        if( new== NULL ){            mb->errors++;            showScriptException(mb,0,MAL,"newMalBlk:no storage left\n");            return mb->vtop;        }        memcpy((char*)new, (char*)mb->var, sizeof(VarPtr) * mb->vtop);        GDKfree((str)mb->var);        mb->vsize= s;        mb->var= new;        mb->var[mb->vtop-1]->gdktype= TYPE_void;    }@cintnewVariable(MalBlkPtr mb, str name, malType type){	int n;	@:makeVarSpace@	if (isTmpName(name)) {		int i = atol(name + 1);		/* test validity */		if (i > mb->vtop) {			showScriptException(mb,0,MAL,				"newVariable:variable %s mis-aligned\n", name);			mb->errors++;		} else if (i < mb->vtop ) {			showScriptException(mb,0,MAL,				"'%s' overwrites %s\n", name, getVarName(mb, i));			mb->errors++;		}	}	n = mb->vtop;	getVar(mb, n) = (VarPtr) GDKzalloc(sizeof(VarRecord));	mb->var[n]->name = name;	mb->var[n]->props = NULL;	setVarType(mb, n, type);	isConstant(mb, n) = 0;	setVarCleanup(mb, n) = FALSE;	getVar(mb, n)->isudftype = 0;	getVar(mb, n)->isused = 0;	mb->vtop++;	return n;}voidrenameVariable(MalBlkPtr mb, int id, str name){	VarPtr v;	assert(id >=0 && id <mb->vtop);	v = getVar(mb, id);	if (v->name)		GDKfree(v->name);	v->name = name;	v->tmpindex = 0;}@+ MAL variablesTemporary target variable act as sinks in the data flow graph.In this case, an optimizer can group them by underlying type and this wayreduce the symbol table size significantly.MAL variables are internally represented by their index intothe variable stack. Their default textual representation is '_'<digits>.Temporary names  are recognized by the parser and an error isproduced if it does not satisfy this condition.Sharing of the temporary is only permitted if the typeis a priory known and not TYPE_any.@cintnewTmpVariable(MalBlkPtr mb, malType type){	int n;	@:makeVarSpace@	n = mb->vtop;	if (getVar(mb, n) == NULL)		getVar(mb, n) = (VarPtr) GDKzalloc(sizeof(VarRecord));/* already captured by memset    mb->var[n]->name = 0;    mb->var[n]->props = NULL;    isConstant(mb,n) = 0;    setVarCleanup(mb,n) = FALSE;	getVar(mb,n)->isudftype= 0;	getVar(mb,n)->isused= 0;*/	getVarTmp(mb, n) = n;	setVarType(mb, n, type);	mb->vtop++;	return n;}intnewTmpSink(MalBlkPtr mb, malType type){	int n;	n = type == TYPE_any ? -1 : findTmpVariable(mb, type);	if (n >= 0)		return n;	return newTmpVariable(mb, type);}intnewTypeVariable(MalBlkPtr mb, malType type){	int n;	n = type == TYPE_any ? -1 : findTmpVariable(mb, type);	if (n > 0 && isTypeVar(mb, n))		return n;	n = newTmpVariable(mb, type);	isTypeVar(mb, n) = TRUE;	return n;}voiddelVariable(MalBlkPtr mb, int varid){	if (varid == mb->vtop - 1) {		GDKfree(getVar(mb, varid));		getVar(mb, varid) = 0;		mb->vtop--;	}}voidcopyVariable(MalBlkPtr dst, MalBlkPtr src, VarPtr v){	VarPtr w;	(void) src;		/* fool the compiler */	w = (VarPtr) GDKzalloc(sizeof(VarRecord));	w->name = v->name ? GDKstrdup(v->name) : 0;	w->type = v->type;	w->gdktype = v->gdktype;	w->cleanup = v->cleanup;	w->fixtype = v->fixtype;	w->isudftype = v->isudftype;	w->isused = v->isused;	w->isaconstant = v->isaconstant;	w->isatypevar = v->isatypevar;	w->tmpindex = v->tmpindex;	w->depth = v->depth;	w->scope = v->scope;	VALcopy(&w->value, &v->value);	dst->var[dst->vtop] = w;	if( v->props )		w->props = cpyPropertySet(v->props);}@-Beware, removing a variablecalls for a re-numbering of the variable indices used in theprogram block. Assuming all new variables are appended only, wemerely have to take care of variable deletions.@cvoidremoveVariable(MalBlkPtr mb, int varid){	int i, j;	InstrPtr p;	for (i = 0; i < mb->stop; i++) {		p = getInstrPtr(mb, i);		for (j = 0; j < p->argc; j++)			if (p->argv[j] > varid)				p->argv[j]--;	}	/* remove the variable from the symbol table */	freeVariable(mb, varid);	for (i = varid; i < mb->vtop - 1; i++)		mb->var[i] = mb->var[i + 1];	mb->vtop--;}voidclearVariable(MalBlkPtr mb, int varid){	VarPtr v;	v = getVar(mb, varid);	if (v == 0)		return;	if (v->name)		GDKfree(v->name);	if (v->isaconstant)		VALclear(&v->value);	if (v->props)		freePropertySet(v->props);	v->props= NULL;	v->name = 0;	v->type = 0;	v->gdktype = 0;	v->cleanup = 0;	v->fixtype = 0;	v->isudftype = 0;	v->isused = 0;	v->isaconstant = 0;	v->isatypevar = 0;	v->tmpindex = 0;	v->depth = 0;	v->scope = 0;	/* the above version is faster memset((char*)v, 0, sizeof(VarRecord)); */}voidfreeVariable(MalBlkPtr mb, int varid){	VarPtr v;	v = getVar(mb, varid);	clearVariable(mb, varid);	GDKfree(v);	getVar(mb, varid) = NULL;}@+ MAL constantsConstants are stored in the symbol table and referencedby a variable identifier.This means that per MAL instruction, we may end up withMAXARG entries in the symbol table. This may lead to longsearches for variables.An optimization strategy deployed in the currentimplementation is to look around fora similar (constant) definition and to reuse its identifier.This avoids an exploding symbol table with a lotof temporary variables (as in tst400cHuge)But then the question becomes how far to search?Searching through all variables is only useful when the list remains shortor when the constant-variable-name is easily derivable from its literalvalue and a hash-based index leads you quickly to it.For the time being, we use a MAL system parameter, MAL_VAR_WINDOW,to indicate the number of symbol table entries to consider.Setting it to >= MAXARG will at least capture repeated use of a constantwithin a single function call or repeated use within a small blockof code.The final step is to prepare a GDK value record, from whichthe internal representation can be obtained duringMAL interpretation.The constant values are linked together to improve searching them.This start of the constant list is kept in the MalBlk.Conversion of a constant to another type is limited to

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -