js实现blockly后台解释器,可以单步执行,可以调用c/c++函数

实现原理

解析blockly语法树,使用js管理状态,实际使用lua执行,c/c++函数调用使用lua调用c/c++函数的能力
可以单行执行
已实现if功能

TODO
for循环功能 函数功能

单步执行效果图
单步执行

直接执行效果图

直接执行

源代码

//0 暂停 1 单步执行 2 断点 
//创建枚举
var AstStatus = {PAUSE : 0,STEP :1,BREAK : 2,PASS:3
}class ASTInterpreter {constructor(ast,funcs) {//执行状态,暂停 单步执行 断点this.status = AstStatus.STEP;//当前节点this.currentBlock = null;this.ast = ast;this.variables = {};this.userFuns={};this.functions=new Set();this.initVariables();this.initFunc(funcs);this.callback=console.log}addEventCallback(func){this.callback=func}initFunc(funcs){for (let item of funcs) {this.addFunction(item)}}initVariables() {let vars = this.ast.variables;for (let i = 0; i < vars.length; i++) {const varDef = vars[i];const varId = varDef.id;const varName = varDef.name;this.variables[varId] = varName;}}stepFunc(){this.executeBlock(this.currentBlock)}addFunction(key) {this.functions.add(key);}getBlockType(block){let type = block.typeif(this.functions.has(type)){//说明是自定义函数return 'function'}else{return type}}execute() {if (this.ast && this.ast.blocks && this.ast.blocks.blocks) {const blocks = this.ast.blocks.blocks;for (let i = 0; i < blocks.length; i++) {const block = blocks[i];this.executeBlock(block);}}}executeBlock(block) {if (!block) return;let btype=this.getBlockType(block)let code = ''switch (btype) {case 'variables_set'://变量idconst varId = block.fields.VAR.id;//解析右值const value = this.evaluateInput(block.inputs.VALUE.block);code +=this.variables[varId]+'='+value;break;case 'function':code += this.executeFunction(block);break;case 'controls_if':this.executeIf(block);break;case 'procedures_callnoreturn':this.executeCallNoReturn(block);break;case 'procedures_defnoreturn':this.executeDefNoReturn(block);break;default:console.error(`Unsupported block type: ${block.type}`);}if(code){this.execLine(code,block.id)}// Execute next blockif (block.next && block.next.block) {this.currentBlock = block.next.block;if(this.status == AstStatus.STEP||this.status == AstStatus.PAUSE){}else{this.executeBlock(block.next.block);}}}//自定义函数定义 用户自己定义的函数不是系统的函数executeDefNoReturn(block){this.userFuns[block.fields.NAME]={params:block.extraState.params,block:block.inputs.STACK.block}return ''}//调用自定义函数 调用自己定义的函数executeCallNoReturn(block){//这里要隔离,不能影响其他变量,函数参数怎么传递,返回值怎么传递是个问题let extraInfo = block.extraStatelet name = extraInfo.namelet args = block.inputsreturn ''}async executeIf(block) {let extraInfo = block.extraStatelet ifprefix = 'IF'let doprefix = 'DO'let isElse = falselet isEIf = falseif(extraInfo){//说明有elseisElse=trueif(extraInfo.elseIfCount){//说明有else ifisEIf = true}}let idx=[0];if(isEIf){//extraInfo.elseIfCount是一个int类型,我要直线这个int类型的值for (let i = 0; i < extraInfo.elseIfCount; i++) {idx.push(i+1)}}let isMatch = falsefor (let i = 0; i < idx.length; i++) {const index = idx[i];const condition = await this.evaluateCondition(block.inputs[ifprefix + index].block)if (condition) {//满足条件执行对应分支this.executeBlock(block.inputs[doprefix + index].block)isMatch=truebreak}}//说明都不匹配 执行else blockif(isElse&&!isMatch){this.executeBlock(block.inputs.ELSE.block)}return ''}executeFunction(block){if (!block) return;let funcName=block.typelet params=block.inputslet paramArr=[]for(let key in params){let param=params[key]if(param.block){let paramValue=this.evaluateInput(param.block)paramArr.push(paramValue)}}//解析函数的参数名//执行自定义函数console.log(1,params)return `${funcName}(${paramArr.join(',')})`}generateMixed(n) {let chars = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];let res = "";for(let i = 0; i < n ; i++) {let id = Math.floor(Math.random()*chars.length);res += chars[id];}return res;}execLine(code,id){//发送到服务器获取结果//执行事件this.callback({id,name:'call'})console.log('exec '+code)}async evaluateCondition(block){if (!block) return;let op = block.fields.OPlet left = this.evaluateInput(block.inputs.A.block)let right = this.evaluateInput(block.inputs.B.block)//发送到服务器获取结果//随机生成变量,服务器会返回这个变量值,这个变量值是boolean类型let key = this.generateMixed(5)switch (op) {case 'EQ':op = '=='break;case 'NEQ':op = '!='break;case 'LT':op = '<'break;case 'LTE':op = '<='break;case 'GT':op = '>'break;case 'GTE':op = '>='break;default:console.error(`Unsupported condition operator: ${op}`);break;}var code = `${key} = (${left} ${op} ${right})`var id=block.idawait this.callback({id,name:'call'})console.log('eval '+code)return true}evaluateInput(input) {if (!input) return null;let block = input;let btype=this.getBlockType(block)switch (btype) {case 'text'://普通text 常量节点return `'${block.fields.TEXT}'`;case 'math_number':return block.fields.NUM;case 'variables_get'://变量赋值给变量const varId = block.fields.VAR.id;return this.variables[varId];//返回变量的名字case 'function'://函数的返回值赋值给变量return this.executeFunction(block); // Recursively execute custom typesdefault:console.error(`Unsupported input block type: ${block.type}`);return null;}}}// Example usagevar funs = ['create_mat','create_hobj','write_mat','printlog','test_tpl']
const interpreter = new ASTInterpreter(ast,funs);interpreter.execute();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/366043.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[无广告!纯干货]免费用CodeFlying自动化生成一个专属的AI机器人

前言&#xff1a; 真心话&#xff0c;花3分钟看文章&#xff0c;再花5分钟体验&#xff0c;你会回来给我点赞的。 随着AIGC&#xff08;人工智能生成内容&#xff09;行业的迅猛发展&#xff0c;人工智能正在以前所未有的速度和方式改变我们的生活。 它不仅在娱乐、教育、医疗…

[数据集][目标检测]游泳者溺水检测数据集VOC+YOLO格式8275张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;8275 标注数量(xml文件个数)&#xff1a;8275 标注数量(txt文件个数)&#xff1a;8275 标注…

汇聚荣拼多多电商好不好?

拼多多电商好不好?这是一个值得探讨的问题。拼多多作为中国领先的电商平台之一&#xff0c;以其独特的商业模式和创新的营销策略吸引了大量用户。然而&#xff0c;对于这个问题的回答并不是简单的好或不好&#xff0c;而是需要从多个方面进行综合分析。 一、商品质量 来看拼多…

ONLYOFFICE:开启高效办公新时代的全能利器

ONLYOFFICE官网链接&#xff1a;在线办公套件 | ONLYOFFICE 在线PDF查看器和转换器 | ONLYOFFICE 在数字化办公日益普及的今天&#xff0c;一款高效、易用、功能强大的办公软件成为了企业和个人不可或缺的得力助手。而ONLYOFFICE&#xff0c;正是这样一款集多种功能于一身的优…

Spring系统学习 - 基于注解管理Bean

什么是基于注解的方式管理Bean 在 Spring 框架中&#xff0c;基于注解的方式管理 Bean 是一种非常流行且现代的方法。它允许你通过在类、方法或字段上添加特定的注解来声明 Bean 的创建和依赖注入&#xff0c;从而避免了在 XML 配置文件中定义 Bean 的繁琐工作。 注解和 XML …

Linux开发讲课29---Linux USB 设备驱动模型

Linux 内核源码&#xff1a;include\linux\usb.h Linux 内核源码&#xff1a;drivers\hid\usbhid\usbmouse.c 1. BUS/DEV/DRV 模型 "USB 接口"是逻辑上的 USB 设备&#xff0c;编写的 usb_driver 驱动程序&#xff0c;支持的是"USB 接口"&#xff1a; US…

Linux:系统安全及应用

目录 一、系统账号管理 1.1、系统账号清理 1.2、密码安全控制 1.3、命令历史限制 二、限制su命令用户 三、PAM安全认证 四、sudo机制提升权限 4.1、sudo机制介绍 4.2、用户别名案例 4.3、启用sudo操作日志 4.4、其他案列sudo 4.5、开关机安全控制 4.6、限制更改GR…

无线物联网练习题

文章目录 选择填空简答大题 选择 不属于物联网感知技术的是(A) A:ZigBee B:红外传感器 C:FRID D:传感器 ZigBee是一种无线通信技术&#xff0c;虽然它常用于物联网中作为设备之间的通信手段&#xff0c;但它本身并不是一种感知技术 关于物联网于与互联网的区别的描述&#xff…

昇思第6天

函数式自动微分 神经网络的训练主要使用反向传播算法&#xff0c;模型预测值&#xff08;logits&#xff09;与正确标签&#xff08;label&#xff09;送入损失函数&#xff08;loss function&#xff09;获得loss&#xff0c;然后进行反向传播计算&#xff0c;求得梯度&#…

一站式uniapp优质源码项目模版交易平台的崛起与影响

一、引言 随着信息技术的飞速发展&#xff0c;软件源码已成为推动行业进步的重要力量。源码的获取、交易和流通&#xff0c;对于开发者、企业以及项目团队而言&#xff0c;具有极其重要的意义。为满足市场对高质量源码资源的迫切需求&#xff0c;一站式uniapp优质源码项目模版…

501、二叉搜索树中的众数

给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。如果树中有不止一个众数&#xff0c;可以按 任意顺序 返回。 假定 BST 满足如下定义&#xff1…

Java的Object类

概述:所有类的根类(父类),所有的类都会直接或者间接继承Object类 Object中的toString()方法&#xff1a; 如果不重写这个toString方法&#xff1a;默认形式是&#xff1a; return getClass().getName() "" Integer.toHexString(hashCode()); 这个我们可以进到Obj…

鸿蒙开发岗位就业前景分析

在信息技术飞速发展的今天&#xff0c;操作系统作为计算机的灵魂&#xff0c;一直是技术创新和市场竞争的焦点。随着华为鸿蒙操作系统的推出&#xff0c;鸿蒙开发岗位逐渐成为IT行业的热门话题。本文将深入探讨鸿蒙开发岗位的就业前景&#xff0c;揭示这一领域的就业新趋势&…

MSVCR120.DLL丢失的多种修复方法,助你快速解决dll问题

在日常生活和工作中&#xff0c;电脑已经成为我们不可或缺的工具。然而&#xff0c;在使用电脑的过程中&#xff0c;我们常常会遇到一些问题&#xff0c;其中之一就是电脑运行软件时提示找不到msvcr120.dll。如果该文件缺失或损坏&#xff0c;可能会导致依赖它的应用程序无法启…

在WSL Ubuntu中启用root用户的SSH服务

在 Ubuntu 中&#xff0c;默认情况下 root 用户是禁用 SSH 登录的&#xff0c;这是为了增加系统安全性。 一、修改配置 找到 PermitRootLogin 行&#xff1a;在文件中找到 PermitRootLogin 配置项。默认情况下&#xff0c;它通常被设置为 PermitRootLogin prohibit-password 或…

代码随想录算法训练营第55天(py)| 单调栈 | 42. 接雨水*、84.柱状图中最大的矩形

42. 接雨水* 力扣链接 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 思路1 暴力 按列来计算。每一列雨水的高度&#xff0c;取决于&#xff0c;该列 左侧最高的柱子和右侧最高的柱子中&#xff0c;…

Study--Oracle-05-Oracler体系结构

一、oracle 体系概览 Oracle数据库的体系结构通常包括以下主要组件&#xff1a; 1、实例&#xff08;Instance&#xff09;&#xff1a;运行数据库的软件环境&#xff0c;包括内存结构&#xff08;SGA&#xff09;和进程结构&#xff08;Background Processes and User Proces…

【电路笔记】-A类放大器

A类放大器 文章目录 A类放大器1、A类放大器概述2、A类放大器基本通用发射极配置3、变压器耦合配置4、总结在 放大器类型简介的文章中,我们介绍了不同类别的放大器。 在本文中,我们将更详细地介绍A类放大器。 在介绍不同的A类放大器配置前,首先的是要记住放大器类别的选择标…

从新手到高手:Scala函数式编程完全指南,Scala 数据类型(4)

1、Scala 数据类型 Scala 与 Java有着相同的数据类型&#xff0c;下表列出了 Scala 支持的数据类型&#xff1a;

【程序大侠传】异步架构应用回调数据接收接口偶发NPE

前序 在这片浩瀚的代码江湖中&#xff0c;各大门派林立&#xff0c;各自修炼独门绝技&#xff0c;江湖中的侠士们分别担任着开发、测试、产品和运维的角色&#xff0c;共同守护着这片数字化的疆域。 开发门派&#xff1a;代码剑宗 代码剑宗的弟子们精通各种编程语言&#xff…