随笔-341  评论-2670  文章-0  trackbacks-0
    Kernel FP的虚拟机设计起来比较别扭,主要还是因为laziness的问题。不过现在已经有了一个能用的想法了。

    第一个需要确定的是assembly。当然,这个assembly只是概念上的,现在并没有什么确定的形式。一个assembly需要一些函数的结构以及名表。名表的作用是减少特化模板函数所需要的内存空间。一个函数总是可以被分解成一个模板以及对于每一种类型需求下所做出的一些改变。例如:

    现在有代码:
1 def inc a = iadd a 1
2 
3 def inc s = concat a (list ' ')
4 
5 def inc2 x = inc (inc x)

    在调用inc2的时候,会根据x的类型确定所需要的inc究竟是什么。这个时候,inc2仅仅依赖于inc,所以在生成assembly的时候可以为这段指令的inc留一个自定义的位置,然后记录当x为string的时候调用第二个,当x为int的时候调用第一个。这个时候inc2的定义就被完整的保留了下来,而且也不需要在运行的时候才判断重载。

    事实上,函数应当属于值。而且有了laziness,代码也应当属于值。所以实际上运行的时候只需要一种数据结构,也就是值了。值有以下几种:
    1、整数和字符(浮点数以后再加)
    2、类型构造(譬如list a b)
    3、表达式树(譬如\a->imul a a)

    在Kernel FP运行的任意一个阶段,所产生的中间结果会这最终结果都只能是这三种类型的其中一种。而且这三种类型还是互相嵌套的。那么在什么时候开始运算呢?实际上我们一贯来需要的首先是判断一个值得类型,也就是将值转换成1或者2。Kernel FP里面的select-case表达式也需要这种功能。至此什么时候该laziness已经非常清楚了。一个表达式来了,我们首先获得它的类型(从而获得其结构),这个时候就一直运行到知道整数的内容、字符的内容或者得到类型构造的构造符号(譬如list)的时候暂停。当结果为类型构造的时候,读到了内容的时候继续递归。这样就可以保证一个值无论在Kernel FP,或者在一个使用Kernel FP的虚拟机的C++程序里面,不需要执行的Kernel FP代码一定不会被执行。

    Kernel FP的表达式一共有primitive表达式(整数或者字符)、函数调用表达式、let-in的局部名称定义表达式、lambda表达式以及select-case表达式。其中,运行的时候let-in表达式可以转化为lambda表达式,函数定义也可以转换为lambda表达式,所以运行时所需的表达式结构也就很容易确定下来了:

    1、值(整数常量或字符常量)
    2、名引用(引用到一个局部的或全局的名称并提供相应的名表,并且保证对同一个名称在不同的地方求值不会导致重复的代码执行)
    3、函数调用
    4、lambda表达式(用于积累到所有参数足够的时候,获得表达式以及局部的名引用对象表)
    5、select-case表达式(用于让laziness的代码开始运转所需的部分)

    那么,当需要知道一个表达式的值的时候需要做什么事情呢?
    首先,对于值来说,因为是常量,所以不需要进行更多的运算。
    第二,对于名引用来说,因为执行的是名引用的表达式,因此不需要什么特殊的动作,只需要按照这里定义的策略执行。
    第三,对于函数调用,我们需要将函数的参数传入lambda表达式的第一个参数,生成一个新的名引用对象并将lambda表达式的内容提上来。
    第四、lambda表达式,不需计算,因为函数本身就是一个值。
    第五、select-case表达式,对被判断的表达式本身的类型进行判断,运行最少的代码之后,生成case所需要的名引用对象并将case的结果表达式的内容提上来。

    至此,运行带有laziness的Kernel FP代码所需要的数据结构以及策略都定下来了。
posted on 2008-10-18 23:29 陈梓瀚(vczh) 阅读(1511) 评论(1)  编辑 收藏 引用 所属分类: 脚本技术

评论:
# re: Kernel FP 虚拟机结构 2008-10-25 22:44 | 金山词霸2008
这个虚拟机的策略到时听可行。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理