Kernel FP成功运行小程序

Kernel FP成功运行小程序
    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类的内容了。

你可能感兴趣的:(Kernel FP成功运行小程序)