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 ))
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 }
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 };
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类的内容了。