غالبًا ما تنشئ تطبيقات Blockly لغة JavaScript كلغة إخراج، ويكون الغرض منها عادةً التشغيل داخل صفحة ويب (ربما الصفحة نفسها أو WebView مضمّن). مثل أيّ أداة إنشاء، تكون الخطوة الأولى هي تضمين أداة إنشاء JavaScript.
import {javascriptGenerator} from 'blockly/javascript';
لإنشاء JavaScript من مساحة العمل، استخدِم:
javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);
يمكن تنفيذ الرمز الناتج مباشرةً في صفحة الويب المقصودة:
try {
eval(code);
} catch (e) {
alert(e);
}
في الأساس، لا يؤدي المقتطف أعلاه سوى إلى إنشاء الرمز وتقييمه. ومع ذلك،
هناك بعض التحسينات. من التحسينات التي تم إجراؤها أنّه تم تضمين try
/catch
في تقييم العبارة لكي تظهر أي أخطاء في وقت التشغيل بدلاً من أن يتم تجاهلها بدون إشعار. تم إجراء تحسين آخر وهو إضافة code
إلى قائمة الكلمات
المحجوزة، فإذا كان رمز المستخدم يحتوي على متغيّر بهذا الاسم، سيتم
إعادة تسميته تلقائيًا بدلاً من حدوث تعارض. يجب
حجز أي متغيّرات محلية بهذه الطريقة.
مجموعات اللحظات المميّزة
يساعد تمييز الكتلة التي يتم تنفيذها حاليًا أثناء تشغيل الرمز البرمجي المستخدمين في فهم سلوك برنامجهم. يمكن إجراء التمييز على مستوى
عبارة بعبارة من خلال ضبط STATEMENT_PREFIX
قبل
إنشاء رمز JavaScript:
javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');
حدِّد highlightBlock
لوضع علامة على الكتلة في مساحة العمل.
function highlightBlock(id) {
workspace.highlightBlock(id);
}
يؤدي ذلك إلى إضافة العبارة highlightBlock('123');
قبل
كل عبارة، حيث يكون 123
هو الرقم التسلسلي للوحدة التي سيتم
تمييزها.
تكرارات لا نهائية
على الرغم من أنّه يتم ضمان صحة البنية النحوية للرمز البرمجي الناتج في جميع
الأوقات، إلا أنّه قد يحتوي على حلقات لا نهائية. بما أنّ حلّ مشكلة التوقف خارج نطاق Blockly، فإنّ أفضل طريقة للتعامل مع هذه الحالات هي الاحتفاظ بعدّاد وخفضه في كل مرة يتم فيها إجراء دورة.
لتنفيذ ذلك، ما عليك سوى ضبط javascriptGenerator.INFINITE_LOOP_TRAP
على مقتطف код
الذي سيتم إدراجه في كل حلقة وكل دالة. في ما يلي مثال:
window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);
مثال
في ما يلي عرض توضيحي مباشر لإنشاء JavaScript وتنفيذه.
JS-Interpreter
إذا كنت جادًا في تشغيل كتل المستخدم بشكل صحيح، يمكنك استخدام مشروع JS-Interpreter. هذا المشروع منفصل عن Blockly، ولكن تم كتابته خصيصًا لاستخدامه مع Blockly.
- تنفيذ الرمز البرمجي بأي سرعة
- إيقاف التنفيذ مؤقتًا أو استئنافه أو تنفيذه خطوة بخطوة
- تمييز الكتل أثناء تنفيذها
- تكون معزولة تمامًا عن JavaScript في المتصفّح.
تشغيل أداة الترجمة الفورية
أولاً، نزِّل JS-Interpreter من GitHub:
بعد ذلك، أضِفه إلى صفحتك:
<script src="acorn_interpreter.js"></script>
إنّ أبسط طريقة لاستدعائه هي إنشاء JavaScript وإنشاء مترجم وتشغيل الرمز:
var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();
خطوة المترجم
لتنفيذ الرمز البرمجي بشكل أبطأ أو بطريقة أكثر تحكّمًا، استبدِل
الطلب إلى run
بحلقة تتضمّن خطوات (في هذه الحالة خطوة واحدة كل 10 مللي ثانية):
function nextStep() {
if (myInterpreter.step()) {
setTimeout(nextStep, 10);
}
}
nextStep();
يُرجى العلم أنّ كل خطوة ليست سطرًا أو كتلة، بل هي وحدة دلالية في JavaScript، وقد تكون دقيقة للغاية.
إضافة واجهة برمجة تطبيقات
"مُفسِّر JavaScript" هو مساحة محايدة معزولة تمامًا عن المتصفّح. تتطلّب أيّ وحدات تنفيذ إجراءات مع العالم الخارجي إضافة واجهة برمجة تطبيقات إلى مترجم لغة برمجة النص البرمجي. للحصول على وصف كامل، يُرجى الاطّلاع على مستندات JS-Interpreter. في البداية، إليك واجهة برمجة التطبيقات المطلوبة لتفعيل وحدات التنبيهات والطلبات:
function initApi(interpreter, globalObject) {
// Add an API function for the alert() block.
var wrapper = function(text) {
return alert(arguments.length ? text : '');
};
interpreter.setProperty(globalObject, 'alert',
interpreter.createNativeFunction(wrapper));
// Add an API function for the prompt() block.
wrapper = function(text) {
return prompt(text);
};
interpreter.setProperty(globalObject, 'prompt',
interpreter.createNativeFunction(wrapper));
}
بعد ذلك، عدِّل عملية إعداد المترجم لإضافة دالة initApi:
var myInterpreter = new Interpreter(code, initApi);
إنّ قالبَي التنبيه والطلب هما الوحدَين في المجموعة التلقائية من القوالب التي تتطلّب واجهة برمجة تطبيقات مخصّصة للمترجم.
يتم الآن الاتصال بـ highlightBlock()
عند التشغيل في JS-Interpreter، يجب تنفيذ highlightBlock()
على الفور خارج وضع الحماية، بينما ينتقل المستخدم خلال البرنامج. لتنفيذ
هذا الإجراء، أنشئ دالة ملفوفة highlightBlock()
لالتقاط دالة
الوسيطة، وسجِّلها كدالة أصلية.
function initApi(interpreter, globalObject) {
// Add an API function for highlighting blocks.
var wrapper = function(id) {
return workspace.highlightBlock(id);
};
interpreter.setProperty(globalObject, 'highlightBlock',
interpreter.createNativeFunction(wrapper));
}
قد تحتاج التطبيقات الأكثر تعقيدًا إلى تنفيذ الخطوات بشكل متكرر بدون التوقف إلى أن يتم الوصول إلى أمر تمييز، ثم التوقف. تحاكي هذه الاستراتيجية تنفيذ كل سطر على حدة. يستخدم المثال أدناه هذا النهج.
مثال على JS-Interpreter
في ما يلي عرض توضيحي مباشر لتفسير JavaScript خطوة بخطوة. يتضمّن العرض التوضيحي وحدة انتظار، وهي مثال جيد لاستخدام السلوك غير المتزامن الآخر (مثل الكلام أو الصوت أو إدخال المستخدم).