开源代码被人抄去用另一个语言重写闭源,只能认栽吗
如题。每次开源项目更新后第二天,闭源的程序就能跟进一样的功能。使用 IDA 反编译后发现其闭源程序部分实现逻辑相似度较高,只是使用了不同语言,而对方认为他用另一个语言重写了就是没有相似度、和开源原作无关联。
开源的时候不知道江湖水深,选择的是 MPL-2.0 ,是只能认栽了吗?
如题。每次开源项目更新后第二天,闭源的程序就能跟进一样的功能。使用 IDA 反编译后发现其闭源程序部分实现逻辑相似度较高,只是使用了不同语言,而对方认为他用另一个语言重写了就是没有相似度、和开源原作无关联。
开源的时候不知道江湖水深,选择的是 MPL-2.0 ,是只能认栽了吗?
书接上回,在《 Hulo 语言架构:从源代码到目标代码的完整流程》一文中,我们介绍了Hulo编程语言的整体架构和编译流程。今天,让我们深入探讨编译流程中的第一个关键环节——解析器。
解析器可以说是源代码到目标语言最重要的基础,它负责将结构化的文本实例化为抽象语法树(AST),这个过程也被称之为编译前端。解析器通过词法分析器(Lexer)将源代码分解为标记流(Token Stream),再通过语法分析器(Parser)将标记流转换为抽象语法树,最终将人类可读的源代码转换为机器可处理的树形数据结构。这个树形结构保留了源代码的语法结构信息,为后续的语义分析、类型检查、优化和代码生成等编译后端阶段提供了必要的数据基础。
听起来好像云里雾里是吧,别急,接下来我们举一个简单的例子来说明:
假设我们现在有这样一段代码:print("Hello, World!")
Token 是词法分析的最小单位,每个 Token 都包含类型和值信息。对于上面的代码,词法分析器会将其分解为以下 Token 序列:
类型 | 值 |
---|---|
IDENT | |
LPAREN | ( |
STRING | "Hello, World!" |
RPAREN | ) |
Ps. 字面量是一种很常见的说法,比如说 3.14 、10 、0644 这些数字就可以被成为 NUMBER 类型的字面量,而 true 和 false 则是 BOOL 类型的字面量。
也就是说,Token 的作用就是将结构化的语法每个部分进行细分,细分到不可再分为止。我们可以在看一个稍微复杂的例子:
class User {
name: str
age: bool
}
类型 | 值 | 说明 |
---|---|---|
CLASS | class | 类声明关键字 |
IDENT | User | 类名标识符 |
LBRACE | { | 左大括号,类体开始 |
IDENT | name | 字段名标识符 |
COLON | : | 类型声明分隔符 |
IDENT | str | 类型名标识符 |
IDENT | age | 字段名标识符 |
COLON | : | 类型声明分隔符 |
IDENT | bool | 类型名标识符 |
RBRACE | } | 右大括号,类体结束 |
词法分析器负责将源代码字符串分解为 Token 流。它的工作过程如下:
例如,对于print("Hello, World!")
:
print
→ 识别为标识符(IDENT)(
→ 识别为左括号(LPAREN)"Hello, World!"
→ 识别为字符串字面量(STRING))
→ 识别为右括号(RPAREN)经过词法分析器的处理,源代码被分解为 Token[]
数组,每个 Token 都包含了类型和值信息。
语法分析器负责将 Token 流转换为抽象语法树(AST)。它根据语言的语法规则,将 Token 组织成有意义的语法结构。
对于print("Hello, World!")
,语法分析器会构建如下 AST:
CallExpr
├── Fun: Ident("print")
└── Args: [StringLiteral("Hello, World!")]
这个 AST 表示:
看到这里,是不是感觉有点熟悉了?在大部分现代化语言的标准库中,往往都包含着解析成该语言 AST 的库。例如:
go/ast
- 提供 Go 语言的 AST 定义和解析功能@typescript-eslint/parser
- TypeScript 的官方解析器ast
模块 - Python 标准库中的抽象语法树模块@babel/parser
- Babel 生态中的 JavaScript 解析器syn
库 - Rust 的语法解析库javac
编译器内置的 AST 处理这些库不仅为语言本身提供了强大的代码分析能力,也为开发者构建工具链、代码格式化、静态分析、代码生成等提供了基础支持。通过使用这些标准化的 AST 库,开发者可以更容易地实现代码转换、优化和工具开发。
回到分析器本身,我们已经完成了从源代码到结构化实例的转换,是的,编译前端就是在做这样的工作,将难以操作的字符串转换成一个个对象,例如 CallExpr 表达式对象、IfStmt 语句对象、ClassDecl 声明对象... 这些转换将代码变得可操作了起来,它不再是只能靠正则表达式或者字符串处理的语法。
在 AST 中,节点通常分为三大类:
Expr (Expression): 表达式节点,表示会产生值的代码片段。例如:
CallExpr
: 函数调用表达式,如 print("hello")
BinaryExpr
: 二元运算表达式,如 a + b
Ident
: 标识符表达式,如变量名 x
StringLiteral
: 字符串字面量,如 "hello"
Stmt (Statement): 语句节点,表示执行动作的代码片段。例如:
IfStmt
: if 条件语句,如 if (x > 0) { ... }
WhileStmt
: while 循环语句,如 while (i < 10) { ... }
AssignStmt
: 赋值语句,如 x = 10
ReturnStmt
: 返回语句,如 return result
Decl (Declaration): 声明节点,表示定义新实体的代码片段。例如:
ClassDecl
: 类声明,如 class User { ... }
FuncDecl
: 函数声明,如 function add(a, b) { ... }
VarDecl
: 变量声明,如 var x = 10
这种分类方式使得 AST 具有清晰的层次结构,便于后续的语义分析、类型检查和代码生成。
Ps. 当然这都是人为划定的,你也可以都把他们当成同样的节点也是可以的。不过,合理的分类能够帮助我们更好地理解代码结构,并为后续的编译阶段提供更清晰的语义信息。
如果你很轻松 50 万一年 会接受 6 万一个月事业单位的媳妇吗 心理会不会想再找找 工资再高点的?
一切源于朋友圈有个会画画的宝妈晒给自己娃画像,但我不会画。
所以我用 stable diffusion 把崽的照片转成简笔画风格,
再用这个转换成视频,然后发朋友圈,就好像我一笔一画地画出来一样😤😤
比如下面是原图:
转换之后可以变为这样(实际生成的是视频不是 gif ):
为庆祝 V2EX 代币上线,现推出专属福利活动!
新用户专享
✅ 即可免费获得:
📌 注意:每个 Solana 钱包地址仅可参与一次
🚀 马上行动:点击绑定钱包
最近 V 站加密货币大热,我也用$V2EX 注册了个小号 @eyebrowkang ,本来打算发在小号的,不过提示注册不满 14 天之类的,还是发在这里吧。
我这里分享加密货币提现的一种方法,供大家参考,此方法使用略有门槛,本文发布在我的博客白眉斋,各位有疑问可以在本帖提出,下面是原文:
本文是一篇简单的杜高思贝银行账户的使用指南,包括开户、出入金、各项费用介绍等部分,其中重点介绍加密货币入金以及出金到 wise 的过程及损耗。
杜高思贝银行位于瑞士日内瓦,既是银行也是证券交易商,具体可以查看其官网https://www.dukascopy.com/swiss/chinese/about/dukascopy-group/,大多数页面都有中文版本,这里不多赘述。 本文主要对其银行的功能进行说明,银行另有一个官网是https://www.dukascopy.bank/swiss/?lang=cn,账户是多币种账户,官方宣传语是
享受瑞士银行账户的优势,提供 24 种货币、国际卡、无缝跨境支付和有吸引力的汇率。
默认不会开通所有货币的账户,但是一旦开通就无法在网站和 APP 关闭,所以建议用到对应币种的时候再开户,而且按照本文的使用方法,其实开通欧元账户就够了。
由于我早在 2022 年就已经开户了,因此关于开户的细节我记得不是特别清晰,或者可能有所变化,大家可以在网络上搜索近期的更为详细的开户教程,这里我只做简单描述。
首先需要准备好:
DOMAIN-SUFFIX,dukascopy.com
DOMAIN-SUFFIX,dukascopy.bank
DOMAIN-SUFFIX,dukascopy.online
网站的静态资源使用 Cloudflare 托管,API 和 Websocket 是托管在 AWS 和自家的 ASN
然后打开 https://www.dukascopy.bank/swiss/open-mca-account/ ,从官网的二维码下载 APP ,按照要求操作即可。(如果看完之后觉得本文有用,可以填写我的邀请码E38-RNX
,当然不填也无所谓,不受影响)
另外,开户需要视频验证,默认是英文,我当时并没有要求中文客服,只要会一些基本的英文就问题不大,不过如果希望稳一点的话,是可以用中文开户的,具体方法各位自行搜索。
下附个人开户过程的截图,供参考:
选择护照
然后我就直接开始了
第二天就收到了开户成功的链接,设置密码登录即可
入金出金都有多种方式,下面介绍银行转账和加密货币两种入金方式,以及通过银行转账的出金方式,其他的方式和相关费用情况可以在官网https://www.dukascopy.bank/swiss/fees/?lang=cn看到。
杜高思贝作为接收方不会收取入金的手续费等其他费用,不过国内银行作为发送方会有手续费、电讯费之类的,还有中间行的额外费用,各大银行不同,且普遍不低。 以中国银行为例,跨境汇款最低收取 50 元/笔,另收电讯费,非港澳台地区人民币 150 元/笔。 也就是每笔跨境汇款损耗都会在 200 元人民币以上。国内最划算的应该是兴业银行的寰宇人生卡,但是我没有实际操作过,所以不确定真实费用。
而如果你有欧元区账户(例如 N26 或者 wise ),由于是单一欧元支付区( SEPA ),所以理论上应该是零损耗入金的。
使用银行转账出金时,建议转出到 wise ,因为杜高思贝出金的手续费是固定的,和转出金额无关,转出到单一欧元支付区( SEPA ),手续费仅有 2.3EUR ,是最低的,其他币种都贵很多。 并且 wise 的欧元账户也支持 SEPA ,最终可以做到 2.3 欧出金。
支持加密货币入金是我目前还在使用杜高思贝的唯一理由,除了交易所的 C2C ,这是将加密货币转换为法币的另一个选择。
目前杜高思贝仅支持绑定以太坊和比特币两种钱包地址,支持比特币、以太坊、泰达币(必须是 ERC20 网络)三种货币入金。具体信息可以在官网查看。
加密货币入金需要先绑定钱包,会通过签名来验证,每次签名有效期三个月,绑定之后更换钱包需要 50CHF (约 450 元),且需要发邮件联系客服,这也就意味着不可以从交易所直接入金。 另外,使用加密货币的全过程注意安全,避免可能的劫持和账户被盗等问题,建议操作过程浏览器只保留一个钱包插件开启。
下面是我从 metamask 钱包入金到杜高思贝(泰达币),然后转出到 wise 的详细过程:
详细的费用明细建议查看https://www.dukascopy.bank/swiss/fees/?lang=cn页面,这里我挑几个比较重要的进行说明:
虽然杜高思贝开户门槛不高,但是实际使用的话还是更适合已经有 wise 或者打算开通 wise 的人, 它的货币兑换由于有手续费,实际汇率不如 wise ,所以在我看来其优势只有一个,就是能把加密货币换成法币,这也是我目前的使用场景。
因此,如果你恰好有 wise 账户,并且希望寻找一个交易所 C2C 提现加密货币之外的方式,那么杜高思贝是国内用户为数不多的选择之一。
最后,如果觉得本文有用,记得注册的时候填写我的邀请码E38-RNX
,感谢你的阅读。
有推荐的卡吗
先把话说明白:这篇是踩坑复盘,不是“技术白皮书”。我从 Kiro 的 spec/space 到把它们拼成 workflow ,又一路换成 requirements-pilot ,最后落在 bmad-pilot 。中间爽点和雷点都写在这——不兜圈子。
于是我基于 BMAD-METHOD 做了 bmad-pilot:把“确认后开干”的顺滑,和“专业文档与角色分工”的秩序,合在一条流水线上。
提示:别一次性把所有角色全开。先跑最短链路,把第一条用户路径打通,再扩。
git clone https://github.com/cexll/myclaude
mkdir -p ~/.claude/{commands,agents}
cp -R myclaude/commands/* ~/.claude/commands/
cp -R myclaude/agents/* ~/.claude/agents/
我试过把东西“自动化到飞起”,也试过“先把话说清楚再干”。后者更诚实,也更稳。requirements-pilot 让人顺手,bmad-pilot 让人安心。前者像一把趁手的小刀,后者是一整套手术器械——对得上场景,才是真的爽。
注:在 IDE 阶段把 docs/prd.md 与 docs/architecture.md 分片到 docs/prd/ 与 docs/architecture/,方便 SM/Dev/QA 用小上下文跑活。
新收了一台 SE 一代,目前 13.3.1 的系统,想问一下各位升级 iOS15.8.4 值得吗。 用 13 系统的话就非永久越狱,15 的话就巨魔商店
从来没有用过 mac(大学的时候 舍友有个 macpro ,但是他装的 win...)
家里有一台去年买的台式,i714 + 4080 + 32g 办公游戏足够(就是显示器拉跨)
主要码代码/做设计,偶尔出差讲系统;
这次买笔记本,最看重的就是屏幕,一定要一个屏幕好点的,色彩好的;
我开发的时候,会有硬件,比如串口,usb ,蓝牙等 链接硬件,这个时候 是不是 mac 要比 win 适配起来要复杂呢;(有些驱动好像还只有 win 的...)
我想买个二手的 99 新机子;预算 1.2W 左右
看了半个月的海鲜市场了,准备入手一个 14 寸 M4PRO 14+20 24G 1T + 纳米;
在咸鱼这个配置 99 新 电池 100% 在保的,大概 1.5W 左右 贵吗;
前两天遇到个机子 国行 99 新 在保 电池 100%,14 寸 M4PRO 14+20 48G+ 1T 1.6W 不知道这价格是贵还是便宜;(现在卖掉了)
老哥们建议我买个什么配置;买的话怎么能把性价比拉满;
Solana 地址其实是个由 ED25519 公钥经过 Base58 编码后的字符串
和其他区块链( BTC 、ERC20 )一样,你也可以自己不断计算(类似于暴力穷举)出一个指定前后缀的 Vanity Address
这样你就可以获得 V2EX 开头的个性钱包地址啦,类似于我的:
V2EXpCPnTCcGfv6eZMbmJcNTseBaqWyBN4LJ67BwSEf
虽然 Github 上有很多开源工具,这里推荐使用 Solana 官方的 Solana CLI 工具
不建议你使用 GOOGLE 到的 XX 网页版生成工具,或者未经审查的软件,因为你有可能会泄露私钥,导致资产被盗!!
https://solana.com/docs/intro/installation#install-the-solana-cli
solana-keygen grind --starts-with V2EX:1
--starts-with V2EX:1:代表以 V2EX 开头,生成 1 个地址后就停止
与此对应的还有--ends-with 、 --starts-and-ends-with 参数
需要注意的是:指定的前后缀长度越长,难度是指数级递增,在我机器上生成一个 4 字符开头的地址大概需要 70 秒左右
耐心等待一会,见到输出下面的内容就是以及算出来一个可用的地址了:
Wrote keypair to V2EXxxxxxxxxxxx.json
solana-keygen
生成的地址会保存在当前目录的 json 文件中,其中文件名就是公钥(你的钱包地址)
你也可以通过 solana-keygen pubkey xxx.json
来获取钱包地址
文件的内容是私钥,不过是[12,34,56...]这种格式的,一个包含 64 个字节的数组来表示私钥
如果你需要将这个钱包地址导入类似于 Phantom 钱包中,需要做一下转换,将其转换为 base58 格式即可
这里提供一个简单的 Python 转换脚本示例
# 先安装依赖 pip install base58
import json
import sys
import base58
if len(sys.argv) != 2:
print('用法: python convert.py [path]')
sys.exit(1)
with open(sys.argv[1], 'r', encoding='utf-8') as f:
keypair_data = json.load(f)
secret_key = bytes(keypair_data)
encoded_secret_key = base58.b58encode(secret_key).decode()
print(f'Base58 编码的私钥:{encoded_secret_key}')
这样你就同时获得了公钥和对应的私钥,也就拥有了一个靓号地址了~ 转入 SOL 或 V2EX 代币试试吧
在过去的几个月里,我自己亲手构建了一个雏形系统:
它不是一个普通项目,也不是一次短期创业尝试。
一个连接工程师、科研人员、创意工作者的协作网络。
一个打破雇佣制、去中心化、自带能量循环的任务场域。
一个自由协作工坊和基地
我称它为:LunarTask | 月球任务系统
这个系统不是为“公司”打造的,而是为未来的自由构建者群体设计的。
我相信,未来的劳动方式不再依附于组织或雇主,
而是用 AI 代理、自主节奏、组队协作的方式完成一个完整闭环。
我是 ruby ,top2 毕业,前算法工程师,也是一位结构控、构建者、科幻小说写作者。
这个系统不是我个人的终点,它是我想发出的一个系统信标。
这个信标,给未来的工作方式、构建方式、意识协作方式,提供另一种可能。
欢迎邮件联系我( rubyhong266@gmail.com)
让我们从“完成一个任务”,到“共建一整个系统”
✴︎ 系统当前版本:v1.0 ✴︎ 起始日期:2025 年 8 月