大家可能对JavaScript,VBScript,Python,Lua,Shell等脚本语言并不陌生,有时候也对Swift语言的特性表现出很大的兴趣。大家在乐此不彼的使用这些语言的时候,有没有想过要自己实现一个脚本引擎呢?(拜托,自己写的能跟那些成熟的比吗?!)话一点错没有,不过通过自己一步步实现一个引擎,从中可以学到不少的知识,也能对现在大家使用的编译器有个旁观的认识。
为了执行的性能,再加一个脚本的“汇编器”;跨平台,给自己的脚本引擎写一个虚拟机,哈哈,也是一种乐趣。
饭呢,要一口一口的吃,事呢要一步一步的做,从简单到复杂,Let’s go!
首先呢,先给要写的脚本引擎一个定位,我们要讲的这个,先定义为嵌入式脚本吧,添加的类库越来越齐全的时候,“经验值”就到了要升级的时刻了,那时,就不仅仅只做潜入式的活了。
func getter()
...
end
func setter(old_value, new_value)
...
end
script.observer("name", {"get"="getter", "set"="setter"})
name="xiaoming" //触发getter,setter
需求千变万化,客户端发版费时费力,无可奈何,回忆下引擎实现的点滴过程,并作为系列文章,分享给大家。
window_width=740
window_height=500
//与xml中一致
logo_ctrl_id=24003
name_ctr_id=24004
element_panel_id=24010
_temp_id=30000
text_ele_clr=0x00aaaaaa
func MakeID()
_temp_id = _temp_id + 1
return _temp_id
end
DT_SINGLELINE=0x00000020
DT_PATH_ELLIPSIS=0x00004000
DT_END_ELLIPSIS=0x00008000
dpi=js.system.dpi
func revert_dpi(len)
return (len * 96 / dpi)
end
bcreate=js.ui.createwindow(window_width,window_height,window_parent);
js.logic.if(!bcreate, "js.debug.abort");
//得到标题的区域
left,_,_,top= js.ui.bound(name_ctr_id);
left = revert_dpi(left)
top = revert_dpi(top)
top = top + 8
foreach(label in labels)
local panel_id=MakeID();
js.ui.addpanel(0,panel_id,left,top,100,20,"",label.clr);
local sta_id=MakeID();
js.ui.addsta(panel_id, sta_id, left, top, 10000, 1, label.text, "", 0x00ffffff, 9);
local width, height = js.ui.autosize(sta_id);
width=revert_dpi(width)
height=revert_dpi(height)
js.ui.setrect(panel_id, left, top, width + 10, height + 6);
js.ui.setrect(sta_id, left + 5, top + 3, width, height);
left = left + width + 15
end
//拆分文件残留信息
js.ui.enable_auto_transtext(0)
left,top,right,bottom= js.ui.bound(element_panel_id);
left=revert_dpi(left)
top=revert_dpi(top)
right=revert_dpi(right)
bottom=revert_dpi(bottom)
richlist_id=MakeID();
js.ui.addrichlist(element_panel_id,richlist_id,left+1, top+1, right-left-2, bottom-top-2);
expand_img_id=js.ui.idi2resid("IDI_DETAIL_UNINST_EXPAND")
unexpand_img_id=js.ui.idi2resid("IDI_DETAIL_UNINST_UNEXPAND")
folder_img_id=js.ui.idi2resid("IDI_DETAIL_UNINST_FOLDER")
left=js.ui.ctrlleft(logo_ctrl_id);
left=revert_dpi(left)
file_items=js.string.token(files_, ";")
files_count=js.object.count(file_items)
if(files_count > 0)
then
files_kv={expand=1,height=0, panel_id=0, arrow_id=0}
local panel_id=MakeID();
js.ui.addpanel(richlist_id,panel_id,0,top,right,30,"",0xffffffff);
_,top,_,_= js.ui.bound(panel_id);
top=revert_dpi(top)
js.ui.addpanel(panel_id,MakeID(),left,top + 5,2,20,"",0xfffb9937);
local text_left = left + 10;
local sta_id=MakeID();
js.ui.addsta(panel_id, sta_id, text_left, top, 200, 20, "文件残留项", "", text_ele_clr, 9);
js.ui.vcenter(panel_id, sta_id)
sta_id=MakeID();
js.ui.addsta(panel_id, sta_id, text_left + 400, top, 100, 20, js.string.combine(files_count,"个项目"), "", 0x003799fb, 9);
js.ui.vcenter(panel_id, sta_id)
local btn_id=MakeID()
js.ui.addbtn(panel_id, btn_id, text_left + 640, top, 12, 7, "", "", "expend_item(files_kv)", 0, 10);
js.ui.load_image_by_id(btn_id, expand_img_id)
js.ui.vcenter(panel_id, btn_id)
files_kv.arrow_id=btn_id
//添加文件项
local sub_files_panel_id=10;
js.ui.addpanel(richlist_id,sub_files_panel_id,0,0,right,0,"",0xffffffff);
_,top,_,_= js.ui.bound(sub_files_panel_id);
top=revert_dpi(top)
local file_size = 0
local sub_file_item_top=top
local index=0
foreach(file in file_items)
sta_id=MakeID();
js.ui.addsta(sub_files_panel_id, sta_id, text_left, sub_file_item_top, 615, 25, file, "", text_ele_clr, 9);
js.ui.ctrlstyle(sta_id, DT_SINGLELINE|DT_END_ELLIPSIS, 0)
local btn_id=MakeID()
js.ui.addbtn(sub_files_panel_id, btn_id, text_left + 620, sub_file_item_top + 4, 14, 12, "", "", js.string.combine("open_folder(", index, ")"), 0, 10);
index=index+1
js.ui.load_image_by_id(btn_id, folder_img_id)
sub_file_item_top = sub_file_item_top + 25
file_size = file_size + js.file.size(file);
end
js.ui.setrect(sub_files_panel_id, 0, top, right, sub_file_item_top - top);
files_kv.height=sub_file_item_top - top;
files_kv.panel_id=sub_files_panel_id
js.ui.adjust_view_total_height(richlist_id, files_kv.height);
sta_id=MakeID();
js.ui.addsta(panel_id, sta_id, text_left + 400 + 100, top, 100, 20, js.file.size_to_str(file_size), "", 0x003799fb, 9);
js.ui.vcenter(panel_id, sta_id)
end
//拆分注册表信息
reg_items=js.string.token(regs_, ";");
reg_count=js.object.count(reg_items);
if(reg_count > 0)
then
regs_kv={expand=1,height=0, panel_id=0, arrow_id=0}
local panel_id=MakeID();
js.ui.addpanel(richlist_id,panel_id,0,0,right,30,"",0xffffffff);
_,top,_,_= js.ui.bound(panel_id);
top=revert_dpi(top)
local flag_id=MakeID();
js.ui.addpanel(panel_id,flag_id,left,top + 5,2,20,"",0xfffb9937);
local text_left = left + 10;
local sta_id=MakeID();
js.ui.addsta(panel_id, sta_id, text_left, top, 200, 20, "注册表残留项", "", text_ele_clr, 9);
js.ui.vcenter(panel_id, sta_id)
sta_id=MakeID();
js.ui.addsta(panel_id, sta_id, text_left + 400, top, 100, 20, js.string.combine(reg_count,"个项目"), "", 0x003799fb, 9);
js.ui.vcenter(panel_id, sta_id)
local btn_id=MakeID();
js.ui.addbtn(panel_id, btn_id, text_left + 640, top, 12, 7, "", "", "expend_item(regs_kv)", 0, 10);
js.ui.load_image_by_id(btn_id, expand_img_id)
js.ui.vcenter(panel_id, btn_id)
regs_kv.arrow_id=btn_id
//添加文件项
local sub_regs_panel_id=11;
js.ui.addpanel(richlist_id,sub_regs_panel_id,0,0,right,0,"",0xffffffff);
_,top,_,_= js.ui.bound(sub_regs_panel_id);
top=revert_dpi(top)
local sub_reg_item_top=top
index=0
foreach(reg in reg_items)
regitem=js.string.token(reg, "|")
regitem_token_count=js.object.count(regitem)
if(regitem_token_count >= 2)
then
sta_id=MakeID();
js.ui.addsta(sub_regs_panel_id, sta_id, text_left, sub_reg_item_top, 610, 25, regitem[0], "", text_ele_clr, 9);
js.ui.ctrlstyle(sta_id, DT_SINGLELINE|DT_END_ELLIPSIS, 0)
local btn_id=MakeID()
js.ui.addbtn(sub_regs_panel_id, btn_id, text_left + 620, sub_reg_item_top + 4, 14, 12, "", "", js.string.combine("open_reg(", regitem[0], "," ,regitem[1], ")"), 0, 10);
js.ui.load_image_by_id(btn_id, folder_img_id)
sub_reg_item_top = sub_reg_item_top + 25
end
end
js.ui.setrect(sub_regs_panel_id, 0, 0, right, sub_reg_item_top);
regs_kv.height=sub_reg_item_top - top
regs_kv.panel_id=sub_regs_panel_id
js.ui.adjust_view_total_height(richlist_id, regs_kv.height);
end
js.ui.update_layout(richlist_id);
func expend_item(kv)
kv.expand=!kv.expand
if(kv.expand)
then
//展开
local l,t,r,b= js.ui.bound(kv.panel_id);
l=revert_dpi(l)
t=revert_dpi(t)
r=revert_dpi(r)
b=revert_dpi(b)
js.ui.setrect(kv.panel_id, l, t, r, kv.height);
js.ui.adjust_view_total_height(richlist_id, kv.height);
js.ui.load_image_by_id(kv.arrow_id, expand_img_id)
else
//合拢
local l,t,r,b= js.ui.bound(kv.panel_id);
l=revert_dpi(l)
t=revert_dpi(t)
r=revert_dpi(r)
b=revert_dpi(b)
js.ui.setrect(kv.panel_id, l, t, r, 0);
js.ui.adjust_view_total_height(richlist_id, -kv.height);
js.ui.load_image_by_id(kv.arrow_id, unexpand_img_id)
end
js.ui.update_layout(richlist_id);
end
func open_folder(index)
js.app.launch_without_sign("%windir%\\explorer.exe", " /select, " + file_items[index]);
end
func open_reg(path, isReg64key)
js.regjump.jump(path, isReg64key)
end
js.debug.gc;