苦恼了一天,在翻译new关键字的时候遇到了一些麻烦, 首先neko是不支持面向对象的,没有class的概念。然后是js端, js的构造方式很奇葩, ES5 的function 和 class 是需要我们特殊区分的。
比如说
function A () {}
即是函数又是类 , 考虑到每个new出来的对象我们都要支持 class 定义的的属性和方法。我们需要在翻译端搞出来一套原型链的机制。
所以这里定义了关键字来区分函数和类。
Class //[Class("exports.cls.StateMachine")];
我们在翻译之前先把我们定义的类和包的路径定义好。类似:
var cls = exports.createNamespace("cls");
cls.ClassA = function() {
[Class("exports.cls.ClassA")];
this.toString = function () {
return "ClassA Call";
}
}
然后我们在翻译的时候就可以使用new关键字来生成他的实例了。 具体细节就不在这里讨论了。
我们假装翻译一个简单点的类。
var exports = {};
exports.createNamespace = function (ns) {
if (exports[ns]) {
return exports[ns];
}
var ps ={};
exports[ns] = {};
return exports[ns];
}
;(function() {
var cls = exports.createNamespace("cls");
cls.ClassA = function() {
[Class("exports.cls.ClassA")];
this.toString = function () {
return "ClassA Call";
}
}
/// 状态机
cls.StateMachine = function() {
[Class("exports.cls.StateMachine")];
this.statOwner = obj;
this.currState = null;
this.preState = null;
this.setCurrentState = function(state) {
currState = state;
};
this.setPreviousState = function(state) {
preState = state;
};
this.setStateCommand = function(state, cmd) {
if (state && state.hasOwnProperty(cmd)) {
state[cmd](this.statOwner);
}
};
this.changeState = function(state) {
this.setPreviousState(currState);
this.setStateCommand(preState, "exit");
this.setCurrentState(state);
this.setStateCommand(state, "enter");
};
this.changingState = function(state) { /// 立刻执行
this.changeState(state);
this.update();
};
this.update = function() {
this.setStateCommand(currState, "execute");
};
this.revertToPreState = function() {
this.changeState(preState);
};
this.getCurrState = function() {
return currState;
};
this.getPreviousState = function() {
return preState;
};
};
}
)();
var NormalState = {
"execute": function (e) {
console.log("execute NormalState \n");
},
"enter":function (e) {
console.log("enter NormalState \n");
},
"exit":function (e) {
console.log("exit NormalState\n");
}
}
var n = new exports.cls.StateMachine(1);
n.setCurrentState(NormalState);
n.update();
console.log(n);
翻译后:
nglobals : 35
nfields : 26
codesize : 369 ops , 560 total
GLOBALS =
global 0 : var __exports_defines__symblos__
global 1 : function 1 nargs 1
global 2 : string "cls"
global 3 : string "exports.cls.ClassA"
global 4 : string "ClassA Call"
global 5 : function 40 nargs 0
global 6 : function 43 nargs 0
global 7 : string "exports.cls.StateMachine"
global 8 : var obj
global 9 : var currState
global 10 : function 66 nargs 1
global 11 : var preState
global 12 : function 69 nargs 1
global 13 : function 72 nargs 2
global 14 : string "exit"
global 15 : string "enter"
global 16 : function 95 nargs 1
global 17 : function 124 nargs 1
global 18 : string "execute"
global 19 : function 135 nargs 0
global 20 : function 144 nargs 0
global 21 : function 151 nargs 0
global 22 : function 154 nargs 0
global 23 : function 157 nargs 0
global 24 : function 224 nargs 0
global 25 : var o:0
global 26 : string "execute NormalState \n"
global 27 : function 241 nargs 1
global 28 : string "enter NormalState \n"
global 29 : function 246 nargs 1
global 30 : string "exit NormalState\n"
global 31 : function 251 nargs 1
global 32 : string "new"
global 33 : function 256 nargs 2
global 34 : debug 560 ops 138 bytes
FIELDS =
objget 154104FF
objset 154A200B
__cls_name__ D0D1A680
toString 386ED0AC
objfield 1A7EC563
statOwner 1BF9C3BF
setPreviousState EB621958
setStateCommand DDBD49FC
setCurrentState E9CD2DDA
changeState 29D11E81
update 07058609
currState E7E0ADBF
preState 03E526EE
changingState 1C815C24
revertToPreState D448728D
getCurrState F7374A49
getPreviousState 15202BE4
createNamespace 08E2A3FF
ClassA 39A52D29
StateMachine C8A78D96
print C88B582D
cls 004B7DAA
enter F0866D18
execute CC0D0A35
exit C31DF71E
new 0053D060
CODE =
000000 0 Jump 281
000002 1 AccEnv 0
000004 2 Push
000005 3 AccStack1
000006 4 Hash
000007 5 Push
000008 6 AccBuiltin objget
00000A 7 Call 2
00000C 8 JumpIfNot 17
00000E 9 AccEnv 0
000010 10 Push
000011 11 AccStack1
000012 12 Hash
000013 13 Push
000014 14 AccBuiltin objget
000016 15 TailCall(2, 3)
000018 16 Ret 1
00001A 17 AccNull
00001B 18 New
00001C 19 Push
00001D 20 AccEnv 0
00001F 21 Push
000020 22 AccStack 2
000022 23 Hash
000023 24 Push
000024 25 AccNull
000025 26 New
000026 27 Push
000027 28 AccBuiltin objset
000029 29 Call 3
00002B 30 AccEnv 0
00002D 31 Push
00002E 32 AccStack 2
000030 33 Hash
000031 34 Push
000032 35 AccBuiltin objget
000034 36 TailCall(2, 4)
000036 37 Ret 2
000038 38 Pop 1
00003A 39 Ret 1
00003C 40 AccGlobal 4
00003E 41 Ret 0
000040 42 Ret 0
000042 43 AccThis
000043 44 Push
000044 45 AccGlobal 3
000046 46 SetField __cls_name__
000048 47 AccThis
000049 48 Push
00004A 49 AccGlobal 5
00004C 50 SetField toString
00004E 51 AccThis
00004F 52 New
000050 53 Push
000051 54 AccGlobal 0
000053 55 Push
000054 56 AccThis
000055 57 AccField __cls_name__
000057 58 Hash
000058 59 Push
000059 60 AccStack 2
00005B 61 Push
00005C 62 AccBuiltin objset
00005E 63 TailCall(3, 4)
000060 64 Pop 1
000062 65 Ret 0
000064 66 AccStack0
000065 67 SetGlobal 9
000067 68 Ret 1
000069 69 AccStack0
00006A 70 SetGlobal 11
00006C 71 Ret 1
00006E 72 AccStack1
00006F 73 Bool
000070 74 JumpIfNot 82
000072 75 AccStack1
000073 76 Push
000074 77 AccStack1
000075 78 Hash
000076 79 Push
000077 80 AccBuiltin objfield
000079 81 Call 2
00007B 82 JumpIfNot 94
00007D 83 AccThis
00007E 84 AccField statOwner
000080 85 Push
000081 86 AccStack 2
000083 87 Push
000084 88 AccStack 2
000086 89 Hash
000087 90 Push
000088 91 AccBuiltin objget
00008A 92 Call 2
00008C 93 TailCall(1, 3)
00008E 94 Ret 2
000090 95 AccGlobal 9
000092 96 Push
000093 97 AccThis
000094 98 Push
000095 99 AccField setPreviousState
000097 100 ObjCall 1
000099 101 AccGlobal 11
00009B 102 Push
00009C 103 AccGlobal 14
00009E 104 Push
00009F 105 AccThis
0000A0 106 Push
0000A1 107 AccField setStateCommand
0000A3 108 ObjCall 2
0000A5 109 AccStack0
0000A6 110 Push
0000A7 111 AccThis
0000A8 112 Push
0000A9 113 AccField setCurrentState
0000AB 114 ObjCall 1
0000AD 115 AccStack0
0000AE 116 Push
0000AF 117 AccGlobal 15
0000B1 118 Push
0000B2 119 AccThis
0000B3 120 Push
0000B4 121 AccField setStateCommand
0000B6 122 ObjCall 2
0000B8 123 Ret 1
0000BA 124 AccStack0
0000BB 125 Push
0000BC 126 AccThis
0000BD 127 Push
0000BE 128 AccField changeState
0000C0 129 ObjCall 1
0000C2 130 AccThis
0000C3 131 Push
0000C4 132 AccField update
0000C6 133 ObjCall 0
0000C8 134 Ret 1
0000CA 135 AccGlobal 9
0000CC 136 Push
0000CD 137 AccGlobal 18
0000CF 138 Push
0000D0 139 AccThis
0000D1 140 Push
0000D2 141 AccField setStateCommand
0000D4 142 ObjCall 2
0000D6 143 Ret 0
0000D8 144 AccGlobal 11
0000DA 145 Push
0000DB 146 AccThis
0000DC 147 Push
0000DD 148 AccField changeState
0000DF 149 ObjCall 1
0000E1 150 Ret 0
0000E3 151 AccGlobal 9
0000E5 152 Ret 0
0000E7 153 Ret 0
0000E9 154 AccGlobal 11
0000EB 155 Ret 0
0000ED 156 Ret 0
0000EF 157 AccThis
0000F0 158 Push
0000F1 159 AccGlobal 7
0000F3 160 SetField __cls_name__
0000F5 161 AccThis
0000F6 162 Push
0000F7 163 AccGlobal 8
0000F9 164 SetField statOwner
0000FB 165 AccThis
0000FC 166 Push
0000FD 167 AccNull
0000FE 168 SetField currState
000100 169 AccThis
000101 170 Push
000102 171 AccNull
000103 172 SetField preState
000105 173 AccThis
000106 174 Push
000107 175 AccGlobal 10
000109 176 SetField setCurrentState
00010B 177 AccThis
00010C 178 Push
00010D 179 AccGlobal 12
00010F 180 SetField setPreviousState
000111 181 AccThis
000112 182 Push
000113 183 AccGlobal 13
000115 184 SetField setStateCommand
000117 185 AccThis
000118 186 Push
000119 187 AccGlobal 16
00011B 188 SetField changeState
00011D 189 AccThis
00011E 190 Push
00011F 191 AccGlobal 17
000121 192 SetField changingState
000123 193 AccThis
000124 194 Push
000125 195 AccGlobal 19
000127 196 SetField update
000129 197 AccThis
00012A 198 Push
00012B 199 AccGlobal 20
00012D 200 SetField revertToPreState
00012F 201 AccThis
000130 202 Push
000131 203 AccGlobal 21
000133 204 SetField getCurrState
000135 205 AccThis
000136 206 Push
000137 207 AccGlobal 22
000139 208 SetField getPreviousState
00013B 209 AccThis
00013C 210 New
00013D 211 Push
00013E 212 AccGlobal 0
000140 213 Push
000141 214 AccThis
000142 215 AccField __cls_name__
000144 216 Hash
000145 217 Push
000146 218 AccStack 2
000148 219 Push
000149 220 AccBuiltin objset
00014B 221 TailCall(3, 4)
00014D 222 Pop 1
00014F 223 Ret 0
000151 224 AccGlobal 2
000153 225 Push
000154 226 AccEnv 0
000156 227 Push
000157 228 AccField createNamespace
000159 229 ObjCall 1
00015B 230 Push
00015C 231 AccStack0
00015D 232 Push
00015E 233 AccGlobal 6
000160 234 SetField ClassA
000162 235 AccStack0
000163 236 Push
000164 237 AccGlobal 23
000166 238 SetField StateMachine
000168 239 Pop 1
00016A 240 Ret 0
00016C 241 AccGlobal 26
00016E 242 Push
00016F 243 AccBuiltin print
000171 244 TailCall(1, 2)
000173 245 Ret 1
000175 246 AccGlobal 28
000177 247 Push
000178 248 AccBuiltin print
00017A 249 TailCall(1, 2)
00017C 250 Ret 1
00017E 251 AccGlobal 30
000180 252 Push
000181 253 AccBuiltin print
000183 254 TailCall(1, 2)
000185 255 Ret 1
000187 256 AccEnv 0
000189 257 AccField cls
00018B 258 Push
00018C 259 AccField ClassA
00018E 260 ObjCall 0
000190 261 AccEnv 0
000192 262 AccField cls
000194 263 Push
000195 264 AccField StateMachine
000197 265 ObjCall 0
000199 266 AccStack1
00019A 267 Push
00019B 268 AccStack1
00019C 269 Hash
00019D 270 Push
00019E 271 AccBuiltin objget
0001A0 272 Call 2
0001A2 273 Push
0001A3 274 AccStack0
0001A4 275 New
0001A5 276 Push
0001A6 277 AccStack0
0001A7 278 Ret 4
0001A9 279 Pop 2
0001AB 280 Ret 2
0001AD 281 AccNull
0001AE 282 New
0001AF 283 SetGlobal 25
0001B1 284 AccGlobal 25
0001B3 285 Push
0001B4 286 SetField enter
0001B6 287 AccGlobal 25
0001B8 288 Push
0001B9 289 SetField execute
0001BB 290 AccGlobal 25
0001BD 291 Push
0001BE 292 SetField exit
0001C0 293 AccNull
0001C1 294 New
0001C2 295 SetGlobal 0
0001C4 296 AccNull
0001C5 297 New
0001C6 298 Push
0001C7 299 AccStack0
0001C8 300 Push
0001C9 301 AccStack1
0001CA 302 Push
0001CB 303 AccGlobal 1
0001CD 304 MakeEnv 1
0001CF 305 SetField createNamespace
0001D1 306 AccStack0
0001D2 307 Push
0001D3 308 AccGlobal 24
0001D5 309 MakeEnv 1
0001D7 310 Push
0001D8 311 AccStack0
0001D9 312 Call 0
0001DB 313 AccGlobal 25
0001DD 314 New
0001DE 315 Push
0001DF 316 Push
0001E0 317 AccGlobal 27
0001E2 318 SetField execute
0001E4 319 AccStack0
0001E5 320 Push
0001E6 321 AccGlobal 29
0001E8 322 SetField enter
0001EA 323 AccStack0
0001EB 324 Push
0001EC 325 AccGlobal 31
0001EE 326 SetField exit
0001F0 327 AccStack0
0001F1 328 Pop 1
0001F3 329 Push
0001F4 330 AccGlobal 0
0001F6 331 Push
0001F7 332 AccGlobal 32
0001F9 333 Hash
0001FA 334 Push
0001FB 335 AccStack 4
0001FD 336 Push
0001FE 337 AccGlobal 33
000200 338 MakeEnv 1
000202 339 Push
000203 340 AccBuiltin objset
000205 341 Call 3
000207 342 JumpIfNot 344
000209 343 AccFalse
00020A 344 JumpIf 353
00020C 345 AccGlobal 0
00020E 346 Push
00020F 347 AccGlobal 7
000211 348 Push
000212 349 AccGlobal 0
000214 350 Push
000215 351 AccField new
000217 352 ObjCall 2
000219 353 Push
00021A 354 AccStack1
00021B 355 Push
00021C 356 AccStack1
00021D 357 Push
00021E 358 AccField setCurrentState
000220 359 ObjCall 1
000222 360 AccStack0
000223 361 Push
000224 362 AccField update
000226 363 ObjCall 0
000228 364 AccStack0
000229 365 Push
00022A 366 AccBuiltin print
00022C 367 Call 1
00022E 368 Pop 4
END
运行结果
execute NormalState
{ StateMachine => #function:0, __cls_name__ => exports.cls.StateMachine, revertToPreState => #function:0, setStateCommand => #function:2, currState => null, setCurrentState => #function:1, setPreviousState => #function:1, getCurrState => #function:0, preState => null, update => #function:0, getPreviousState => #function:0, statOwner => null, changingState => #function:1, changeState => #function:1, toString => #function:0, ClassA => #function:0 }
翻译完成后, 需要整理一下原型链的思路, 如何和js或者lua吧原型链继承和查找,是接下来需要面对的问题。