Chinaunix首页 | 论坛 | 博客
  • 博客访问: 984554
  • 博文数量: 150
  • 博客积分: 3017
  • 博客等级: 少校
  • 技术积分: 3829
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-19 14:40
个人简介

Now in Baidu WISE team

文章分类

全部博文(150)

文章存档

2014年(8)

2013年(31)

2012年(111)

分类: C/C++

2013-01-31 11:42:33

(作者码字辛苦,转载请以超链接形式注明出处)

之前我们处理了不带参函数的形式,现在来考虑带参的形式。


首先,我们观察传递参数时,到底需要做哪些事情。

方便起见,我们假设方法的局部变量和全局变量共用一个变量表VarHash,我们可以通过变量的名字从该表中获得这个名字代表的具体值。

考虑一个简单的函数定义和调用

def testfun(a,b) { stmt;}    //定义了有两个形参a,b的方法testfun

testfun(p1,p2);                     //调用上边定义的方法testfun,传递两个实参p1,p2,假设p1,p2是已经赋值过的全局变量


那么,参数传递的过程,实际上就是

1.在变量表中新建两个变量,a,b,并置为空    

2.将p1,p2分别复制一份填充如a,b, 即  VarHash["a“] = dup(p1), VarHash["b"] = dup(p2);


所以我们要做的就是在调用时,复制一份实参,然后填充入形参的位置。


然后我们考虑方法的定义:

对于一个方法,我们用左节点存储其形参列表, 右结点存储要执行的语句。那么执行时,我们先要根据其左节点进行参数的传递,完成后形参在VarHash中已经有了值了,再执行右结点,那么这时候右结点就可以顺利的调用形参了。

一个方法节点建成以后,类似变量,我们可以以方法名为key ,填入方法表中FunHash. FunHash["testfun"] = &funnode.


最后,我们考虑调用方法语句:

对于一个调用语句,我们用左节点存储传入的参数列表,我们可以将其想象成一个数组。如上面的代码例子中,这个数组就有2个元素,分别为a,b,他们都是两个变量,可以从VarHash中得到实际的值。

其右节点,指向它所调用的函数,这个指针可以通过名字在FunHash中获取,即  node->right = FunHash["testfun"]


接下来,我们先给出一份函数定义和调用的语法树示意图:




最后来考虑如何执行一个函数的调用。


对于上面给出的简单代码例子,可分解如下: 

记函数调用的结点为funcall,函数的结点为fundef, 那么有funcall->right = fundef

1. 获取实参列表 funcall->right, 得到的一个数组paramarr = (p1,p2);

2. 执行参数赋值 paramnode = funccall->right->left 即 fundef->left;

3. 若paramnode不为空,说明有形参需要赋值,得到形参名"a";

4. 获得paramarr[0]的值p1,复制一份,放入VarHash,  VarHash["a"] = dup(p1);

5. 继续下一个个赋值, paramnode = paramnode->right;


6. 若paramnode不为空,说明有形参需要赋值,获得形参名"b"

7. 获得paramarr[1]的值p2,复制一份,放入VarHash,  VarHash["b"] = dup(p2);

8. 继续下一个个赋值, paramnode = paramnode->right;

9.paramnode为空,说明2个形参赋值完毕,返回


10.执行fundef->right. 即stmt


由于在处理语句时,参数的个数是不一定的,所以采用了链表来记录实际参数列表,每次赋值完一个,下移即可。上面使用数组,仅为了表达方便。


部分参考代码如下,已测试通过。 完整的代码,请参阅  


... ...
Node* createPARAM(char* name, Hash localvars){
	Node* ret = createEmptyNode();
	ret->op =  PARAMS;
	ret->localvars = localvars;
	ret->data = createStrData(name);
	return ret;
}

Node* createPARAMS(Node* param, Node* params){
	param->right = params;
	return param;
}
... ...

Node* createFUN(Node* paramslist, Node* stmts, Hash localvars){
	Node* ret = createEmptyNode();
	ret->op = FUN;
	ret->localvars = localvars;
	ret->left = paramslist;
	ret->right = stmts;
	return ret;
}

... ...
typedef struct _ArrayUnit{
	void* data;
	struct _ArrayUnit * next;	
} ArrayUnit;
....


Data ExPARAMS(Node* node, ArrayUnit* actualParams){
	//actual params should be array
	Data *dup = (Data*)malloc(sizeof(Data));
	memcpy(dup, actualParams->data, sizeof(Data));
	setItem(node->localvars,node->data->value.strValue,dup);
	actualParams = actualParams->next;
	if(node->right != NULL){
		ExPARAMS(node->right, actualParams);
	}
}


... ...


Data ExFUNCALL(Node* node){
	//set param
	Data params = ExGET(node->left);
	ExPARAMS(node->right->left, params.value.arrayValue);
	return ExSTMT(node->right);
}


... ...





阅读(2265) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~