当前位置: 首页 > news >正文

JavaScript系列(50)--编译器实现详解

JavaScript编译器实现详解 🔨

今天,让我们深入探讨JavaScript编译器的实现。编译器是一个将源代码转换为目标代码的复杂系统,通过理解其工作原理,我们可以更好地理解JavaScript的执行过程。

编译器基础概念 🌟

💡 小知识:编译器通常包括词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成等阶段。每个阶段都有其特定的任务和挑战。

词法分析器实现 📊

// 1. Token类型定义
const TokenType = {// 关键字FUNCTION: 'FUNCTION',RETURN: 'RETURN',IF: 'IF',ELSE: 'ELSE',// 标识符和字面量IDENTIFIER: 'IDENTIFIER',NUMBER: 'NUMBER',STRING: 'STRING',// 运算符PLUS: 'PLUS',MINUS: 'MINUS',MULTIPLY: 'MULTIPLY',DIVIDE: 'DIVIDE',// 分隔符LEFT_PAREN: 'LEFT_PAREN',RIGHT_PAREN: 'RIGHT_PAREN',LEFT_BRACE: 'LEFT_BRACE',RIGHT_BRACE: 'RIGHT_BRACE',SEMICOLON: 'SEMICOLON',// 其他EOF: 'EOF'
};// 2. Token类
class Token {constructor(type, value, line, column) {this.type = type;this.value = value;this.line = line;this.column = column;}
}// 3. 词法分析器
class Lexer {constructor(source) {this.source = source;this.tokens = [];this.start = 0;this.current = 0;this.line = 1;this.column = 1;}scanTokens() {while (!this.isAtEnd()) {this.start = this.current;this.scanToken();}this.tokens.push(new Token(TokenType.EOF, null,this.line, this.column));return this.tokens;}scanToken() {const c = this.advance();switch (c) {// 单字符tokencase '(': this.addToken(TokenType.LEFT_PAREN); break;case ')': this.addToken(TokenType.RIGHT_PAREN); break;case '{': this.addToken(TokenType.LEFT_BRACE); break;case '}': this.addToken(TokenType.RIGHT_BRACE); break;case ';': this.addToken(TokenType.SEMICOLON); break;// 运算符case '+': this.addToken(TokenType.PLUS); break;case '-': this.addToken(TokenType.MINUS); break;case '*': this.addToken(TokenType.MULTIPLY); break;case '/':if (this.match('/')) {// 单行注释while (this.peek() !== '\n' && !this.isAtEnd()) {this.advance();}} else {this.addToken(TokenType.DIVIDE);}break;// 忽略空白字符case ' ':case '\r':case '\t':break;case '\n':this.line++;this.column = 1;break;// 字符串case '"': this.string(); break;default:if (this.isDigit(c)) {this.number();} else if (this.isAlpha(c)) {this.identifier();} else {throw new Error(`Unexpected character: ${c} at line ${this.line}`);}break;}}// 辅助方法advance() {this.column++;return this.source.charAt(this.current++);}match(expected) {if (this.isAtEnd()) return false;if (this.source.charAt(this.current) !== expected) return false;this.current++;return true;}peek() {if (this.isAtEnd()) return '\0';return this.source.charAt(this.current);}isAtEnd() {return this.current >= this.source.length;}addToken(type, literal = null) {const text = this.source.substring(this.start, this.current);this.tokens.push(new Token(type, literal || text, this.line, this.column));}
}

语法分析器实现 🚀

// 1. AST节点类型
class ASTNode {constructor(type) {this.type = type;}
}// 2. 表达式节点
class BinaryExpr extends ASTNode {constructor(left, operator, right) {super('BinaryExpr');this.left = left;this.operator = operator;this.right = right;}
}class UnaryExpr extends ASTNode {constructor(operator, right) {super('UnaryExpr');this.operator = operator;this.right = right;}
}class LiteralExpr extends ASTNode {constructor(value) {super('LiteralExpr');this.value = value;}
}// 3. 语法分析器
class Parser {constructor(tokens) {this.tokens = tokens;this.current = 0;}parse() {try {return this.expression();} catch (error) {console.error('Parse error:', error);return null;}}expression() {return this.term();}term() {let expr = this.factor();while (this.match(TokenType.PLUS, TokenType.MINUS)) {const operator = this.previous();const right = this.factor();expr = new BinaryExpr(expr, operator, right);}return expr;}factor() {let expr = this.unary();while (this.match(TokenType.MULTIPLY, TokenType.DIVIDE)) {const operator = this.previous();const right = this.unary();expr = new BinaryExpr(expr, operator, right);}return expr;}unary() {if (this.match(TokenType.MINUS)) {const operator = this.previous();const right = this.unary();return new UnaryExpr(operator, right);}return this.primary();}primary() {if (this.match(TokenType.NUMBER)) {return new LiteralExpr(parseFloat(this.previous().value));}if (this.match(TokenType.LEFT_PAREN)) {const expr = this.expression();this.consume(TokenType.RIGHT_PAREN,"Expect ')' after expression.");return expr;}throw new Error('Expect expression.');}// 辅助方法match(...types) {for (const type of types) {if (this.check(type)) {this.advance();return true;}}return false;}check(type) {if (this.isAtEnd()) return false;return this.peek().type === type;}advance() {if (!this.isAtEnd()) this.current++;return this.previous();}isAtEnd() {return this.peek().type === TokenType.EOF;}peek() {return this.tokens[this.current];}previous() {return this.tokens[this.current - 1];}
}

代码生成器实现 💻

// 1. 代码生成器
class CodeGenerator {constructor() {this.output = '';this.indent = 0;}generate(ast) {return this.visitNode(ast);}visitNode(node) {switch (node.type) {case 'BinaryExpr':return this.generateBinaryExpr(node);case 'UnaryExpr':return this.generateUnaryExpr(node);case 'LiteralExpr':return this.generateLiteralExpr(node);default:throw new Error(`Unknown node type: ${node.type}`);}}generateBinaryExpr(node) {const left = this.visitNode(node.left);const right = this.visitNode(node.right);return `(${left} ${node.operator.value} ${right})`;}generateUnaryExpr(node) {const right = this.visitNode(node.right);return `(${node.operator.value}${right})`;}generateLiteralExpr(node) {return node.value.toString();}
}// 2. 优化器
class Optimizer {optimize(ast) {return this.visitNode(ast);}visitNode(node) {switch (node.type) {case 'BinaryExpr':return this.optimizeBinaryExpr(node);case 'UnaryExpr':return this.optimizeUnaryExpr(node);case 'LiteralExpr':return node;default:throw new Error(`Unknown node type: ${node.type}`);}}optimizeBinaryExpr(node) {const left = this.visitNode(node.left);const right = this.visitNode(node.right);// 常量折叠if (left.type === 'LiteralExpr' && right.type === 'LiteralExpr') {const result = this.evaluateConstExpr(left.value,node.operator.value,right.value);return new LiteralExpr(result);}return new BinaryExpr(left, node.operator, right);}evaluateConstExpr(left, operator, right) {switch (operator) {case '+': return left + right;case '-': return left - right;case '*': return left * right;case '/': return left / right;default:throw new Error(`Unknown operator: ${operator}`);}}
}// 3. 源码映射生成器
class SourceMapGenerator {constructor() {this.mappings = [];this.sources = [];this.names = [];}addMapping(generated, original, source, name) {this.mappings.push({generated,original,source,name});}generate() {return {version: 3,file: 'output.js',sourceRoot: '',sources: this.sources,names: this.names,mappings: this.encodeMappings()};}encodeMappings() {// 实现VLQ编码return this.mappings.map(mapping => {return [mapping.generated.line,mapping.generated.column,mapping.original.line,mapping.original.column].join(',');}).join(';');}
}

实际应用场景 💼

// 1. 简单计算器编译器
class CalculatorCompiler {constructor() {this.lexer = null;this.parser = null;this.generator = null;}compile(source) {// 词法分析this.lexer = new Lexer(source);const tokens = this.lexer.scanTokens();// 语法分析this.parser = new Parser(tokens);const ast = this.parser.parse();// 优化const optimizer = new Optimizer();const optimizedAst = optimizer.optimize(ast);// 代码生成this.generator = new CodeGenerator();return this.generator.generate(optimizedAst);}
}// 2. DSL编译器
class DSLCompiler {constructor(grammar) {this.grammar = grammar;this.lexer = null;this.parser = null;}compile(source) {// 根据语法规则生成词法分析器this.lexer = this.createLexer(source);const tokens = this.lexer.scanTokens();// 根据语法规则生成语法分析器this.parser = this.createParser(tokens);const ast = this.parser.parse();// 生成目标代码return this.generateCode(ast);}createLexer(source) {// 根据语法规则创建自定义词法分析器return new CustomLexer(source, this.grammar.tokens);}createParser(tokens) {// 根据语法规则创建自定义语法分析器return new CustomParser(tokens, this.grammar.rules);}generateCode(ast) {// 根据AST生成目标代码const generator = new CustomCodeGenerator(this.grammar.target);return generator.generate(ast);}
}// 3. 模板编译器
class TemplateCompiler {constructor() {this.cache = new Map();}compile(template) {if (this.cache.has(template)) {return this.cache.get(template);}const tokens = this.tokenize(template);const ast = this.parse(tokens);const code = this.generate(ast);const render = new Function('data', code);this.cache.set(template, render);return render;}tokenize(template) {const tokens = [];let current = 0;while (current < template.length) {if (template[current] === '{' && template[current + 1] === '{') {// 处理表达式current += 2;let expr = '';while (current < template.length && !(template[current] === '}' && template[current + 1] === '}')) {expr += template[current];current++;}tokens.push({type: 'expression',value: expr.trim()});current += 2;} else {// 处理文本let text = '';while (current < template.length && !(template[current] === '{' && template[current + 1] === '{')) {text += template[current];current++;}tokens.push({type: 'text',value: text});}}return tokens;}
}

性能优化技巧 ⚡

// 1. 缓存优化
class CompilerCache {constructor() {this.tokenCache = new Map();this.astCache = new Map();this.codeCache = new Map();}getTokens(source) {const hash = this.hashSource(source);if (this.tokenCache.has(hash)) {return this.tokenCache.get(hash);}const tokens = new Lexer(source).scanTokens();this.tokenCache.set(hash, tokens);return tokens;}getAST(tokens) {const hash = this.hashTokens(tokens);if (this.astCache.has(hash)) {return this.astCache.get(hash);}const ast = new Parser(tokens).parse();this.astCache.set(hash, ast);return ast;}getCode(ast) {const hash = this.hashAST(ast);if (this.codeCache.has(hash)) {return this.codeCache.get(hash);}const code = new CodeGenerator().generate(ast);this.codeCache.set(hash, code);return code;}hashSource(source) {// 实现源码哈希return source.length + source.slice(0, 100);}hashTokens(tokens) {// 实现tokens哈希return tokens.map(t => t.type + t.value).join('');}hashAST(ast) {// 实现AST哈希return JSON.stringify(ast);}
}// 2. 并行处理
class ParallelCompiler {constructor(workerCount = navigator.hardwareConcurrency) {this.workers = [];this.initWorkers(workerCount);}async initWorkers(count) {for (let i = 0; i < count; i++) {const worker = new Worker('compiler-worker.js');this.workers.push(worker);}}async compile(sources) {const chunks = this.splitSources(sources);const promises = chunks.map((chunk, index) => {return new Promise((resolve, reject) => {const worker = this.workers[index % this.workers.length];worker.onmessage = e => resolve(e.data);worker.onerror = reject;worker.postMessage({ type: 'compile', sources: chunk });});});const results = await Promise.all(promises);return this.mergeResults(results);}splitSources(sources) {// 将源码分割成多个块const chunkSize = Math.ceil(sources.length / this.workers.length);const chunks = [];for (let i = 0; i < sources.length; i += chunkSize) {chunks.push(sources.slice(i, i + chunkSize));}return chunks;}
}// 3. 增量编译
class IncrementalCompiler {constructor() {this.cache = new CompilerCache();this.dependencies = new Map();this.modifiedFiles = new Set();}markFileModified(file) {this.modifiedFiles.add(file);// 标记依赖文件const deps = this.dependencies.get(file) || new Set();for (const dep of deps) {this.markFileModified(dep);}}async compile(files) {const results = new Map();for (const file of files) {if (!this.modifiedFiles.has(file) && this.cache.has(file)) {results.set(file, this.cache.get(file));continue;}const result = await this.compileFile(file);results.set(file, result);this.cache.set(file, result);this.modifiedFiles.delete(file);}return results;}async compileFile(file) {const source = await this.readFile(file);const tokens = this.cache.getTokens(source);const ast = this.cache.getAST(tokens);// 收集依赖this.collectDependencies(file, ast);return this.cache.getCode(ast);}collectDependencies(file, ast) {const deps = new Set();this.traverseAST(ast, node => {if (node.type === 'Import') {deps.add(node.source);}});this.dependencies.set(file, deps);}
}

最佳实践建议 💡

