elench-lang 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +53 -0
- package/README.md +302 -2
- package/bin/elench.js +69 -0
- package/package.json +37 -4
- package/scripts/clean-pycache.js +37 -0
- package/scripts/npm_smoke.js +88 -0
- package/src/README-/345/205/274/345/256/271/345/261/202.md +26 -0
- package/src/ast_util.py +111 -0
- package/src/bench.py +376 -0
- package/src/borrow.py +282 -0
- package/src/bound.py +13 -0
- package/src/cfg.py +219 -0
- package/src/chart.py +209 -0
- package/src/check_docs.py +156 -0
- package/src/checker.py +2473 -0
- package/src/contract_metric.py +87 -0
- package/src/cost_check.py +13 -0
- package/src/cost_diff.py +533 -0
- package/src/cost_domain/__init__.py +32 -0
- package/src/cost_domain/bound.py +739 -0
- package/src/cost_domain/cost_check.py +394 -0
- package/src/cost_domain/cost_interp.py +1998 -0
- package/src/cost_domain/symbolic.py +554 -0
- package/src/cost_explain.py +503 -0
- package/src/cost_interp.py +13 -0
- package/src/cxx_map.py +184 -0
- package/src/dispatch.py +314 -0
- package/src/dsh.py +3980 -0
- package/src/dup_scan.py +180 -0
- package/src/elench.py +15 -0
- package/src/emit.py +56 -0
- package/src/ffi_c.py +70 -0
- package/src/fmt.py +115 -0
- package/src/formatter.py +596 -0
- package/src/grammar.py +272 -0
- package/src/guarantees.py +116 -0
- package/src/highlight.py +156 -0
- package/src/interp.py +2119 -0
- package/src/isolated.py +161 -0
- package/src/jsonval.py +236 -0
- package/src/kappa_vs_measured.py +347 -0
- package/src/kinds.py +122 -0
- package/src/lexer.py +559 -0
- package/src/migrate_docs.py +115 -0
- package/src/otel.py +579 -0
- package/src/otel_dashboard.py +218 -0
- package/src/otel_export.py +380 -0
- package/src/otel_local_sink.py +141 -0
- package/src/otel_view.py +156 -0
- package/src/parser.py +1909 -0
- package/src/parser.py.bak +1781 -0
- package/src/policy.py +271 -0
- package/src/rename_ch.py +81 -0
- package/src/requires.py +242 -0
- package/src/segment_plan.py +150 -0
- package/src/shape.py +130 -0
- package/src/stdlib.py +1856 -0
- package/src/stdlib.py.bak +1751 -0
- package/src/symbolic.py +13 -0
- package/src/sync_docs.py +225 -0
- package/src/test_checker.py.bak +443 -0
- package/src/test_formatter.py.bak +201 -0
- package/src/test_invalid.py.bak +342 -0
- package/src/test_parser.py.bak +423 -0
- package/src/typecheck.py +865 -0
- package/src/typecheck.py.bak +741 -0
- package/src/typenames.py +56 -0
- package/src/walk.py +197 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
202
|
+
|
package/NOTICE
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Elench — 权利归属说明 / Ownership notice
|
|
2
|
+
=========================================
|
|
3
|
+
|
|
4
|
+
本仓库的代码与文档按组件区分归属,目的是让"项目成果"与"非项目工作"在
|
|
5
|
+
文件层面就有边界,而不是靠口头说明。
|
|
6
|
+
|
|
7
|
+
一、本项目(北京邮电大学 2026 年雏雁计划)范围内的成果
|
|
8
|
+
--------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
以下内容属于项目研究成果,知识产权归 **北京邮电大学** 所有
|
|
11
|
+
(《北京邮电大学本科生创新创业实践活动管理办法》校教发〔2018〕22 号 第十一条):
|
|
12
|
+
|
|
13
|
+
· src/lexer.py src/parser.py src/typecheck.py src/checker.py
|
|
14
|
+
· src/interp.py src/symbolic.py src/cost_interp.py src/cost_check.py
|
|
15
|
+
· src/stdlib.py src/jsonval.py src/fmt.py src/dsh.py(解释器相关子命令)
|
|
16
|
+
· tests/cases/test_*.py(测试套,123 个文件)
|
|
17
|
+
· tools/(检查与复现工具:artifact_check / defect_report / demo_repair 等)
|
|
18
|
+
· 文档/(语言规格、设计文档、样例程序、决策记录)
|
|
19
|
+
· 预印本与演示论文(论文的署名权归作者,单位署名为北京邮电大学)
|
|
20
|
+
|
|
21
|
+
学生作为实际完成人享有 **署名权**,并按学校与学院规定获得创新创业学分认定
|
|
22
|
+
与推免支持;软著等登记事项以学校为著作权人办理。
|
|
23
|
+
|
|
24
|
+
二、明确不在本项目范围内的内容
|
|
25
|
+
--------------------------------
|
|
26
|
+
|
|
27
|
+
以下内容 **不属于本项目成果**,不纳入上述产权约定:
|
|
28
|
+
|
|
29
|
+
· **编译器后端(代码生成)**:把 `.eln` 翻译为 C++ 或任何原生代码的
|
|
30
|
+
实现、以及为它生成的产物(`.cpp` / `.h` / 可执行文件)。
|
|
31
|
+
当前仓库中的 `elench cpp` 子命令属于**实验性、待移出**的部分:
|
|
32
|
+
它不承诺、不验收,也不使用项目经费与工时。
|
|
33
|
+
|
|
34
|
+
若日后开发编译器后端,应 **另行立项**,或作为 **个人作品** 放在独立仓库,
|
|
35
|
+
并在该仓库的 NOTICE 中单独声明归属。
|
|
36
|
+
|
|
37
|
+
三、开源发布
|
|
38
|
+
------------
|
|
39
|
+
|
|
40
|
+
本仓库以 Apache-2.0 公开,**须经学校审批或备案**。
|
|
41
|
+
发布时的版权行写法:
|
|
42
|
+
|
|
43
|
+
Copyright 2026 Beijing University of Posts and Telecommunications
|
|
44
|
+
(interpreter, specification, tooling)
|
|
45
|
+
|
|
46
|
+
四、边界的时间依据
|
|
47
|
+
------------------
|
|
48
|
+
|
|
49
|
+
立项前已完成并公开的版本(v0.1)为 **前期基础**,不作为结题成果:
|
|
50
|
+
|
|
51
|
+
git tag v0.1-pre-project
|
|
52
|
+
|
|
53
|
+
该 tag 的提交时间与 GitHub 发布时间戳,是"在先"的客观证据。
|
package/README.md
CHANGED
|
@@ -1,3 +1,303 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AI 导向编程语言
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **许可证**:代码与文档均为 [Apache-2.0](LICENSE)。
|
|
4
|
+
> **引用**:见 [`CITATION.cff`](CITATION.cff)(GitHub 页面右上会出现「Cite this repository」)。
|
|
5
|
+
> **DOI**:**尚无**。计划在 **M1 退出门槛②(双值域统一)达成后**打 tag `v0.70-m1` 并发布到 Zenodo。
|
|
6
|
+
> 在拿到 DOI 之前,引用请用仓库 URL + 提交号,**不要编造 DOI**。
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
> **把「我想让它多快」从注释里搬到编译器能查的地方。**
|
|
10
|
+
|
|
11
|
+
一门面向 AI 代码生成的编程语言:函数不只写「怎么做」,还写「要做到什么程度」——**成本由编译器算出,由人设定目标,两者的差记为债务**。
|
|
12
|
+
|
|
13
|
+
**当前状态**:**解释器、契约检查、成本域、最小 C++ 后端都在跑**(`src/`,**123 个测试文件**逐个通过);契约检查覆盖 effects / 借用 / 目标,成本判定是三值(达成 / 债务 / 无法判定);实验 S1–S4 已跑并出图。对外快照见 tag **`v1.0-preprint`**。
|
|
14
|
+
>
|
|
15
|
+
> **2026-11-06 更正**:这句此前是「设计 v0.66 / M0 完成 / 368 项测试 / M1 未开始 / 实验未跑」——**五项里四项已过期**。版本号不再手写在这里,以 `CHANGELOG.md` 与 tag 为准。
|
|
16
|
+
**这不是一个能用的语言**:它是一套**可检查的契约系统**加一个够跑样例的实现。能做的:算上界、判契约、把「不知道」明确说出来;不能做的:替代 C++、当完整编译器。
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 安装(npm)
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g elench-lang # 装完命令叫 `elench`
|
|
24
|
+
npx elench-lang --help # 不装也能试
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> **包名 `elench-lang` 与命令名 `elench` 不同**:`elench` 被判与已有的 `wrench` 过近、
|
|
28
|
+
> `elenchus` 是别人的包,所以包用 `elench-lang`;**装的命令仍是 `elench`**。
|
|
29
|
+
|
|
30
|
+
**前置**:本机要有 **Python ≥ 3.10**(`python3` 或 `python` 在 PATH 里,或用 `PYTHON=/path/to/python` 指定)。
|
|
31
|
+
npm 包是**薄包装**——它不含 Python 运行时,只带 elench 的源码与一个转发脚本。
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## 它要解决的两个问题
|
|
35
|
+
|
|
36
|
+
| # | 问题 | 现在什么样 |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| 1 | **AI 写得出来,但核不了** | 性能信息只活在注释、PR 描述、作者脑子里,编译器一个都不看 |
|
|
39
|
+
| 2 | **常数因子只能靠猜** | 哈希集/排序扫描/位图,选哪个取决于输入——AI 猜不出临界点,因为它本来就不可推断 |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 六个机制
|
|
44
|
+
|
|
45
|
+
### 1. 意图与事实分开:`target` 由人冻结,`cost` 由编译器算出
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
spec evaluate(text: []u8) -> Result[i64, CalcError] {
|
|
49
|
+
effects {alloc};
|
|
50
|
+
target {
|
|
51
|
+
time : { max: O(text.length()) },
|
|
52
|
+
allocation: { max: O(text.length()) },
|
|
53
|
+
};
|
|
54
|
+
} end spec
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
编译器算出实际成本,写进 `evaluate.cost.yaml`(YAML,可 diff,变化项置顶):
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
functions:
|
|
61
|
+
evaluate: # ▲ 本次有变化
|
|
62
|
+
time: {min: "n", max: "n"}
|
|
63
|
+
allocation: {min: "0", max: "8*n"}
|
|
64
|
+
debt: {time: none, allocation: none}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**让 AI 写 `cost`,等于让被考的人自己报分。** 改成算出来之后,这一处谎言就不可能发生。
|
|
68
|
+
|
|
69
|
+
### 2. 声明与实现分家:`.tu` 装承诺,`.eln` 装实现
|
|
70
|
+
|
|
71
|
+
| 文件 | 谁写 | 内容 |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `模块名.tu` | 人(AI 提议) | 全部声明,几十行,**人真的会看完** |
|
|
74
|
+
| `模块名.ai` | AI | 签名 + 函数体,**零声明** |
|
|
75
|
+
| `模块名.cost.yaml` | 编译器 | 算出的成本 |
|
|
76
|
+
| `模块名.dispatch.yaml` | 测量 | `?!` 选了谁 |
|
|
77
|
+
|
|
78
|
+
**结果:可撒谎的位置 7 处(全在 `.tu`),`.eln` 里 0 处。**
|
|
79
|
+
|
|
80
|
+
### 3. 算法选择外包给测量:`?!` + `choose` + `over` 名单
|
|
81
|
+
|
|
82
|
+
候选写在宿主 spec 的 `choose` 子块里(完整程序见 [`样例/search.tu`](文档/样例/search.tu)):
|
|
83
|
+
|
|
84
|
+
<!-- @include 文档/样例/search.tu#choose -->
|
|
85
|
+
```
|
|
86
|
+
choose search_impl(const Vec<u64>& xs, u64 key) -> u64! {
|
|
87
|
+
over {
|
|
88
|
+
search_linear,
|
|
89
|
+
search_binary,
|
|
90
|
+
search_interp pending
|
|
91
|
+
}
|
|
92
|
+
;
|
|
93
|
+
objective time;
|
|
94
|
+
};
|
|
95
|
+
```
|
|
96
|
+
<!-- @end -->
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
val idx = ?!search_impl(xs, key); // 只有这一步未定
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| 硬规则 | 为什么 |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `?!` 的承诺是**分段上界**:按运行期分档表逐段取「该段真正会跑的那个候选」的 κ;无表时退回「所有候选取 max」 | 承诺与运行期**同源**——跑的不是承诺里那个候选,界就不成立 |
|
|
105
|
+
| `?!` **不能构成整个函数体** | 否则退化成"两套实现二选一",生成者就不必想清楚算法结构 |
|
|
106
|
+
|
|
107
|
+
### 4. 骨架先行:`pending`
|
|
108
|
+
|
|
109
|
+
下面是上一节那个 `choose` 块的关键一行(片段;完整块见上一节,权威样例见 [`样例/search.tu`](文档/样例/search.tu)):
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
choose search_impl(xs: []u64, key: u64) -> Result[u64, SearchError] {
|
|
113
|
+
over {search_linear, search_binary, search_interp pending}; // 声明:这个还没写
|
|
114
|
+
} end choose
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
| 命令 | 含未实现时 |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `elench check` | **通过**(骨架合法、可审) |
|
|
120
|
+
| `elench build` | **失败**(不能测量没写的候选) |
|
|
121
|
+
|
|
122
|
+
**检查器能算出"谁没写",但算不出"这是故意的还是漏的"**——`pending` 就是让作者承认。
|
|
123
|
+
|
|
124
|
+
### 5. 每个可能出错的地方留痕
|
|
125
|
+
|
|
126
|
+
| 设计 | 规则 |
|
|
127
|
+
|---|---|
|
|
128
|
+
| 算术返回 `Result` | `(a + b)?` —— 每个可能溢出的点必须写 `?` |
|
|
129
|
+
| 文本是字节 | `[]u8`,一元素一字节(不是 8 字节) |
|
|
130
|
+
| 无隐式转换 / 无类型后缀 / 一种写法 | `42u64` 是错的;`function` 是错误,不是兼容 |
|
|
131
|
+
| 块必须有终止符 | `if … end if`、`match … end match`、`kernels … end fn` |
|
|
132
|
+
|
|
133
|
+
### 6. 报告告诉你「哪些数字不能全信」
|
|
134
|
+
|
|
135
|
+
每份成本报告有独立的**信任区**,列出全部被信任的声明及其影响面。
|
|
136
|
+
**并把「算出来的」与「派生的」分开列——一个转发点不算一次独立验证。**
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 与其他语言的关系
|
|
141
|
+
|
|
142
|
+
| 语言 | 它做什么 | 本设计不同在哪 |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| **C++** | 通用系统语言 | 不追求通用,不替代 C++ |
|
|
145
|
+
| **Rust** | 内存安全 + 零开销 | 语义跟 Rust(移动、借用),但多一层**成本契约** |
|
|
146
|
+
| **Dafny / F\*** | 全功能验证 | 只做**有界**的成本与效果检查,不做完整验证 |
|
|
147
|
+
| **Zig** | 显式优于隐式 | 同源,但把「多快」也纳入显式 |
|
|
148
|
+
|
|
149
|
+
**不做什么**:不自研后端;不承诺精确时间(只承诺量级 + 结构上界);v0 不做代码生成与契约验证。
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 仓库结构
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
ai-lang-design/
|
|
157
|
+
├── src/ 实现(Python;**C++ 后端是最小切片,不是替代品**)
|
|
158
|
+
│ ├── lexer.py 词法分析
|
|
159
|
+
│ ├── parser.py 解析(宽松超集,带 span 诊断)
|
|
160
|
+
│ ├── checker.py 契约检查(F / B / V 系列、effects、借用、目标)
|
|
161
|
+
│ ├── cost_domain/ 成本域:符号界、目标比较、归因
|
|
162
|
+
│ ├── interp.py 具体执行器
|
|
163
|
+
│ ├── formatter.py `elench fmt`(幂等、注释保留)
|
|
164
|
+
│ ├── dsh.py 命令行入口(`elench` 是它的别名)
|
|
165
|
+
│ └── …
|
|
166
|
+
├── tests/cases/ **123 个测试文件**(逐个独立运行,全绿才算过)
|
|
167
|
+
├── tools/ 对拍、数字对账、实验脚本
|
|
168
|
+
├── corpus/adversarial/ 对抗语料(判不了就说判不了)
|
|
169
|
+
├── editors/ VSCode 扩展(语法高亮)
|
|
170
|
+
└── 文档/
|
|
171
|
+
├── 语言介绍.md ← 从这开始
|
|
172
|
+
├── 一屏对比.md
|
|
173
|
+
├── 语法清单.md
|
|
174
|
+
├── 对抗语料.md 每条难例的归因
|
|
175
|
+
├── 退出码与CI.md 各子命令的退出码 + 可抄的 CI 样例
|
|
176
|
+
├── 设计/
|
|
177
|
+
│ ├── 目前设计/ **主线 10 份**:规格、语法清单、决定清单、目标、能力索引…
|
|
178
|
+
│ ├── 目前设计/未做/ **可开工的条目**(两份台账 + 分析稿)
|
|
179
|
+
│ ├── 目前设计/未做/挂起/ 裁定暂不做的提案(**有"什么情况下改主意"**)
|
|
180
|
+
│ └── 归档/ 做完了的、被取代的
|
|
181
|
+
├── 实验/ A/B 实验、实测数据(默认不入库)
|
|
182
|
+
└── 其他/ 申报书草稿、入门长文、学习路线
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
> **2026-11-06 更正**:这一段此前写着"`未来计划/` 实现路线、M0/M00 计划"、
|
|
186
|
+
> "规格 v0.66"、"`src/test_*.py` 368 项测试"——**三条都已过期**:
|
|
187
|
+
> 未来计划/未来设计/战略三个目录已清空并入 `目前设计/未做/` 与 `归档/`;
|
|
188
|
+
> 测试早已迁到 `tests/cases/`,当前 **123 个文件**。
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## 从哪里读
|
|
193
|
+
|
|
194
|
+
| 你想… | 读 |
|
|
195
|
+
|---|---|
|
|
196
|
+
| 快速判断值不值得 | [`文档/语言介绍.md`](文档/语言介绍.md) |
|
|
197
|
+
| **一屏看差异(vs Rust)** | [`文档/一屏对比.md`](文档/一屏对比.md) |
|
|
198
|
+
| 看语法长什么样 | [`文档/语法清单.md`](文档/语法清单.md) |
|
|
199
|
+
| 看一个完整例子 | [`文档/样例/示例-三个构造.md`](文档/样例/示例-三个构造.md) |
|
|
200
|
+
| 参与实现 | [`CONTRIBUTING.md`](CONTRIBUTING.md) |
|
|
201
|
+
| **下一步做什么** | [`CHANGELOG.md`](CHANGELOG.md) |
|
|
202
|
+
| 看条款(给实现者) | [`文档/语法清单.md`](文档/语法清单.md) |
|
|
203
|
+
| 看哪些是原创判断 | [`文档/设计/目前设计/评估/定位与主张.md`](文档/设计/目前设计/评估/定位与主张.md) |
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## 已知缺口
|
|
208
|
+
|
|
209
|
+
| 编号 | 问题 | 严重度 |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| **G1** | 高阶函数的成本契约无法表达 | P0(卡 M2) |
|
|
212
|
+
| G9 | 成本模型缺少"内存搬运"维度 | P1 |
|
|
213
|
+
| G13–G16 | 链接模型 / 属性传递 / 标准库范围 / 门禁引导期 | P2 |
|
|
214
|
+
|
|
215
|
+
**M0 与 M1 均无阻塞。**
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 一句话
|
|
220
|
+
|
|
221
|
+
> **别的语言让你写"怎么做"。**
|
|
222
|
+
> **这门语言还让你写"要做到什么程度",然后替你核对。**
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 许可与参与
|
|
227
|
+
|
|
228
|
+
| 件 | 位置 |
|
|
229
|
+
|---|---|
|
|
230
|
+
| 代码许可 | `LICENSE`(**Apache-2.0**) |
|
|
231
|
+
| 贡献指南 | `CONTRIBUTING.md`(**四道门必须同时绿**) |
|
|
232
|
+
| 贡献者协议 | `CLA.md`(也接受 DCO:`git commit -s`) |
|
|
233
|
+
| 引用格式 | `CITATION.cff` |
|
|
234
|
+
| 企业侧保留区 | `ee/`(占位,说明"开源到什么程度") |
|
|
235
|
+
|
|
236
|
+
**一句话**:核心能力(语言 / 编译器 / 检查器 / 成本推导 / 门禁)**全部开源**,不做开源阉割。
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 命令行:**只写一个名字就够**
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
elench cost sum # 自动配成 sum.tu + sum.eln
|
|
244
|
+
elench check sum # 同上
|
|
245
|
+
elench cost sum.tu # 只给声明,自动补实现
|
|
246
|
+
elench cost sum.eln # 只给实现,顺序自动摆正
|
|
247
|
+
elench export count # 八个命令都一样接受只写名字
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
> **`<模块.tu> [<模块.eln>]` 是内部约定,不该变成输入负担。**
|
|
251
|
+
> 用户只记得住"这个程序叫 sum"。
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 自动链:`export` → `build` → `dispatch + measure`
|
|
256
|
+
|
|
257
|
+
**默认全自动**,一条命令拿到全部结论:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
elench export sum # 自己先 build,build 自动跑静态 dispatch(**不跑 measure**)
|
|
261
|
+
elench export sum --no-auto # 只导出,不跑前面那些(CI / 排查用)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
关掉的方式:`--no-auto`,或环境变量 `ELENCH_AUTO=0`。
|
|
265
|
+
|
|
266
|
+
**`measure` 不进自动链**:它要真执行候选,大范围下几十秒到分钟级。
|
|
267
|
+
分档表单独生成:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
elench measure sum # 只跑测量、生成 .dispatch.yaml
|
|
271
|
+
elench build sum --measure # 构建时顺带测
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## OTel:本机不用 Docker
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
python tools/otel_local_sink.py --out otel.ndjson # 一个终端
|
|
280
|
+
$env:OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318" # 另一个终端
|
|
281
|
+
elench export count --push
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**看板**:`python tools\otel_dashboard.py --file otel.ndjson --port 8080` → <http://127.0.0.1:8080>
|
|
285
|
+
|
|
286
|
+
## 安装(Linux / macOS 一键)
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
git clone https://github.com/xiaohuo123212/elench.git
|
|
290
|
+
cd elench
|
|
291
|
+
./install.sh # 先看要做什么: ./install.sh --dry-run
|
|
292
|
+
elench --version # 重开终端后
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
脚本做两件事之一,**不需要 sudo、不动系统 PATH**:
|
|
296
|
+
|
|
297
|
+
| 情况 | 做法 |
|
|
298
|
+
|---|---|
|
|
299
|
+
| 有 `pip` | `python3 -m pip install --user .`,装成真正的控制台命令 |
|
|
300
|
+
| 没 `pip` | 在 `~/.local/bin/elench` 放一个启动器,指向仓库里的 `src/elench.py` |
|
|
301
|
+
|
|
302
|
+
卸载:`./install.sh --uninstall`。
|
|
303
|
+
**Windows** 用 VS Code 扩展里的 `Elench: 安装命令行(加入 PATH)`。
|
package/bin/elench.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// elench 的 npm 入口:找 python,把参数原样转给它。
|
|
3
|
+
//
|
|
4
|
+
// 为什么是"薄包装"而不是重写:elench 的核心是 Python(约 3.5MB 源码、19 个子命令)。
|
|
5
|
+
// 重写成 JS 等于重做一遍,而且会立刻出现两套语义。
|
|
6
|
+
// 这里只做三件事:找解释器、传环境、原样转发退出码。
|
|
7
|
+
"use strict";
|
|
8
|
+
|
|
9
|
+
const { spawnSync } = require("child_process");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
|
|
13
|
+
const pkgRoot = path.join(__dirname, "..");
|
|
14
|
+
const srcDir = path.join(pkgRoot, "src");
|
|
15
|
+
const dshPy = path.join(srcDir, "dsh.py");
|
|
16
|
+
|
|
17
|
+
if (!fs.existsSync(dshPy)) {
|
|
18
|
+
console.error(`elench: 包内缺少 src/dsh.py(安装可能不完整):${dshPy}`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const candidates = [];
|
|
23
|
+
if (process.env.PYTHON) candidates.push(process.env.PYTHON);
|
|
24
|
+
candidates.push("python3", "python");
|
|
25
|
+
|
|
26
|
+
function probe(exe) {
|
|
27
|
+
const r = spawnSync(exe, ["-c", "import sys;sys.exit(0 if sys.version_info>=(3,10) else 9)"], {
|
|
28
|
+
stdio: "ignore",
|
|
29
|
+
});
|
|
30
|
+
return r.status === 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let py = null;
|
|
34
|
+
for (const c of candidates) {
|
|
35
|
+
try {
|
|
36
|
+
if (probe(c)) {
|
|
37
|
+
py = c;
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
} catch (_e) {
|
|
41
|
+
/* 试下一个 */
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!py) {
|
|
46
|
+
console.error(
|
|
47
|
+
"elench: 找不到可用的 Python(需要 >= 3.10)。\n" +
|
|
48
|
+
" 已尝试:" + candidates.join(", ") + "\n" +
|
|
49
|
+
" 装好 Python 后重试,或用 PYTHON=/path/to/python 指定。"
|
|
50
|
+
);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const env = Object.assign({}, process.env, {
|
|
55
|
+
PYTHONIOENCODING: "utf-8",
|
|
56
|
+
PYTHONPATH: [srcDir, process.env.PYTHONPATH].filter(Boolean).join(path.delimiter),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const r = spawnSync(py, [dshPy].concat(process.argv.slice(2)), {
|
|
60
|
+
stdio: "inherit",
|
|
61
|
+
env,
|
|
62
|
+
cwd: process.cwd(),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (r.error) {
|
|
66
|
+
console.error(`elench: 启动 Python 失败:${r.error.message}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
process.exit(r.status === null ? 1 : r.status);
|
package/package.json
CHANGED
|
@@ -1,6 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elench-lang",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Elenchus — cost contracts as machine-checkable code. CLI command: elench.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cost",
|
|
7
|
+
"complexity",
|
|
8
|
+
"contracts",
|
|
9
|
+
"static-analysis",
|
|
10
|
+
"big-o",
|
|
11
|
+
"elench"
|
|
12
|
+
],
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"bin": {
|
|
15
|
+
"elench": "bin/elench.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"bin/",
|
|
19
|
+
"src/",
|
|
20
|
+
"scripts/",
|
|
21
|
+
"README.md",
|
|
22
|
+
"NOTICE",
|
|
23
|
+
"LICENSE"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=16"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"prepack": "node scripts/clean-pycache.js",
|
|
30
|
+
"test": "node bin/elench.js --help"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/elench-lang/elench.git"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
}
|
|
39
|
+
}
|