感谢吴烜向我推荐了这个论坛,,进来发现好多知乎互相关注的熟人。。。
这个引擎的编译器和虚拟机还有不少小问题,所以暂时还未正式开源上线,不过今年肯定会开源上线
我这里展示一些小Demo,大家都可以探讨一下
1.这个JavaScript引擎目前支持绝大部分ES5和部分ES6语法。
2.支持英文或中文或者混合写代码。
3.编译器和虚拟机均为C语言实现,虚拟机基于栈实现,并未用WASM。
支持绝大部分ES5和ES6语法:
原生支持JSON,数组,字符串,及常用的方法和对象这些基础没什么好说的,不过还是有些不同,比如不支持函数嵌套声明(我个人觉得这没什么卵用),不过嵌套闭包还是可以的:
比如修改了typeof语法,说实话原来JavaScript的typeof有些鸡肋,修改后:
编译器和虚拟机为C语言实现:
既然要移植到各种单片机/嵌入式芯片上运行,至少虚拟机必然要用C语言写,这个虚拟机是基于栈实现一共59条指令,可以通过编译器,编译出字节码文件及相应调试文件,这个字节码调试文件是有中文的,你可以看一下某些程序在栈中的执行情况,这是上面闭包Demo的字节码调试文件:
中文字节码调试文件
这个JavaScript引擎是已经在单片机上扩展封装了大量的库和API:包括常用的单片机硬件对象,语音识别对象,物联网对象(HTTP和MQTT),GUI对象等。
在单片上用JavaScript做一个计算器:
代码在这里:
//导入UI界面必要的库文件
importFile "tim_ui.js"
import tim;
//创建一个字体,单片机硬件资源有限,还不能动态生成字体,只能加载生成好的字库文件
const myFont = createFont({
file: 'font/lh32_20_7f_b4.bin',
start: 0x20,
end: 0x7f,
bpp: 4,
lineHeight: 32,
});
//创建另一个字体
const keyFont = createFont({
file: 'font/lh21_20_7f_b4.bin',
start: 0x20,
end: 0x7f,
bpp: 4,
lineHeight: 21,
});
const disCont = new timui(curScreen, widgetCont);
timui.style(disCont, {
'width': '100%',
'height': '80px',
'borderBottom': '3px 0x6c757d',
'color': 0xdc3545, //同CSS指容器内文字颜色
});
const disLabel = new timui(disCont, widgetLabel);
disLabel.setText('0');
timui.style(disLabel, {'font': myFont, 'align': alignRM,});
const stacks = [0, 0, 0, 0, 0];
let stackPointer = 0;
function pushStack(v)
{
stacks[stackPointer] = v;
stackPointer++;
if (stackPointer == 3) {
//当栈里有三个数据时,就可以计算了
if (typeof stacks[0] === 'string') {
stackPointer = 1;
return;
}
switch (stacks[1]) {
case 1:
stacks[0] += stacks[2];
break;
case 2:
stacks[0] -= stacks[2];
break;
case 3:
stacks[0] *= stacks[2];
break;
case 4:
if (stacks[2] === 0) {
stacks[0] = '#ff0000 ERR /0!#';
} else {
stacks[0] /= stacks[2];
}
break;
}
stackPointer = 1;
}
}
let num = 0;
let isFloat = 1, isInt = 10;
let isClear = 0;
function myCalc(evt)
{
switch (evt.value) {
case '+':
pushStack(num);
pushStack(1);
break;
case '-':
pushStack(num);
pushStack(2);
break;
case '*':
pushStack(num);
pushStack(3);
break;
case '/':
pushStack(num);
pushStack(4);
break;
case '=':
if (isClear) {
stackPointer = 0;
stacks[0] = 0;
stacks[1] = 0;
this.children[0].setText('=');
timui.style(this, {'backgroundColor': 0xffc107});
} else {
if (stackPointer == 2) {
//说明有数据入栈
pushStack(num);
stackPointer = 0;
}
stacks[1] = 0;
this.children[0].setText('CE');
timui.style(this, {'backgroundColor': 0xdc3545});
}
isClear = !isClear;
break;
case '.':
isFloat = 0.1;
isInt = 1;
disLabel.setText(num + '.');
return;
default:
let n = evt.value.toNumber();
num = num * isInt + n * isFloat;
if (typeof isFloat === 'double') {
isFloat *= 0.1;
}
disLabel.setText(num + '');
return;
}
num = 0;
isFloat = 1;
isInt = 10;
switch (stacks[1]) {
case 1:
disLabel.setText(stacks[0] + '+');
break;
case 2:
disLabel.setText(stacks[0] + '-');
break;
case 3:
disLabel.setText(stacks[0] + 'x');
break;
case 4:
disLabel.setText(stacks[0] + '/');
break;
default:
disLabel.setText(stacks[0] + '');
break;
}
}
const btnm = new timui(curScreen, widgetCont);
timui.style(btnm, {
'width': '100%',
'height': '360px',
'align': alignBM,
'top': '-17px',
'display': 'flex',
flexFlow: flexFlowRowWrap,
justifyContent: flexStretch,
alignContent: flexStretch,
});
const btns = ['7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'.', '0', '=', '+'];
const btnSize = (320 - 40) / 4;
for (let i in btns) {
const cell = new timui(btnm);
timui.style(cell, {'width': btnSize + 'px', 'height': btnSize + 'px', 'borderRadius': '12px', backgroundColor: 0xe0e0e0});
timui.style(cell, {'backgroundColor': 0xa1a1a1}, stPressed); //设置按下时的样式
const label = new timui(cell, widgetLabel);
timui.style(label, {'font': keyFont});
label.setText(btns[i]);
timui.style(label, {'align': alignC,});
timui.bindEvent(cell, evtClicked, myCalc, btns[i]);
}
//单独为14号按钮(也就是‘等于按钮’)设置一个背景色
timui.style(btnm.children[14], {'backgroundColor': 0xffc107});
单片机上行还模拟实现了CSS,这样前端的知识拿过来直接用。。。
这些Demo,包括上面的基于栈的单片机Demo都是可以用全中文实现的,篇幅有限我这里不展开贴代码了。
比如,中文脚本编程在单片机上实现一个温湿度检测仪:https://zhuanlan.zhihu.com/p/594793888