blockly生成javascript

来源:互联网 发布:mac触摸板按键声音大 编辑:程序博客网 时间:2024/05/16 19:45

生成和运行Javascript

块应用程序通常生成JavaScript作为其输出语言,通常在Web页面(可能相同或嵌入式WebView)中运行。像任何生成器,第一步是包括javascript生成器。

对于web Blockly,包括javascript_compressed.js,紧接 blockly_compressed.js

WEB

<script src="blockly_compressed.js"></script>
<script src="javascript_compressed.js"></script>

要从工作区生成JavaScript,请调用:

WEB

Blockly.JavaScript.addReservedWords('code');
var code = Blockly.JavaScript.workspaceToCode(workspace);

Blockly for Android生成JavaScript默认情况下,不应该需要配置。有关 详细信息,请参阅 使用自定义JavaScript生成器。

生成的代码可以在目标网页中执行:

try {
 
eval(code);
} catch (e) {
  alert
(e);
}

基本上,上面的代码片段只是生成代码和evals它。然而,有几个细化。一个细化是eval被包装在try/中catch,以便任何运行时错误是可见的,而不是安静地失败。另一个细化是code添加到保留字的列表,以便如果用户的代码包含该名称的变量,它将被自动重命名,而不是冲突。任何局部变量都应该以这种方式保留。

突出显示块(仅限Web)

在同一页面中运行代码的Web应用程序通常包括在代码运行时突出显示当前执行的块。这可以STATEMENT_PREFIX在生成JavaScript代码之前通过设置在语句一语句级别上完成

Blockly.JavaScript.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
Blockly.JavaScript.addReservedWords('highlightBlock');

定义highlightBlock标记工作区上的块。

function highlightBlock(id) {
  workspace
.highlightBlock(id);
}

这将导致在highlightBlock('123');每个语句之前添加语句,其中123是要突出显示的块的序列号。

无限循环

虽然结果代码在任何时候都保证在语法上是正确的,但它可能包含无限循环。由于求解 Halting 问题超出了Blockly的范围(!),处理这些情况的最佳方法是保持计数器,并在每次执行迭代时递减计数器。要实现这一点,只需设置Blockly.JavaScript.INFINITE_LOOP_TRAP一个代码片段,将插入到每个循环和每个函数。这里是一个例子:

window.LoopTrap = 1000;
Blockly.JavaScript.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = Blockly.JavaScript.workspaceToCode(workspace);

这是 一个 生成和执行JavaScript 的现场演示

JS解释器

如果你认真正确地运行用户的块,那么 JS Interpreter项目是要走的路。这个项目与Blockly分开,但是专门为Blockly写的。

  • 以任何速度执行代码。
  • 暂停/恢复/逐步执行。
  • 突出显示块执行时。
  • 完全独立于浏览器的JS。

这里是 使用Blockly和JS Interpreter生成和执行JavaScript 的现场演示

运行解释器

首先,从GitHub下载JS解释器:

然后将其添加到您的网页:

<script src="acorn_interpreter.js"></script>

调用它的最简单的方法是生成JavaScript,创建解释器,并运行代码:

var code = Blockly.JavaScript.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter
.run();

步骤翻译

为了更慢地执行代码,或者以更受控制的方式,用run循环(在这种情况下每10ms一步)替换调用

function nextStep() {
 
if (myInterpreter.step()) {
    window
.setTimeout(nextStep, 10);
 
}
}
nextStep
();

注意,每个步骤不是一行或一个块,它是JavaScript中的语义单元,它可能是非常细粒度的。

添加API

JS解释器是一个与浏览器完全隔离的沙盒。任何对外界执行操作的块都需要向解释器添加API。有关完整说明,请参阅 JS-Interpreter文档但首先,这里是需要支持警报和提示块的API:

function initApi(interpreter, scope) {
 
// Add an API function for the alert() block.
 
var wrapper = function(text) {
    text
= text ? text.toString() : '';
   
return interpreter.createPrimitive(alert(text));
 
};
  interpreter
.setProperty(scope, 'alert',
      interpreter
.createNativeFunction(wrapper));

 
// Add an API function for the prompt() block.
  wrapper
= function(text) {
    text
= text ? text.toString() : '';
   
return interpreter.createPrimitive(prompt(text));
 
};
  interpreter
.setProperty(scope, 'prompt',
      interpreter
.createNativeFunction(wrapper));
}

然后修改您的解释器初始化以传入initApi函数:

var myInterpreter = new Interpreter(code, initApi);

警报和提示块是缺省的块集中只有需要为解释器定制API的两个块。

连接 highlightBlock()

当在JS解释器中运行时,highlightBlock()应立即执行,在沙箱外,作为用户逐步执行程序。为此,创建一个包装函数highlightBlock()以捕获函数参数,并将其注册为本机函数。

function initApi(interpreter, scope) {
 
// Add an API function for highlighting blocks.
 
var wrapper = function(id) {
    id
= id ? id.toString() : '';
   
return interpreter.createPrimitive(workspace.highlightBlock(id));
 
};
  interpreter
.setProperty(scope, 'highlightBlock',
      interpreter
.createNativeFunction(wrapper));
}

更复杂的应用程序可能希望重复执行步骤而不暂停,直到达到突出显示命令,然后暂停。此策略模拟逐行执行。下面的示例使用此方法。

0 0
原创粉丝点击