  1. 错误处理和恢复
// 1. 错误收集器
class ErrorCollector {constructor() {this.errors = [];}addError(error) {this.errors.push({message: error.message,line: error.line,column: error.column,phase: error.phase});}hasErrors() {return this.errors.length > 0;}getErrors() {return this.errors;}clear() {this.errors = [];}
}// 2. 错误恢复策略
class ErrorRecovery {static recoverFromSyntaxError(parser) {// 跳过到下一个同步点while (!parser.isAtEnd()) {if (parser.match(TokenType.SEMICOLON)) return;if (parser.peek().type === TokenType.RIGHT_BRACE) return;parser.advance();}}
}// 3. 诊断信息生成
class DiagnosticReporter {constructor(source) {this.source = source;this.lines = source.split('\n');}report(error) {const line = this.lines[error.line - 1];const pointer = ' '.repeat(error.column - 1) + '^';return [`Error: ${error.message}`,`  at line ${error.line}, column ${error.column}`,line,pointer,`Phase: ${error.phase}`].join('\n');}
}

结语 📝

JavaScript编译器的实现是一个复杂但有趣的主题。通过本文,我们学习了:

  1. 编译器的基本架构和工作原理
  2. 词法分析和语法分析的实现
  3. 代码生成和优化技术
  4. 性能优化策略
  5. 错误处理和最佳实践

💡 学习建议:在实现编译器时,要注意模块化设计和错误处理。合理使用缓存和优化策略,可以显著提升编译性能。同时,良好的错误提示对于开发者体验至关重要。


如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

JavaScript系列(50)--编译器实现详解

JavaScript编译器实现详解 &#x1f528; 今天&#xff0c;让我们深入探讨JavaScript编译器的实现。编译器是一个将源代码转换为目标代码的复杂系统&#xff0c;通过理解其工作原理&#xff0c;我们可以更好地理解JavaScript的执行过程。 编译器基础概念 &#x1f31f; &…...

大数据相关职位 职业进阶路径

大数据相关职位 & 职业进阶路径 &#x1f4cc; 大数据相关职位 & 职业进阶路径 大数据领域涵盖多个方向&#xff0c;包括数据工程、数据分析、数据治理、数据科学等&#xff0c;每个方向的进阶路径有所不同。以下是大数据相关职位的详细解析及其职业进阶关系。 &#…...

基础项目实战——学生管理系统(c++)

目录 前言一、功能菜单界面二、类与结构体的实现三、录入学生信息四、删除学生信息五、更改学生信息六、查找学生信息七、统计学生人数八、保存学生信息九、读取学生信息十、打印所有学生信息十一、退出系统十二、文件拆分结语 前言 这一期我们来一起学习我们在大学做过的课程…...

C++,STL,【目录篇】

文章目录 一、简介二、内容提纲第一部分&#xff1a;STL 概述第二部分&#xff1a;STL 容器第三部分&#xff1a;STL 迭代器第四部分&#xff1a;STL 算法第五部分&#xff1a;STL 函数对象第六部分&#xff1a;STL 高级主题第七部分&#xff1a;STL 实战应用 三、写作风格四、…...

【Rust自学】15.3. Deref trait Pt.2:隐式解引用转化与可变性

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.3.1. 函数和方法的隐式解引用转化(Deref Coercion) 隐式解引用转化(Deref Coercion)是为函数和方法提供的一种便捷特性。 它的原理是…...

密码强度验证代码解析:C语言实现与细节剖析

在日常的应用开发中&#xff0c;密码强度验证是保障用户账户安全的重要环节。今天&#xff0c;我们就来深入分析一段用C语言编写的密码强度验证代码&#xff0c;看看它是如何实现对密码强度的多维度检测的。 代码整体结构 这段C语言代码主要实现了对输入密码的一系列规则验证&a…...

arkts bridge使用示例

接上一篇&#xff1a;arkui-x跨平台与android java联合开发-CSDN博客 本篇讲前端arkui如何与后端其他平台进行数据交互&#xff0c;接上一篇&#xff0c;后端os平台为Android java。 arkui-x框架提供了一个独特的机制&#xff1a;bridge。 1、前端接口定义实现 定义一个bri…...

LINUX部署微服务项目步骤

项目简介技术栈 主体技术&#xff1a;SpringCloud&#xff0c;SpringBoot&#xff0c;VUE2&#xff0c; 中间件&#xff1a;RabbitMQ、Redis 创建用户 在linux服务器home下创建用户qshh&#xff0c;用于后续本项目需要的环境进行安装配置 #创建用户 useradd 用户名 #设置登录密…...

zsh安装插件

0 zsh不仅在外观上比较美观&#xff0c;而且其具有强大的插件&#xff0c;如果不使用那就亏大了。 官方插件库 https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins 官方插件库并不一定有所有的插件&#xff0c;比如zsh-autosuggestions插件就不再列表里&#xff0c;下面演示zs…...

网站如何正式上线(运维详解)

因为平台原因&#xff0c;不能有太多链接&#xff0c;所以下文中链接都删除了&#xff0c;想访问的去原文链接&#xff1a;https://www.zhoudongqi.com/ TIPS 这篇文章是我自己运营运维的wordpess站点的经验总结&#xff0c;可以说十分详细&#xff0c;域名&#xff0c;服务器和…...

SQL server 数据库使用整理

标题&#xff1a;SQL server 数据库使用整理 1.字符串表名多次查询 2.读取SQL中Json字段中的值&#xff1a;JSON_VALUE&#xff08;最新版本支持&#xff0c;属性名大小写敏感&#xff09; 1.字符串表名多次查询 SELECT ROW_NUMBER() OVER (ORDER BY value ASC) rowid,value…...

【Rust自学】17.2. 使用trait对象来存储不同值的类型

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 17.2.1. 需求 这篇文章以一个例子来介绍如何在Rust中使用trait对象来存储不同值的类型。 …...

初始化mysql报错cannot open shared object file: No such file or directory

报错展示 我在初始化msyql的时候报错&#xff1a;mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory 解读&#xff1a; libaio包的作用是为了支持同步I/O。对于数据库之类的系统特别重要&#xff0c;因此…...

2025年1月22日(网络编程)

系统信息&#xff1a; ubuntu 16.04LTS Raspberry Pi Zero 2W 系统版本&#xff1a; 2024-10-22-raspios-bullseye-armhf Python 版本&#xff1a;Python 3.9.2 已安装 pip3 支持拍摄 1080p 30 (1092*1080), 720p 60 (1280*720), 60/90 (640*480) 已安装 vim 已安装 git 学习…...

Jason配置环境变量

jason官网 https://jason-lang.github.io/ https://github.com/jason-lang/jason/releases 步骤 安装 Java 21 或更高版本 安装 Visual Studio Code 根据操作系统&#xff0c;请按照以下具体步骤操作 视窗 下载 Jason 的最新版本&#xff0c;选择“jason-bin-3.3.0.zip”…...

蓝桥杯python语言基础(7)——自定义排序和二分查找

目录 一、自定义排序 &#xff08;一&#xff09;sorted &#xff08;二&#xff09;list.sort 二、二分查找 bisect 一、自定义排序 &#xff08;一&#xff09;sorted sorted() 函数会返回一个新的已排序列表&#xff0c;而列表的 sort() 方法会直接在原列表上进行排序…...

(开源)基于Django+Yolov8+Tensorflow的智能鸟类识别平台

1 项目简介&#xff08;开源地址在文章结尾&#xff09; 系统旨在为了帮助鸟类爱好者、学者、动物保护协会等群体更好的了解和保护鸟类动物。用户群体可以通过平台采集野外鸟类的保护动物照片和视频&#xff0c;甄别分类、实况分析鸟类保护动物&#xff0c;与全世界各地的用户&…...

后盾人JS--闭包明明白白

延伸函数环境生命周期 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> <…...

redis的分片集群模式

redis的分片集群模式 1 主从哨兵集群的问题和分片集群特点 主从哨兵集群可应对高并发写和高可用性&#xff0c;但是还有2个问题没有解决&#xff1a; &#xff08;1&#xff09;海量数据存储 &#xff08;2&#xff09;高并发写的问题 使用分片集群可解决&#xff0c;分片集群…...

Kiwi 安卓浏览器本月停止维护,扩展功能迁移至 Edge Canary

IT之家 1 月 25 日消息&#xff0c;科技媒体 Android Authority 今天&#xff08;1 月 25 日&#xff09;发布博文&#xff0c;报道称 Kiwi 安卓浏览器将于本月停止维护&#xff0c;相关扩展支持功能已整合到微软 Edge Canary 浏览器中。 开发者 Arnaud42 表示 Kiwi 安卓浏览器…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...