随笔-341  评论-2670  文章-0  trackbacks-0
    Kernel FP已经可以运行小程序了。现在还处于测试阶段,过于复杂的程序估计是跑不过的。先简单介绍一下如何在C++调用Kernel FP的代码。

    首先贴出一段Kernel FP的代码:
 1 module startup
 2 import system
 3 
 4 data maybe T = return T | error T
 5 
 6 def add a b = 
 7   let
 8     def xadd = iadd a b
 9   in xadd
10 
11 def foo a =
12   select a of
13     case 0 : return 100
14     case 1 : return 200
15     case 2 : return 300
16     else : error a
17   end
18 
19 def translate a =
20   select a of
21     case return t : iadd 10000 t
22     case error t : iadd 1000 t
23   end
24 
25 def main = translate (foo (add 1 2))

    程序非常直白。add 1 2返回3,经过foo选择返回error 3,经过translate变成iadd 1000 3,最后输出1003。现在Kernel FP的对外api还没写,只是在调试内核代码。为什么只有iadd呢?因为我只实现了iadd……其他的等以后再说。先看看如何调用一个main函数。在没有对外api的情况下,只能对内核的对象进行裸调……

   
 1 void RunProgram(VL_KfpRuntimeProgram::Ptr Program)
 2 {
 3     VL_KfpRuntimeEnvironment Environment;
 4     Environment.Program=Program;
 5 
 6     MyPlugin Plugin(&Environment);
 7     Environment.Plugins.Add(&Plugin);
 8 
 9     VL_KfpRuntimeFunction* Function=&Program->Functions[Program->FunctionIDMap[L"startup.main"][0]];
10 
11     VL_KfpRuntimeValueEnvironment ValueEnvironment;
12     ValueEnvironment.Environment=&Environment;
13     ValueEnvironment.SetTable(new VL_KfpRuntimeValueTable(new VL_KfpRuntimeValueTable(0,0),Function->Instance));
14 
15     VL_KfpRuntimeExpression* Expression=Function->AssociatedExpression;
16     VL_KfpRuntimeValue* Value=Expression->CreateRuntimeValue(&ValueEnvironment);
17     Value->Increase();
18     VL_KfpRuntimeEvaluateResult Result;
19     Value->EvaluateUntilGetType(&Environment,Result);
20     if(Result.HasError)
21     {
22         GetConsole()->Write(L"发生错误:"+Result.ErrorMessage+L"\r\n");
23     }
24     else
25     {
26         if(Result.Value.GetValue()->Kind==VL_KfpRuntimeValue::vkekInteger)
27         {
28             GetConsole()->Write(L"返回值:"+VUnicodeString(((VL_KfpRuntimeIntegerValue*)Result.Value.GetValue())->Data)+L"\r\n");
29         }
30         else
31         {
32             GetConsole()->Write(L"返回值不是整数。\r\n");
33         }
34     }
35     Value->Decrease();
36 }

    首先程序经过先前实现的类型推导,得到编译后的程序VL_KfpRuntimeProgram,然后取出startup.main的函数指针。得到了函数指针之后,将函数的上下文和函数绑定的表达式都保存起来,然后将表达式转换为VL_RuntimeValue。最后对VL_RuntimeValue与上下文结合进行求值。

    当然了,程序会调用到iadd,这是一个外部函数,实现两个整数的加法。所以还得实现一个插件来执行iadd:

 1 class MyPlugin : public VL_KfpRuntimePlugin
 2 {
 3 public:
 4     VL_KfpRuntimeEnvironment*        Environment;
 5     VInt                            External_IAdd;
 6 
 7     MyPlugin(VL_KfpRuntimeEnvironment* aEnvironment)
 8     {
 9         Environment=aEnvironment;
10 
11         External_IAdd=Environment->Program->ExternalIDMap[L"kernelfp::iadd"];
12     }
13 
14     VLE_KfpPluginResult Invoke(VInt ExternalID , InParams& In , OutParams& Out)
15     {
16         if(ExternalID==External_IAdd)
17         {
18             if(In.Parameters.GetCount()==2)
19             {
20                 VL_KfpRuntimeEvaluateResult r1,r2;
21 
22                 In.Parameters[0].GetValue()->EvaluateUntilGetType(Environment,r1);
23                 if(r1.HasError)
24                 {
25                     Out.ErrorMessage=r1.ErrorMessage;
26                     return vkprFail;
27                 }
28                 if(r1.Value.GetValue()->Kind!=VL_KfpRuntimeValue::vkekInteger)
29                 {
30                     Out.ErrorMessage=L"iadd函数的参数必须是两个int。";
31                     return vkprFail;
32                 }
33 
34                 In.Parameters[1].GetValue()->EvaluateUntilGetType(Environment,r2);
35                 if(r2.HasError)
36                 {
37                     Out.ErrorMessage=r2.ErrorMessage;
38                     return vkprFail;
39                 }
40                 if(r2.Value.GetValue()->Kind!=VL_KfpRuntimeValue::vkekInteger)
41                 {
42                     Out.ErrorMessage=L"iadd函数的参数必须是两个int。";
43                     return vkprFail;
44                 }
45 
46                 VInt Value1=((VL_KfpRuntimeIntegerValue*)r1.Value.GetValue())->Data;
47                 VInt Value2=((VL_KfpRuntimeIntegerValue*)r2.Value.GetValue())->Data;
48                 Out.Result.SetValue(new VL_KfpRuntimeIntegerValue(Value1+Value2));
49                 return vkprSuccess;
50             }
51             else
52             {
53                 Out.ErrorMessage=L"iadd函数的参数必须是两个int。";
54                 return vkprFail;
55             }
56         }
57         else
58         {
59             return vkprPass;
60         }
61     }
62 
63     VLE_KfpPluginResult GetParameterCount(VInt ExternalID , VInt& Count)
64     {
65         if(ExternalID==External_IAdd)
66         {
67             Count=2;
68             return vkprSuccess;
69         }
70         else
71         {
72             return vkprPass;
73         }
74     }
75 };

    这也就是MyPlugin类的内容了。
posted on 2008-12-10 23:03 陈梓瀚(vczh) 阅读(1709) 评论(2)  编辑 收藏 引用 所属分类: 脚本技术

评论:
# re: Kernel FP成功运行小程序 2008-12-10 23:58 | kuafoo
还在等你发布界面库呢  回复  更多评论
  
# re: Kernel FP成功运行小程序 2008-12-11 01:44 | 陈梓瀚(vczh)
界面库啊,自从Preview之后就很少升级了。因为剩下的那几个控件实在是懒的去封装……不过这应该是迟早的事情。等需要为kernel fp做Demo的时候,估计就开始了吧……  回复  更多评论
  

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