diff --git a/ViperAIChat/App/main.vp b/ViperAIChat/App/main.vp index 170b8ab..d1a7e5b 100644 --- a/ViperAIChat/App/main.vp +++ b/ViperAIChat/App/main.vp @@ -27,7 +27,7 @@ import vthreading import requests import requests.https as rhttps import json -import w32.win32memory as win32mem +import win32.win32memory as win32mem # ============================================================ diff --git a/ViperCPW/App/main.vp b/ViperCPW/App/main.vp index 0e5fbed..36d9077 100644 --- a/ViperCPW/App/main.vp +++ b/ViperCPW/App/main.vp @@ -1,22 +1,22 @@ # ============================================================ # main.vp — ViperCPW:CreateProcessA 独立复现工程 # -# 目的:把原先塞在 TransPyV\App\main.vp 里的 [TEMP-PROBE] 探针整体搬到 -# 一个独立 Viper 工程里,脱开 TPV 单独复现 / 二分。 +# 目的:把原先塞在 ViperC\App\main.vp 里的 [TEMP-PROBE] 探针整体搬到 +# 一个独立 Viper 工程里,脱开 VPC 单独复现 / 二分。 # -# 待复现现象:自举出的 TransPyV.exe 内 CreateProcessA 恒返回 0 且 +# 待复现现象:自举出的 viperc.exe 内 CreateProcessA 恒返回 0 且 # GetLastError=87(ERROR_INVALID_PARAMETER);同参数在 Python/ctypes # 下 ok=1。 # -# TPV 侧已逐项实测 ok=0/err=87 的维度(本工程用于在"非 TPV 宿主"上复核): +# VPC 侧已逐项实测 ok=0/err=87 的维度(本工程用于在"非 VPC 宿主"上复核): # IR/机器码栈传参(逐槽核对正确)、si.cb=104 与结构体布局、命令行内容 # (逐字节回读正确、手工复制不用 strcpy 也 87)、应用名(含绝对路径)、 # lpCurrentDirectory、lpEnvironment、bInheritHandles(0/1)、 # dwCreationFlags(0/CREATE_NO_WINDOW)。 # -# 本工程要回答的问题:这是"仅 TPV.exe 特有",还是"任何 Viper 程序都如此"。 +# 本工程要回答的问题:这是"仅 VPC.exe 特有",还是"任何 Viper 程序都如此"。 # -# 五组用例(与 TPV 探针同参数、同 si 构造),每组打印 ok 与 GetLastError: +# 五组用例(与 VPC 探针同参数、同 si 构造),每组打印 ok 与 GetLastError: # #1 lpApplicationName=NULL + "llc --version",inh=1,flags=0 # #2 同 #1 但 inh=0 # #3 同 #1 但 flags=CREATE_NO_WINDOW @@ -25,19 +25,18 @@ # 对照组:打印本进程 GetCurrentDirectoryA 的结果(证明本进程能正常调 Win32)。 # # 判定: -# 五组全 ok=0/err=87 ⇒ 与 TransPyV.exe 同因,问题在 Viper 生成代码/运行期, -# 与 TPV 自身逻辑无关(任何 Viper 程序都如此)。 -# 任一组 ok=1 ⇒ 该维度即是 TPV 特有问题,按组二分定位。 +# 五组全 ok=0/err=87 ⇒ 与 viperc.exe 同因,问题在 Viper 生成代码/运行期, +# 与 VPC 自身逻辑无关(任何 Viper 程序都如此)。 +# 任一组 ok=1 ⇒ 该维度即是 VPC 特有问题,按组二分定位。 # ============================================================ -import t, c from stdint import * import stdio import stdlib import string -import w32.win32base -import w32.win32file -import w32.win32process -import w32.win32console +import win32.win32base +import win32.win32file +import win32.win32process +import win32.win32console # 控制台代码页:UTF-8 @@ -47,7 +46,7 @@ define PAGE_CODE = 65001 # ============================================================ # 单组复现:构造 si/pi → 调 CreateProcessA → 打印 ok / GetLastError / si 字段 -# si 构造与 TPV 的 _run_cmd_wait 逐字一致: +# si 构造与 VPC 的 _run_cmd_wait 逐字一致: # T() 构造 → string.memset 显式清零 → si.cb = STARTUPINFOA.__sizeof__() # ============================================================ def ProbeCreateProcessA(Tag: str, AppName: str, CommandLine: str, @@ -59,7 +58,7 @@ def ProbeCreateProcessA(Tag: str, AppName: str, CommandLine: str, CommandLine : lpCommandLine InheritHandles : 第 5 实参 bInheritHandles CreationFlags : 第 6 实参 dwCreationFlags - lpEnvironment / lpCurrentDirectory 恒传 NULL(TPV 侧已实测与 87 无关)。 + lpEnvironment / lpCurrentDirectory 恒传 NULL(VPC 侧已实测与 87 无关)。 """ # 命令行必须放进可写堆缓冲:CreateProcessA 会原地改写 lpCommandLine, # 不能传只读字面量。 @@ -76,16 +75,16 @@ def ProbeCreateProcessA(Tag: str, AppName: str, CommandLine: str, string.strcpy(CmdBuffer, CommandLine) # si/pi:T() 构造只 alloca 不 memset,必须显式清零 - # 先例:TransPyV/App/lib/Phase/BuildPipeline.vp:530-532 - # (string.memset(t.CPtr(c.Addr(si)), 0, STARTUPINFOA.__sizeof__())) + # 先例:ViperC/App/lib/Phase/BuildPipeline.vp:530-532 + # (string.memset(rawptr(c.Addr(si)), 0, STARTUPINFOA.__sizeof__())) # 类型引用写法:includes/subprocess.vp:99-100 - # c.Addr() 取址:includes/condition.vp:26;t.CPtr(c.Addr(x)):includes/subprocess.vp:121 - StartupInfo: w32.win32process.STARTUPINFOA = w32.win32process.STARTUPINFOA() - ProcessInfo: w32.win32process.PROCESS_INFORMATION = w32.win32process.PROCESS_INFORMATION() - string.memset(t.CPtr(&StartupInfo), 0, w32.win32process.STARTUPINFOA.__sizeof__()) - string.memset(t.CPtr(&ProcessInfo), 0, w32.win32process.PROCESS_INFORMATION.__sizeof__()) + # c.Addr() 取址:includes/condition.vp:26;rawptr(c.Addr(x)):includes/subprocess.vp:121 + StartupInfo: win32.win32process.STARTUPINFOA = win32.win32process.STARTUPINFOA() + ProcessInfo: win32.win32process.PROCESS_INFORMATION = win32.win32process.PROCESS_INFORMATION() + string.memset(rawptr(&StartupInfo), 0, win32.win32process.STARTUPINFOA.__sizeof__()) + string.memset(rawptr(&ProcessInfo), 0, win32.win32process.PROCESS_INFORMATION.__sizeof__()) # si.cb = 结构体大小:includes/subprocess.vp:100 - StartupInfo.cb = w32.win32process.STARTUPINFOA.__sizeof__() + StartupInfo.cb = win32.win32process.STARTUPINFOA.__sizeof__() # 应用名描述:None 显式打印成 NULL(不臆造内容,也不兜底成别的路径) AppDesc: str = "NULL" @@ -93,24 +92,24 @@ def ProbeCreateProcessA(Tag: str, AppName: str, CommandLine: str, AppDesc = AppName # GetLastError 基线:调用前读取,用于判定 err 是否为残留值 - # GetLastError 声明:includes/w32/win32base.vp:62 + # GetLastError 声明:includes/win32/win32base.vp:62 # 调用后紧跟读取的先例:ViperApps/ViperZipfileProject/App/main.vp:116 - PreError: uint32 = w32.win32base.GetLastError() + PreError: uint32 = win32.win32base.GetLastError() # 单条调用:10 实参,lpEnvironment / lpCurrentDirectory 恒 NULL - # 先例:includes/subprocess.vp:112-123(t.CPtr(0) 表 NULL 见 :113/:115/:119/:120) - OkValue: int = w32.win32process.CreateProcessA( - AppName, CmdBuffer, t.CPtr(0), t.CPtr(0), InheritHandles, CreationFlags, - t.CPtr(0), t.CPtr(0), t.CPtr(&StartupInfo), t.CPtr(&ProcessInfo)) + # 先例:includes/subprocess.vp:112-123(None 表 NULL 见 :113/:115/:119/:120) + OkValue: int = win32.win32process.CreateProcessA( + AppName, CmdBuffer, None, None, InheritHandles, CreationFlags, + None, None, rawptr(&StartupInfo), rawptr(&ProcessInfo)) # GetLastError 必须紧跟调用读取(printf 等都会覆盖它) - ErrorValue: uint32 = w32.win32base.GetLastError() + ErrorValue: uint32 = win32.win32base.GetLastError() # --- 字段转储:整数字段与指针字段统一 uint64() 后按 %llu 打印 --- - # uint64(结构体字段) 先例:TransPyV/App/lib/Stub/StubMerger/StubMergerStore.vp:79 + # uint64(结构体字段) 先例:ViperC/App/lib/Stub/StubMerger/StubMergerStore.vp:79 # (uint64(scan_result.Entries)) # uint64(c.Addr(x)) 先例:ViperApps/ViperOS/VKernel/Kernel/sched/sched.vp:217 # (entry_addr: uint64 = uint64(c.Addr(_thread_entry))) - # uint64(malloc 缓冲) 先例:TransPyV/App/lib/Stub/StubMerger/StubMergerBuild.vp:1313 段 + # uint64(malloc 缓冲) 先例:ViperC/App/lib/Stub/StubMerger/StubMergerBuild.vp:1313 段 # (uint64(ext_ptr)) # %llu 先例:includes/memhub.vp:792 CbValue: uint64 = uint64(StartupInfo.cb) @@ -129,7 +128,7 @@ def ProbeCreateProcessA(Tag: str, AppName: str, CommandLine: str, Tag, OkValue, uint64(ErrorValue), uint64(PreError), AppDesc, CommandLine, CmdAddress) # si 关键字段:cb / dwFlags / cbReserved2 / lpReserved2 / 三个 hStd* + si/pi 地址 - # 字段定义:includes/w32/win32process.vp:42-60(STARTUPINFOA) + # 字段定义:includes/win32/win32process.vp:42-60(STARTUPINFOA) stdio.printf("[CPW] %s si.cb=%llu si.dwFlags=%llu si.cbReserved2=%llu si.lpReserved2=%llu si.hStdIn=%llu si.hStdOut=%llu si.hStdErr=%llu si.addr=%llu pi.addr=%llu\n", Tag, CbValue, FlagsValue, CbReserved2Value, Reserved2Value, StdInputValue, StdOutputValue, StdErrorValue, SiAddress, PiAddress) @@ -137,8 +136,8 @@ def ProbeCreateProcessA(Tag: str, AppName: str, CommandLine: str, # 成功时关闭子进程句柄(避免句柄泄漏) # 先例:includes/subprocess.vp:179-180 if OkValue != 0: - w32.win32base.CloseHandle(ProcessInfo.hThread) - w32.win32base.CloseHandle(ProcessInfo.hProcess) + win32.win32base.CloseHandle(ProcessInfo.hThread) + win32.win32base.CloseHandle(ProcessInfo.hProcess) stdlib.free(CmdBuffer) # stdout 全缓冲,逐组刷新以保证崩溃前输出可见 # 先例:ViperApps/ViperZipfileProject/App/main.vp:33(stdio.fflush(None)) @@ -152,22 +151,22 @@ def ProbeCreateProcessA(Tag: str, AppName: str, CommandLine: str, def PrintCurrentDirectory() -> int: """[CPW] 对照组:打印本进程当前目录与错误码""" # 缓冲与调用形态先例:includes/os/_win32.vp:76-91(getcwd:malloc → 调用 → - # buf[length] = 0 → str(buf));MAX_PATH 声明:includes/w32/win32base.vp:18 + # buf[length] = 0 → str(buf));MAX_PATH 声明:includes/win32/win32base.vp:18 CwdLength: ULONG = 0 CwdError: uint32 = 0 CwdDesc: str = "" - CwdBuffer: bytes = stdlib.malloc(w32.win32base.MAX_PATH + 1) + CwdBuffer: bytes = stdlib.malloc(win32.win32base.MAX_PATH + 1) if CwdBuffer is None: stdio.printf("[CPW] control GetCurrentDirectoryA MALLOC-FAILED\n") return 1 - # GetCurrentDirectoryA 声明:includes/w32/win32file.vp:129 - CwdLength = w32.win32file.GetCurrentDirectoryA(w32.win32base.MAX_PATH + 1, CwdBuffer) - CwdError = w32.win32base.GetLastError() # 必须紧跟调用读取 + # GetCurrentDirectoryA 声明:includes/win32/win32file.vp:129 + CwdLength = win32.win32file.GetCurrentDirectoryA(win32.win32base.MAX_PATH + 1, CwdBuffer) + CwdError = win32.win32base.GetLastError() # 必须紧跟调用读取 if CwdLength > 0: - if CwdLength < w32.win32base.MAX_PATH + 1: + if CwdLength < win32.win32base.MAX_PATH + 1: CwdBuffer[CwdLength] = 0 else: - CwdBuffer[w32.win32base.MAX_PATH] = 0 # 缓冲区不足:截断显示 + CwdBuffer[win32.win32base.MAX_PATH] = 0 # 缓冲区不足:截断显示 CwdDesc = str(CwdBuffer) stdio.printf("[CPW] control GetCurrentDirectoryA len=%llu err=%llu cwd=%s\n", uint64(CwdLength), uint64(CwdError), CwdDesc) @@ -176,20 +175,15 @@ def PrintCurrentDirectory() -> int: return 0 -# ============================================================ -# main: 入口 -# @t.CExport + main() -> int 先例:ViperApps/ViperZipfileProject/App/main.vp:305-306 -# ============================================================ -@t.CExport -def main() -> int: +export def main() -> int: # 控制台 UTF-8(中文注释/标签不乱码) - # 声明:includes/w32/win32console.vp:81-82 + # 声明:includes/win32/win32console.vp:81-82 # 先例:ViperApps/ViperQtHelloWorld/App/main.vp:18+34-35 - w32.win32console.SetConsoleOutputCP(PAGE_CODE) - w32.win32console.SetConsoleCP(PAGE_CODE) + win32.win32console.SetConsoleOutputCP(PAGE_CODE) + win32.win32console.SetConsoleCP(PAGE_CODE) # stdio.printf 声明:includes/stdio.vp:4 - stdio.printf("ViperCPW: CreateProcessA standalone repro (Viper host, not TransPyV.exe)\n") + stdio.printf("ViperCPW: CreateProcessA standalone repro (Viper host, not viperc.exe)\n") PrintCurrentDirectory() # #1 基线:NULL 应用名 + inh=1 + flags=0 @@ -197,14 +191,14 @@ def main() -> int: # #2 同 #1 但 bInheritHandles=0 ProbeCreateProcessA("#2 NULL-app inh=0 flags=0", None, "llc --version", 0, 0) # #3 同 #1 但 dwCreationFlags=CREATE_NO_WINDOW - # CREATE_NO_WINDOW 定义:includes/w32/win32process.vp:23 + # CREATE_NO_WINDOW 定义:includes/win32/win32process.vp:23 ProbeCreateProcessA("#3 NULL-app inh=1 flags=CREATE_NO_WINDOW", None, "llc --version", - 1, w32.win32process.CREATE_NO_WINDOW) + 1, win32.win32process.CREATE_NO_WINDOW) # #4 绝对路径应用名 ProbeCreateProcessA("#4 abs-app", "D:\\msys64\\clang64\\bin\\llc.exe", "llc --version", 1, 0) - # #5 报错里那条原样命令行(正斜杠相对路径,与 TPV 探针 #3 逐字相同) + # #5 报错里那条原样命令行(正斜杠相对路径,与 VPC 探针 #3 逐字相同) ProbeCreateProcessA("#5 raw-cmdline(fwd slashes)", None, - "llc -filetype=obj -relocation-model=pic -o ./TransPyV/.tpv_build/output/xx/xxx.obj ./TransPyV/.tpv_build/temp/xx/xxx.ll", + "llc -filetype=obj -relocation-model=pic -o ./ViperC/__vpcbuild__/output/xx/xxx.obj ./ViperC/__vpcbuild__/temp/xx/xxx.ll", 1, 0) stdio.printf("ViperCPW: DONE\n") diff --git a/ViperFLProject/.gitignore b/ViperFLProject/.gitignore deleted file mode 100644 index 44fcca7..0000000 --- a/ViperFLProject/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*.o -*.obj -*.exe -*.img -*.iso -**/__pycache__/ -.cache/ -*.pyc - -# 编译 -**/output/ -**/temp/ -**/__vpcbuild__/ \ No newline at end of file diff --git a/ViperFLProject/App/main2.vp b/ViperFLProject/App/main2.vp deleted file mode 100644 index 0ebfba2..0000000 --- a/ViperFLProject/App/main2.vp +++ /dev/null @@ -1,158 +0,0 @@ -# main2.vp — ViperFLProject fltk GUI 测试(回调 + 控件展示) -# -# 构建需 VPC/TPC 支持 project.vpj linker.static_libs 静态链接 -# (本工程已配置链接 ../includes/fltk/cfltk/build 下的 cfltk2 + FLTK 静态库)。 -# -# 回调说明:Viper 模块级函数可直接作为 Fl_Callback 传入(VPC 自动把函数名 -# bitcast 为函数指针)。回调签名统一为 def cb(w: bytes, data: bytes), -# 其中 w 是触发回调的控件指针,data 是注册时传入的用户数据。 -import t, c -import stdlib -import viperlib -import fltk - - -# 模块级全局:供回调访问 main() 中创建的控件指针(回调是 C 层直接调用, -# 拿不到 main 的局部变量);空指针用 None(C null),不能用整数 0。 -term_ptr: t.CPtr = None -status_ptr: t.CPtr = None -scheme_idx: int = 0 -theme_idx: int = 0 - - -def on_btn_click(w: bytes, data: bytes): - """按钮点击回调:改按钮文字 + 状态栏显示""" - fltk.Fl_Widget_set_label(w, "Clicked!") - fltk.Fl_Widget_redraw(w) - fltk.Fl_Output_set_value(status_ptr, "Button clicked") - - -def on_check(w: bytes, data: bytes): - """复选框回调:状态栏显示勾选状态""" - v: int = fltk.Fl_Check_Button_is_checked(w) - if v != 0: - fltk.Fl_Output_set_value(status_ptr, "Checked") - else: - fltk.Fl_Output_set_value(status_ptr, "Unchecked") - - -def on_slider(w: bytes, data: bytes): - """滑动条回调:状态栏实时显示数值""" - v: double = fltk.Fl_Slider_value(w) - buf: bytes = stdlib.malloc(32) - if buf is not None: - viperlib.snprintf(buf, 32, "Slider = %.2f", v) - fltk.Fl_Output_set_value(status_ptr, buf) - stdlib.free(buf) - - -def on_go(w: bytes, data: bytes): - """按钮回调:读取输入框文本 → 终端打印""" - txt: str = fltk.Fl_Input_value(data) - fltk.Fl_Terminal_append(term_ptr, "input: ") - fltk.Fl_Terminal_append(term_ptr, txt) - fltk.Fl_Terminal_append(term_ptr, "\n") - - -def on_menu_open(w: bytes, data: bytes): - fltk.Fl_Output_set_value(status_ptr, "Menu: File/Open") - - -def on_menu_about(w: bytes, data: bytes): - fltk.Fl_Output_set_value(status_ptr, "Menu: Help/About") - - -def on_style(w: bytes, data: bytes): - """风格切换回调:base→plastic→gtk+→gleam→oxy 循环""" - global scheme_idx - scheme_idx = scheme_idx + 1 - if scheme_idx == 1: - fltk.Fl.set_scheme("plastic") - elif scheme_idx == 2: - fltk.Fl.set_scheme("gtk+") - elif scheme_idx == 3: - fltk.Fl.set_scheme("gleam") - elif scheme_idx == 4: - fltk.Fl.set_scheme("oxy") - else: - fltk.Fl.set_scheme("base") - scheme_idx = 0 - fltk.Fl_Output_set_value(status_ptr, f"Scheme: {fltk.Fl.scheme_string()}") - - -def on_theme(w: bytes, data: bytes): - """Fl_Theme 主题切换:base→Dark→Metro 循环""" - global theme_idx - theme_idx = theme_idx + 1 - if theme_idx == 1: - fltk.Fl.set_theme_dark() - elif theme_idx == 2: - fltk.Fl.set_theme_metro() - else: - fltk.Fl.set_scheme("base") - fltk.Fl.reload_scheme() - theme_idx = 0 - fltk.Fl_Output_set_value(status_ptr, f"Theme: {theme_idx}") - - -def on_tick(w: bytes, data: bytes): - """定时器回调:每秒终端打印一次并续订""" - fltk.Fl_Terminal_append(term_ptr, "tick\n") - fltk.Fl.add_timeout(1.0, on_tick, 0) - - -def main() -> int: - global term_ptr, status_ptr - fltk.Fl_init_all() - - win = fltk.Fl_Window(600, 460, "Viper FLTK Demo") - menubar = fltk.Fl_Menu_Bar(0, 0, 600, 25) - status = fltk.Fl_Output(10, 30, 580, 25) - btn = fltk.Fl_Button(10, 70, 120, 30, "Click Me") - check = fltk.Fl_Check_Button(150, 70, 100, 30, "Enable") - slider = fltk.Fl_Slider(280, 70, 200, 30) - input_ = fltk.Fl_Input(10, 110, 210, 30, "Type here") - go = fltk.Fl_Button(230, 110, 55, 30, "Go") - style = fltk.Fl_Button(295, 110, 55, 30, "Style") - theme = fltk.Fl_Button(360, 110, 55, 30, "Theme") - spinner = fltk.Fl_Spinner(425, 110, 100, 30) - browser = fltk.Fl_Browser(10, 150, 280, 140) - tree = fltk.Fl_Tree(300, 150, 280, 140) - term = fltk.Fl_Terminal(10, 300, 570, 120, "Terminal") - win.end() - - # 保存全局指针(回调用) - term_ptr = t.CPtr(term._ptr) - status_ptr = t.CPtr(status._ptr) - - # 菜单(回调 + 快捷键 Ctrl+O:0x4000 | 'o'(111)) - menubar.add("File/Open", 0x4000 | 111, 0, on_menu_open) - menubar.add("Help/About", 0, 0, on_menu_about) - - # 回调注册 - btn.set_callback(on_btn_click, 0) - check.set_callback(on_check, 0) - slider.set_callback(on_slider, 0) - go.set_callback(on_go, input_._ptr) - style.set_callback(on_style, 0) - theme.set_callback(on_theme, 0) - - # 数值微调框 - spinner.set_minimum(0.0) - spinner.set_maximum(100.0) - spinner.set_step(1.0) - spinner.set_value(42.0) - - # 列表 + 树 - browser.add("Item 1") - browser.add("Item 2") - browser.add("Item 3") - tree.add("Root/Child A/Leaf 1") - tree.add("Root/Child B") - - # 定时器 - fltk.Fl.add_timeout(1.0, on_tick, 0) - - win.show() - fltk.Fl.run() - return 0 diff --git a/ViperFLProject/LICENSE b/ViperFLProject/LICENSE deleted file mode 100644 index cee2f62..0000000 --- a/ViperFLProject/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 TermiNexus - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/ViperFLProject/README.md b/ViperFLProject/README.md deleted file mode 100644 index e1fe40f..0000000 --- a/ViperFLProject/README.md +++ /dev/null @@ -1,289 +0,0 @@ -# Viper Template Project - -[English](#english) | [中文](#中文) - -A minimal, ready-to-use template for bootstrapping a new [Viper](../wiki/01-overview.md) language project on **Windows (x86_64-pc-windows-gnu)**. - -Windows 平台(x86_64-pc-windows-gnu)下 [Viper](../wiki/01-overview.md) 语言新项目的最小可用模板。 - ---- - - - -## 中文 - -### 这是什么 - -`ViperTemplateProject` 是基于 `Viper` 语言的 **Windows 桌面应用模板**。克隆本仓库后,你可以立即得到一个能够: - -- 设置 Windows 控制台为 UTF-8 编码(避免中文乱码) -- 打印一行 `你好,世界` -- 通过 `llc + clang++`(mingw 工具链)编译为原生 `app.exe` - -的最小 Viper 项目。 - -模板对应的语言编译器是 [TransPyC](https://git.gvsds.com/GVSDS/TransPyC);关于 Viper 语言本身的概览,参见 [TransPyC 仓库 wiki](../wiki/01-overview.md)。 - -### 目录结构 - -``` -ViperTemplateProject/ -├── .gitignore # 忽略 build/、*.o、*.exe、缓存等 -├── README.md # 本文件 -├── project.vpj # 项目配置(编译器、链接器、目标三元组等) -└── App/ - └── main.py # 入口文件 -``` - -### 前提条件 - -| 工具 | 说明 | -|------|------| -| `python` ≥ 3.10 | 用于运行 TransPyC 编译器 | -| `llc` | LLVM 静态编译器,编译 `.ll` → `.o` | -| `clang++` | mingw 工具链下的链接驱动(`x86_64-w64-mingw32`) | -| `TransPyC` 仓库 | 本编译器,克隆在 `ViperTemplateProject/..` 同一目录下 | - -环境变量建议(PowerShell): - -```powershell -$env:PATH = "D:\msys64\mingw64\bin;D:\LLVM\bin;$env:PATH" -``` - -### 快速开始 - -```powershell -# 1. 确保目录布局正确 -# D:\Users\TermiNexus\Desktop\TransPyC\ -# ├── TransPyC\ # 编译器仓库 -# └── ViperTemplateProject\ # 本仓库 - -cd D:\Users\TermiNexus\Desktop\TransPyC\ViperTemplateProject - -# 2. 编译并运行 -python ..\TransPyC\Projectrans.py ` - --project .\project.vpj ` - --clean-cache=false - -# 3. 产物位于 output\app.exe -.\output\app.exe -``` - -预期输出: - -``` -你好,世界 -``` - -### 编写你的第一个程序 - -打开 `App/main.py`,替换 `print("你好,世界")` 为任意合法 Viper 表达式。例如: - -```python -import w32.win32console as w32cmd -import t, c - -pagecode: t.CDefine = 65001 - -@t.CExport -def main() -> int: - w32cmd.SetConsoleOutputCP(pagecode) - w32cmd.SetConsoleCP(pagecode) - - # 你的代码从这里开始 - a: t.CInt = 1 - b: t.CInt = 2 - print("a + b =", a + b) - - return 0 -``` - -### 修改项目配置 - -打开 `project.vpj`,按需调整: - -| 字段 | 含义 | 模板默认值 | -|------|------|-----------| -| `name` | 项目名(仅显示用) | `Standard Template Project` | -| `source_dir` | 源文件根目录 | `./App` | -| `temp_dir` | 中间产物目录(`.pyi` / `.stub.ll`) | `./temp` | -| `output_dir` | 最终产物目录 | `./output` | -| `compiler.cmd` | 汇编器 | `llc` | -| `compiler.flags` | 传给 `llc` 的参数 | `["-filetype=obj", "-relocation-model=pic"]` | -| `linker.cmd` | 链接器 | `clang++` | -| `linker.flags` | 链接器参数 | mingw 标准库 + `kernel32` | -| `linker.output` | 产物名 | `app.exe` | -| `includes` | 标准库搜索路径 | `["../includes"]` | -| `target.triple` | LLVM 目标三元组 | `x86_64-pc-windows-gnu` | -| `target.datalayout` | LLVM 数据布局 | mingw 默认 | -| `options.target` | 后端目标 | `llvm` | -| `options.strict_mode` | 严格类型检查 | `true` | -| `options.slice_level` | 切片级别 | `3` | - -### 跨平台使用 - -本模板默认针对 **Windows + mingw**。若需在其他平台使用,修改 `project.vpj` 的 `compiler.cmd` / `linker.cmd` / `target.triple`: - -- **Linux (x86_64)**:`triple = "x86_64-unknown-linux-gnu"`,`linker.cmd = "clang++"` -- **macOS (x86_64)**:`triple = "x86_64-apple-darwin*"`,`linker.cmd = "clang++"` -- **裸机 x86_64 (ViperOS)**:`triple = "x86_64-none-elf"`,`linker.cmd = "ld.lld"`,需要 `isr.s` 启动文件 - -### 常见问题 - -**Q: 报错 `cannot find includes/os` / `cannot find includes/atom` 之类?** -A: 检查 `project.vpj` 中的 `includes` 字段是否指向 `TransPyC/includes`。`../includes` 假设本仓库与 `TransPyC` 仓库同级。 - -**Q: 输出 `app.exe` 双击闪退?** -A: 在终端中运行 `.\output\app.exe` 而非双击,并确认 mingw 与 LLVM 在 `PATH` 中。 - -**Q: 想完全清理构建产物?** -A: 使用 `python ..\TransPyC\Projectrans.py --project .\project.vpj --clean-cache` 清理缓存;删除 `output/` 和 `temp/` 即可彻底重置。 - -**Q: `StandardTemplateProject` 和本仓库是什么关系?** -A: 本仓库 `ViperTemplateProject` 是 `StandardTemplateProject` 的独立仓库版本。如果你仍想保留 `StandardTemplateProject` 放在 `TransPyC` 仓库内,只需把它加入 `TransPyC/.gitignore` 的 `# 排除独立仓库的目录` 小节。 - -### 进一步阅读 - -- [Viper 语言概览](../wiki/01-overview.md) -- [类型系统](../wiki/02-type-system.md) -- [OOP 与对象模型](../wiki/06-oop.md) -- [自举路线图](../wiki/13-bootstrapping.md) - ---- - - - -## English - -### What is this - -`ViperTemplateProject` is a **Windows desktop application template** based on the [Viper](../wiki/01-overview.md) language. After cloning, you immediately have a minimal Viper project that: - -- Sets the Windows console to UTF-8 (avoids mojibake for non-ASCII output) -- Prints `你好,世界` -- Compiles to a native `app.exe` via `llc + clang++` (mingw toolchain) - -The corresponding compiler is [TransPyC](https://git.gvsds.com/GVSDS/TransPyC). For a Viper language overview, see the [TransPyC wiki](../wiki/01-overview.md). - -### Directory layout - -``` -ViperTemplateProject/ -├── .gitignore # ignores build/, *.o, *.exe, caches, etc. -├── README.md # this file -├── project.vpj # project config (compiler, linker, target triple, ...) -└── App/ - └── main.py # entry point -``` - -### Prerequisites - -| Tool | Notes | -|------|-------| -| `python` ≥ 3.10 | runs the TransPyC compiler | -| `llc` | LLVM static compiler, `.ll` → `.o` | -| `clang++` | mingw toolchain driver (`x86_64-w64-mingw32`) | -| `TransPyC` repo | the compiler, cloned as a sibling of `ViperTemplateProject` | - -Suggested `PATH` (PowerShell): - -```powershell -$env:PATH = "D:\msys64\mingw64\bin;D:\LLVM\bin;$env:PATH" -``` - -### Quick start - -```powershell -# 1. Make sure the layout is right -# D:\Users\TermiNexus\Desktop\TransPyC\ -# ├── TransPyC\ # compiler repo -# └── ViperTemplateProject\ # this repo - -cd D:\Users\TermiNexus\Desktop\TransPyC\ViperTemplateProject - -# 2. Build and run -python ..\TransPyC\Projectrans.py ` - --project .\project.vpj ` - --clean-cache=false - -# 3. Output is at output\app.exe -.\output\app.exe -``` - -Expected output: - -``` -你好,世界 -``` - -### Writing your first program - -Open `App/main.py` and replace `print("你好,世界")` with any valid Viper expression. Example: - -```python -import w32.win32console as w32cmd -import t, c - -pagecode: t.CDefine = 65001 - -@t.CExport -def main() -> int: - w32cmd.SetConsoleOutputCP(pagecode) - w32cmd.SetConsoleCP(pagecode) - - # your code goes here - a: t.CInt = 1 - b: t.CInt = 2 - print("a + b =", a + b) - - return 0 -``` - -### Editing project.vpj - -| Field | Meaning | Template default | -|-------|---------|------------------| -| `name` | display name | `Standard Template Project` | -| `source_dir` | source root | `./App` | -| `temp_dir` | intermediate artifacts (`.pyi` / `.stub.ll`) | `./temp` | -| `output_dir` | final artifacts | `./output` | -| `compiler.cmd` | assembler | `llc` | -| `compiler.flags` | flags passed to `llc` | `["-filetype=obj", "-relocation-model=pic"]` | -| `linker.cmd` | linker | `clang++` | -| `linker.flags` | linker flags | mingw stdlib + `kernel32` | -| `linker.output` | output name | `app.exe` | -| `includes` | standard library search paths | `["../includes"]` | -| `target.triple` | LLVM target triple | `x86_64-pc-windows-gnu` | -| `target.datalayout` | LLVM data layout | mingw default | -| `options.target` | backend target | `llvm` | -| `options.strict_mode` | strict type checking | `true` | -| `options.slice_level` | slice level | `3` | - -### Cross-platform use - -This template targets **Windows + mingw** by default. To use on another platform, adjust `compiler.cmd` / `linker.cmd` / `target.triple` in `project.vpj`: - -- **Linux (x86_64)**: `triple = "x86_64-unknown-linux-gnu"`, `linker.cmd = "clang++"` -- **macOS (x86_64)**: `triple = "x86_64-apple-darwin*"`, `linker.cmd = "clang++"` -- **Bare-metal x86_64 (ViperOS)**: `triple = "x86_64-none-elf"`, `linker.cmd = "ld.lld"`, requires `isr.s` startup - -### FAQ - -**Q: Error like `cannot find includes/os` or `cannot find includes/atom`?** -A: Check that the `includes` field in `project.vpj` points to the `TransPyC/includes` directory. `../includes` assumes this repo lives next to `TransPyC`. - -**Q: `app.exe` flashes and closes on double-click?** -A: Run `.\output\app.exe` from a terminal, not by double-clicking. Make sure mingw and LLVM are on `PATH`. - -**Q: How to fully clean build artifacts?** -A: `python ..\TransPyC\Projectrans.py --project .\project.vpj --clean-cache` clears the cache. To reset everything, also delete `output/` and `temp/`. - -**Q: What is the relationship with `StandardTemplateProject`?** -A: This repo `ViperTemplateProject` is the standalone-repo version of `StandardTemplateProject`. If you still want `StandardTemplateProject` to live inside the `TransPyC` repo, add it to the `# 排除独立仓库的目录` section in `TransPyC/.gitignore`. - -### Further reading - -- [Viper language overview](../wiki/01-overview.md) -- [Type system](../wiki/02-type-system.md) -- [OOP and object model](../wiki/06-oop.md) -- [Bootstrapping roadmap](../wiki/13-bootstrapping.md) diff --git a/ViperFLProject/project.vpj b/ViperFLProject/project.vpj deleted file mode 100644 index 78ae5a5..0000000 --- a/ViperFLProject/project.vpj +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "ViperFLProject - FLTK GUI Test", - "version": "1.0.0", - "source_dir": "./App", - "build_dir": "./__vpcbuild__", - "compiler": { - "cmd": "llc", - "flags": [ - "-filetype=obj", - "-relocation-model=pic" - ] - }, - "linker": { - "cmd": "clang++.exe", - "flags": [ - "-fuse-ld=lld", - "-lmsvcrt", - "-lucrt", - "-lpthread", - "-lmingwex", - "-lkernel32", - "-lcomdlg32", - "-lcomctl32", - "-lole32", - "-luuid", - "-lwinmm", - "-lgdi32", - "-lgdiplus", - "-ladvapi32", - "-lshell32", - "-lws2_32", - "-luser32", - "-lwinspool" - ], - "static_libs": [ - "../../includes/fltk/cfltk/build/libcfltk2.a", - "../../includes/fltk/cfltk/build/libfltk_theme.a", - "../../includes/fltk/cfltk/build/fltk/lib/libfltk_images.a", - "../../includes/fltk/cfltk/build/fltk/lib/libfltk.a", - "../../includes/fltk/cfltk/build/fltk/lib/libfltk_png.a", - "../../includes/fltk/cfltk/build/fltk/lib/libfltk_jpeg.a", - "../../includes/fltk/cfltk/build/fltk/lib/libfltk_z.a" - ], - "output": "app.exe" - }, - "includes": [ - "../../includes" - ], - "target": { - "triple": "x86_64-pc-windows-gnu", - "datalayout": "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" - }, - "options": { - "slice_level": 3, - "target": "llvm", - "strict_mode": true - } -} diff --git a/ViperMNIST/App/lib/AppGui.vp b/ViperMNIST/App/lib/AppGui.vp index acf66c2..ac37059 100644 --- a/ViperMNIST/App/lib/AppGui.vp +++ b/ViperMNIST/App/lib/AppGui.vp @@ -14,7 +14,6 @@ # 线程模型: 训练在 vthreading 后台线程跑, 只写 MnistNet 的 prog_* 进度总线; # 主线程用 QTimer 轮询刷新界面, 不与之共享 Qt 对象。 # ============================================================ -import t, c from stdint import * import stdlib import string @@ -23,8 +22,8 @@ import vthreading import memhub import torch import viperlib -import w32.fileio as fileio -import w32.win32file as win32file +import win32.fileio as fileio +import win32.win32file as win32file import lib.MnistData as MnistData import lib.MnistNet as MnistNet @@ -39,8 +38,7 @@ define CHART_KEEP = 800 define ANIM_SPAN = 16 -@t.NoVTable -class AppGui: +novirtual class AppGui: # ---- 应用与主窗 ---- App: vqt6.QApplication* Win: vqt6.QMainWindow* @@ -78,12 +76,12 @@ class AppGui: Pbar: vqt6.QProgressBar* Log: vqt6.QPlainTextEdit* Chart: vqt6.ChartView* - LineLoss: t.CPtr - LineAcc: t.CPtr + LineLoss: rawptr + LineAcc: rawptr ChartSynced: int # 验证集曲线(每 epoch 一个点, 与训练曲线分开同步) - LineValLoss: t.CPtr - LineValAcc: t.CPtr + LineValLoss: rawptr + LineValAcc: rawptr ChartSyncedVal: int # ---- 推理页 ---- @@ -122,7 +120,7 @@ class AppGui: # 只存线程句柄: Thread 对象本身是创建帧的栈 alloca, 跨帧持有会悬垂; # 句柄由 on_start_train 在 Thread 尚存活时取出, 之后用模块级 # wait_handle/close_handle 操作。 - ThreadH: t.CPtr + ThreadH: rawptr XBuf: double* YBuf: int* NTrain: sizet @@ -138,8 +136,8 @@ class AppGui: Img28: bytes Sample28: bytes HaveSample: int - TestRaw: t.CPtr - TestLbl: t.CPtr + TestRaw: rawptr + TestLbl: rawptr TestN: sizet Probs: double* HiddenBuf: double* @@ -337,9 +335,9 @@ class AppGui: self.LblStatus = self.make_label("池: 512MB 数据目录: data", "color:#8a93a1;") # statusBar() 返回裸指针: 返回包装类对象(按值 struct)的方法在跨模块 # 调用时返回类型无法精确解析(编译器 fail-fast), 故此处直连 FFI。 - # 注解写 t.CPtr 而非 vqt6.QtStatusBarPtr —— 跨模块 typedef 注解 + # 注解写 rawptr 而非 vqt6.QtStatusBarPtr —— 跨模块 typedef 注解 # 不在解析白名单内, 会走"类型注解解析失败"诊断路径。 - sb: t.CPtr = self.Win.statusBar() + sb: rawptr = self.Win.statusBar() vqt6.vqt6_qstatusbar_add_widget(sb, self.LblStatus._ptr, 0) self.TimerPoll = vqt6.QTimer() @@ -561,8 +559,8 @@ class AppGui: buf: bytes = stdlib.malloc(1024) if buf is None: return "." - # hModule 传空指针用 t.CPtr(0): HANDLE 是 VOIDPTR, 整数 0 不能隐式转指针 - win32file.GetModuleFileNameA(t.CPtr(0), buf, ULONG(1024)) + # hModule 传空指针用 None: HANDLE 是 VOIDPTR, 整数 0 不能隐式转指针 + win32file.GetModuleFileNameA(None, buf, ULONG(1024)) n: sizet = string.strlen(buf) # 第一步: 从右往左找最后一个路径分隔符, 在那里截断(去掉文件名本身) cut: sizet = 0 @@ -862,7 +860,7 @@ class AppGui: self.BtnTrain.setEnabled(0) self.BtnStop.setEnabled(1) self.Training = 1 - th: vthreading.Thread* = vthreading.Thread(WorkerTrain, t.CPtr(0)) + th: vthreading.Thread* = vthreading.Thread(WorkerTrain, None) th.start() self.ThreadH = th.handle # 帧内取出句柄, 之后不再持 Thread 对象 self.TimerPoll.start(120) @@ -1024,7 +1022,7 @@ class AppGui: return idx: sizet = MnistNet.rand_idx(self.TestN) lb: uchar* = self.TestLbl - src: t.CPtr = self.TestRaw + 16 + idx * MnistData.N_IN + src: rawptr = self.TestRaw + 16 + idx * MnistData.N_IN string.memcpy(self.Sample28, src, MnistData.N_IN) self.HaveSample = 1 self.Canvas.setImage28(self.Sample28) @@ -1144,87 +1142,87 @@ class AppGui: _g_ui: AppGui* -def CbDownload(slot_id: int, data: t.CPtr): +def CbDownload(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_download() -def CbCopyLink(slot_id: int, data: t.CPtr): +def CbCopyLink(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_copy_link() -def CbPickDir(slot_id: int, data: t.CPtr): +def CbPickDir(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_pick_dir() -def CbCheckData(slot_id: int, data: t.CPtr): +def CbCheckData(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.check_data() -def CbPickLocal(slot_id: int, data: t.CPtr): +def CbPickLocal(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_pick_local() -def CbArchChanged(slot_id: int, data: t.CPtr): +def CbArchChanged(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_arch_changed() -def CbStartTrain(slot_id: int, data: t.CPtr): +def CbStartTrain(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_start_train() -def CbStopTrain(slot_id: int, data: t.CPtr): +def CbStopTrain(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_stop_train() -def CbZoomChart(slot_id: int, data: t.CPtr): +def CbZoomChart(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_zoom_chart() -def CbPollTraining(slot_id: int, data: t.CPtr): +def CbPollTraining(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_poll_training() -def CbLoadModel(slot_id: int, data: t.CPtr): +def CbLoadModel(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_load_model() -def CbPickSample(slot_id: int, data: t.CPtr): +def CbPickSample(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_pick_sample() -def CbClearCanvas(slot_id: int, data: t.CPtr): +def CbClearCanvas(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_clear_canvas() -def CbCanvasChanged(slot_id: int, data: t.CPtr): +def CbCanvasChanged(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_canvas_changed() -def CbUse(slot_id: int, data: t.CPtr): +def CbUse(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_use() -def CbAnimTick(slot_id: int, data: t.CPtr): +def CbAnimTick(slot_id: int, data: rawptr): if _g_ui is not None: _g_ui.on_anim_tick() -def WorkerTrain(arg: t.CPtr) -> t.CPtr: +def WorkerTrain(arg: rawptr) -> rawptr: """后台训练线程入口""" if _g_ui is not None: _g_ui.worker_train() diff --git a/ViperMNIST/App/lib/MnistData.vp b/ViperMNIST/App/lib/MnistData.vp index 533e0db..57bd1e2 100644 --- a/ViperMNIST/App/lib/MnistData.vp +++ b/ViperMNIST/App/lib/MnistData.vp @@ -11,14 +11,13 @@ # 说明: fileio.File.read_all 契约是"最多读 max_count-1 字节并补 NUL", # 故所有整读调用都按 目标长度+1 申请与请求, 否则会丢最后一字节。 # ============================================================ -import t, c from stdint import * import stdlib import string import stdio import viperlib import os -import w32.fileio as fileio +import win32.fileio as fileio import gzip import requests import requests.https as reqhttps @@ -34,20 +33,20 @@ MNIST_BASE: str = "https://ossci-datasets.s3.amazonaws.com/mnist" # ============================================================ # 基础读写 # ============================================================ -def be32(buf: t.CPtr, off: sizet) -> uint32: +def be32(buf: rawptr, off: sizet) -> uint32: """IDX 大端 u32""" ub: uchar* = buf return (uint32(ub[off]) << 24) | (uint32(ub[off + 1]) << 16) \ | (uint32(ub[off + 2]) << 8) | uint32(ub[off + 3]) -def read_file_all(path: str, fsize: sizet) -> t.CPtr: +def read_file_all(path: str, fsize: sizet) -> rawptr: """整读文件到 malloc 缓冲, 失败返回 None 注意: read_all 最多读 max_count-1 字节并补 NUL, 故按 fsize+1 申请/请求""" f: fileio.File* = fileio.File(path, fileio.MODE.R) if f.closed: return None - buf: t.CPtr = stdlib.malloc(fsize + 1) + buf: rawptr = stdlib.malloc(fsize + 1) if buf is None: f.close() return None @@ -102,7 +101,7 @@ def idx_usable(path: str, is_lb: int) -> int: if sz < 16: f.close() return 0 - hdr: t.CPtr = stdlib.malloc(64) + hdr: rawptr = stdlib.malloc(64) if hdr is None: f.close() return 0 @@ -161,7 +160,7 @@ def download_inflate(url: str, out_path: str) -> int: if cap < 1024: cap = 1024 # 保险起见: ISIZE 与实际不符时报"目标缓冲不足", 就翻倍重试(正常情况下一次成功) - dst: t.CPtr = None + dst: rawptr = None n: LONG = 0 while True: dst = stdlib.malloc(cap) @@ -378,7 +377,7 @@ def load_mnist_images(path: str, dst: double*, f.close() return 0 f.close() - whole: t.CPtr = read_file_all(path, sizet(sz)) + whole: rawptr = read_file_all(path, sizet(sz)) if whole is None: stdio.printf("[mnist] 读取失败: %s\n", path) return 0 @@ -426,7 +425,7 @@ def load_mnist_labels(path: str, dst: int*, f.close() return 0 f.close() - whole: t.CPtr = read_file_all(path, sizet(sz)) + whole: rawptr = read_file_all(path, sizet(sz)) if whole is None: return 0 # IDX 标签魔数: 00 00 08 01 diff --git a/ViperMNIST/App/lib/MnistNet.vp b/ViperMNIST/App/lib/MnistNet.vp index 18fd737..4f945e5 100644 --- a/ViperMNIST/App/lib/MnistNet.vp +++ b/ViperMNIST/App/lib/MnistNet.vp @@ -12,7 +12,6 @@ # 进度总线: train_run 每个记录点写入 prog_* 数组, UI 线程只读轮询; # prog_stop 置 1 可请求提前结束(训练线程在下一个 step 边界退出)。 # ============================================================ -import t, c from stdint import * import stdlib import string @@ -20,7 +19,7 @@ import stdio import math import memhub import torch -import w32.fileio as fileio +import win32.fileio as fileio # 输入/输出维度与数据层保持单一定义, 避免两处各写一份导致漂移 from lib.MnistData import N_IN, N_OUT @@ -80,16 +79,15 @@ define GRAPH_IN_SIDE = 8 define NET_BYTES = 480 -def _zeros_raw(pool: memhub.MemBuddy*, nb: sizet) -> t.CPtr: +def _zeros_raw(pool: memhub.MemBuddy*, nb: sizet) -> rawptr: """从内存池分配并清零一块裸缓冲(动量缓冲用; pool.alloc 不保证清零)""" - p: t.CPtr = pool.alloc(nb) + p: rawptr = pool.alloc(nb) if p is not None: string.memset(p, 0, nb) return p -@t.NoVTable -class Net: +novirtual class Net: # --- 通用 (1-4) --- Arch: sizet # 1 ARCH_MLP / ARCH_CNN Hidden: sizet # 2 MLP 隐藏层宽度; CNN 的 FC1 宽度 @@ -110,28 +108,28 @@ class Net: wf2: torch.Tensor* # 15 bf2: torch.Tensor* # 16 # --- CNN 前向激活 (17-26) --- - BZ1: t.CPtr # 17 conv1 输出 c1*28*28 - BA1: t.CPtr # 18 relu(BZ1) - BP1: t.CPtr # 19 pool1 输出 c1*14*14 - BZ2: t.CPtr # 20 conv2 输出 c2*14*14 - BA2: t.CPtr # 21 relu(BZ2) - BP2: t.CPtr # 22 pool2 输出 c2*7*7(FC1 的输入) - BZ3: t.CPtr # 23 fc1 输出 h - BA3: t.CPtr # 24 relu(BZ3) - BLG: t.CPtr # 25 logits 10 - BDA3: t.CPtr # 26 fc1 输出的梯度 h + BZ1: rawptr # 17 conv1 输出 c1*28*28 + BA1: rawptr # 18 relu(BZ1) + BP1: rawptr # 19 pool1 输出 c1*14*14 + BZ2: rawptr # 20 conv2 输出 c2*14*14 + BA2: rawptr # 21 relu(BZ2) + BP2: rawptr # 22 pool2 输出 c2*7*7(FC1 的输入) + BZ3: rawptr # 23 fc1 输出 h + BA3: rawptr # 24 relu(BZ3) + BLG: rawptr # 25 logits 10 + BDA3: rawptr # 26 fc1 输出的梯度 h # --- CNN 反向梯度 (27-34) --- - BDLG: t.CPtr # 27 dlogits 10 - BGZ3: t.CPtr # 28 fc1 反传的预激活梯度 h - BGP2: t.CPtr # 29 fc1 反传的输入梯度 49*c2 - BGA2: t.CPtr # 30 relu2 的输入梯度 c2*14*14 - BGZ2: t.CPtr # 31 pool2 反传结果 c2*14*14 - BGP1: t.CPtr # 32 conv2 反传的输入梯度 c1*14*14 - BGA1: t.CPtr # 33 relu1 的输入梯度 c1*28*28 - BGZ1: t.CPtr # 34 pool1 反传结果 c1*28*28 + BDLG: rawptr # 27 dlogits 10 + BGZ3: rawptr # 28 fc1 反传的预激活梯度 h + BGP2: rawptr # 29 fc1 反传的输入梯度 49*c2 + BGA2: rawptr # 30 relu2 的输入梯度 c2*14*14 + BGZ2: rawptr # 31 pool2 反传结果 c2*14*14 + BGP1: rawptr # 32 conv2 反传的输入梯度 c1*14*14 + BGA1: rawptr # 33 relu1 的输入梯度 c1*28*28 + BGZ1: rawptr # 34 pool1 反传结果 c1*28*28 # --- CNN 池化 argmax (35-36) --- - ARG1: t.CPtr # 35 pool1 窗口内下标(int) c1*14*14 - ARG2: t.CPtr # 36 pool2 窗口内下标(int) c2*7*7 + ARG1: rawptr # 35 pool1 窗口内下标(int) c1*14*14 + ARG2: rawptr # 36 pool2 窗口内下标(int) c2*7*7 # --- FC 层 2D 视图壳 (37-44, 每步复用不再分配) --- VF: torch.Tensor* # 37 (1, 49*c2) 复用 BP2 VZ3: torch.Tensor* # 38 (1, h) 复用 BZ3 @@ -148,27 +146,27 @@ class Net: GBF2: torch.Tensor* # 48 # --- MLP 动量缓冲 (49-52) --- # 重球法的速度项, 与参数同元素个数, 训练开始前清零; 只训练时用 - Mw1: t.CPtr # 49 - Mb1: t.CPtr # 50 - Mw2: t.CPtr # 51 - Mb2: t.CPtr # 52 + Mw1: rawptr # 49 + Mb1: rawptr # 50 + Mw2: rawptr # 51 + Mb2: rawptr # 52 # --- CNN 动量缓冲 (53-60) --- - Mwc1: t.CPtr # 53 - Mbc1: t.CPtr # 54 - Mwc2: t.CPtr # 55 - Mbc2: t.CPtr # 56 - Mwf1: t.CPtr # 57 - Mbf1: t.CPtr # 58 - Mwf2: t.CPtr # 59 - Mbf2: t.CPtr # 60 + Mwc1: rawptr # 53 + Mbc1: rawptr # 54 + Mwc2: rawptr # 55 + Mbc2: rawptr # 56 + Mwf1: rawptr # 57 + Mbf1: rawptr # 58 + Mwf2: rawptr # 59 + Mbf2: rawptr # 60 def __new__(self, pool: memhub.MemBuddy*, hidden: sizet, arch: sizet = ARCH_MLP, c1: sizet = 0, - c2: sizet = 0) -> t.CPtr: + c2: sizet = 0) -> rawptr: # 网络对象要跨帧存活(Qt 面板里存在 AppGui.Net 字段上, 训练线程还要读), # 而类实例默认是创建函数的栈 alloca —— 必须堆分配。 # 整体清零: 未用到的架构字段保持 NULL, 由 ok()/前向按 arch 判断。 - p: t.CPtr = pool.alloc(NET_BYTES) + p: rawptr = pool.alloc(NET_BYTES) if p is not None: string.memset(p, 0, NET_BYTES) return p @@ -413,7 +411,7 @@ def batch_accuracy(logits: torch.Tensor*, # 反向顺序: logits -> fc2 -> relu3 -> fc1 -> pool2 -> relu2 -> conv2 # -> pool1 -> relu1 -> conv1 # ============================================================ -def relu_raw(x: t.CPtr, out: t.CPtr, n: sizet): +def relu_raw(x: rawptr, out: rawptr, n: sizet): """out = max(0, x) 逐元素(裸缓冲版, 免去给 4D 缓冲造 2D 视图壳)""" if x is None or out is None: return @@ -427,7 +425,7 @@ def relu_raw(x: t.CPtr, out: t.CPtr, n: sizet): od[i] = double(0.0) -def relu_raw_bwd(za: t.CPtr, g: t.CPtr, gz: t.CPtr, n: sizet): +def relu_raw_bwd(za: rawptr, g: rawptr, gz: rawptr, n: sizet): """gz = g * (za > 0) —— za 是 relu 的输入(预激活)缓冲""" if za is None or g is None or gz is None: return @@ -441,7 +439,7 @@ def relu_raw_bwd(za: t.CPtr, g: t.CPtr, gz: t.CPtr, n: sizet): od[i] = double(0.0) -def cnn_forward(net: Net*, img: t.CPtr): +def cnn_forward(net: Net*, img: rawptr): """img: 784 个 0..1 归一化灰度(double 缓冲); logits 落在 net.BLG""" if net is None or img is None: return @@ -485,7 +483,7 @@ def cnn_zero_grads(net: Net*): torch.zero_grad(net.bf2) -def cnn_backward(net: Net*, img: t.CPtr, label: int) -> double: +def cnn_backward(net: Net*, img: rawptr, label: int) -> double: """反向累积一个样本的参数梯度, 返回该样本交叉熵损失 img 必须与 cnn_forward 传入的是同一块缓冲(conv1 反向要用它)""" if net is None: @@ -500,7 +498,7 @@ def cnn_backward(net: Net*, img: t.CPtr, label: int) -> double: s1: sizet = sizet(CNN_SIDE1) n1: sizet = c1 * s * s n2: sizet = c2 * s1 * s1 - loss_buf: t.CPtr = stdlib.malloc(8) + loss_buf: rawptr = stdlib.malloc(8) lab: int* = stdlib.malloc(4) if loss_buf is None or lab is None: if loss_buf is not None: @@ -576,7 +574,7 @@ def _write_tensor(f: fileio.File*, x: torch.Tensor*) -> sizet: return nb -def _read_tensor(whole: t.CPtr, off: sizet, +def _read_tensor(whole: rawptr, off: sizet, x: torch.Tensor*) -> sizet: """从整块缓冲的 off 处读一个张量, 返回新偏移(0 表示失败)""" nb: sizet = _bytes_of(x) @@ -656,7 +654,7 @@ def load_model_mk1(path: str, w1: torch.Tensor*, stdio.printf("[model] 文件过小: %s\n", path) return 1 # read_all 契约: 最多读 max_count-1 字节, 故 +1 - whole: t.CPtr = stdlib.malloc(sizet(sz) + 1) + whole: rawptr = stdlib.malloc(sizet(sz) + 1) if whole is None: return 1 fr: fileio.File* = fileio.File(path, fileio.MODE.R) @@ -756,7 +754,7 @@ def load_model_mk2(path: str, net: Net*) -> int: stdio.printf("[model] 尺寸不匹配(期望字节=%zu, 实得=%zu)\n", expect, sizet(sz)) return 1 - whole: t.CPtr = stdlib.malloc(sizet(sz) + 1) + whole: rawptr = stdlib.malloc(sizet(sz) + 1) if whole is None: return 1 fr: fileio.File* = fileio.File(path, fileio.MODE.R) @@ -994,11 +992,11 @@ def ce_from_logits(lg: double*, off: sizet, c: sizet, mx = d[off + j] s: double = double(0.0) for j in range(c): - s = s + vipermath.exp(d[off + j] - mx) + s = s + math.exp(d[off + j] - mx) li: sizet = sizet(label) if li >= c: li = 0 - return -(d[off + li] - mx - vipermath.log(s)) + return -(d[off + li] - mx - math.log(s)) def epoch_lr(lr: double, epoch: sizet, epochs: sizet) -> double: @@ -1307,7 +1305,7 @@ def _train_cnn(pool: memhub.MemBuddy*, # 单样本输入缓冲: MnistData.load_mnist_images 已把像素归一化到 0..1, # 这里只做搬运(可选平移增强), 不再二次除以 255 —— conv 只吃 double, # 且反向 conv1 要用与 forward 同一块缓冲。 - in_buf: t.CPtr = stdlib.malloc(N_IN * 8) + in_buf: rawptr = stdlib.malloc(N_IN * 8) if in_buf is None: prog_fail = 1 prog_done = 1 @@ -1513,11 +1511,11 @@ def predict_full(w1: torch.Tensor*, b1: torch.Tensor*, mx = lgl[ci] s: double = double(0.0) for ci in range(N_OUT): - s = s + vipermath.exp(lgl[ci] - mx) + s = s + math.exp(lgl[ci] - mx) best: int = 0 bv: double = double(-1.0) for ci in range(N_OUT): - p: double = vipermath.exp(lgl[ci] - mx) / s + p: double = math.exp(lgl[ci] - mx) / s if out_probs is not None: op: double* = out_probs op[ci] = p @@ -1541,7 +1539,7 @@ def predict_cnn(net: Net*, img28: bytes, if net is None or img28 is None: return -1 h: sizet = net.Hidden - xbuf: t.CPtr = stdlib.malloc(N_IN * 8) + xbuf: rawptr = stdlib.malloc(N_IN * 8) if xbuf is None: return -1 x: double* = xbuf @@ -1558,13 +1556,13 @@ def predict_cnn(net: Net*, img28: bytes, mx = ld[ci] s: double = double(0.0) for ci in range(N_OUT): - s = s + vipermath.exp(ld[ci] - mx) + s = s + math.exp(ld[ci] - mx) if s <= double(0.0): return -1 best: int = 0 bv: double = double(-1.0) for ci in range(N_OUT): - p: double = vipermath.exp(ld[ci] - mx) / s + p: double = math.exp(ld[ci] - mx) / s if out_probs is not None: op: double* = out_probs op[ci] = p @@ -1600,7 +1598,7 @@ def evaluate_cnn(net: Net*, return double(0.0) xd: double* = xbuf yd: int* = ybuf - in_buf: t.CPtr = stdlib.malloc(N_IN * 8) + in_buf: rawptr = stdlib.malloc(N_IN * 8) if in_buf is None: return double(0.0) ind: double* = in_buf diff --git a/ViperMNIST/App/main.vp b/ViperMNIST/App/main.vp index 5393c76..7dd0fec 100644 --- a/ViperMNIST/App/main.vp +++ b/ViperMNIST/App/main.vp @@ -21,7 +21,6 @@ # 权重形状同 PyTorch: Conv(out,in,k,k) / Linear(out,in), b(out) # 计算: torch-lite 线性前向走 vipersimd.simd_dot4d, relu 走 simd_max4d # ============================================================ -import t, c from stdint import * import stdlib import string @@ -31,7 +30,7 @@ import memhub import argparse import requests import torch -import w32.win32console as w32cmd +import win32.win32console as win32cmd import lib.MnistData as MnistData import lib.MnistNet as MnistNet import lib.AppGui as AppGui @@ -270,8 +269,8 @@ def run_cli(pool: memhub.MemBuddy*) -> int: # ============================================================ def main() -> int: # UTF-8 控制台(与 ViperC main 一致) - w32cmd.SetConsoleOutputCP(CODE_PAGE) - w32cmd.SetConsoleCP(CODE_PAGE) + win32cmd.SetConsoleOutputCP(CODE_PAGE) + win32cmd.SetConsoleCP(CODE_PAGE) # 主内存池: CLI 与 GUI 共用, 先建池再解析 argv(GUI 分支也需要池) arena: bytes = stdlib.malloc(POOL_SIZE) diff --git a/ViperOpenSSLProject/App/main.vp b/ViperOpenSSLProject/App/main.vp index e67e4e5..9c2a967 100644 --- a/ViperOpenSSLProject/App/main.vp +++ b/ViperOpenSSLProject/App/main.vp @@ -6,12 +6,10 @@ # # 链接目标尚未定(msys2 预装 3.6.2 动态库 或 openssl_358_C 自编译), # 配好 project.vpj 的 -lcrypto/-lssl(或 static_libs)后才可链接运行。 -import t, c import stdlib import binascii import openssl -import w32.win32console as w32cmd -import viperlib +import win32.win32console as win32cmd def print_digest(name: str, buf: bytes, length: int): @@ -20,8 +18,8 @@ def print_digest(name: str, buf: bytes, length: int): def main() -> int: - w32cmd.SetConsoleOutputCP(65001) - w32cmd.SetConsoleCP(65001) + win32cmd.SetConsoleOutputCP(65001) + win32cmd.SetConsoleCP(65001) # ---- 1) 版本 ---- ver: str = openssl.OpenSSL_version(openssl.OpenSslVersion) @@ -31,7 +29,7 @@ def main() -> int: # ---- 2) 摘要 ---- data: str = "hello openssl" - dlen: int = len(data) + dlen: int = int(len(data)) md5_buf: bytes = stdlib.malloc(openssl.Md5DigestLength) openssl.MD5(data, dlen, md5_buf) diff --git a/ViperQtHelloWorld/App/main.vp b/ViperQtHelloWorld/App/main.vp index b414f1a..27b7dad 100644 --- a/ViperQtHelloWorld/App/main.vp +++ b/ViperQtHelloWorld/App/main.vp @@ -15,7 +15,7 @@ import c import vqt6 import stdlib import memhub -import w32.win32console as w32cmd +import win32.win32console as win32cmd import viperlib define pagecode = 65001 @@ -31,8 +31,8 @@ define POOL_SIZE = 1 * 1024 * 1024 def main() -> int: global _mbuddy - w32cmd.SetConsoleOutputCP(pagecode) - w32cmd.SetConsoleCP(pagecode) + win32cmd.SetConsoleOutputCP(pagecode) + win32cmd.SetConsoleCP(pagecode) # 模块内存池 (QApplication([]) 里的 [] 要在这里分配) arena: bytes = stdlib.malloc(POOL_SIZE) diff --git a/ViperRequestsTest/App/main.vp b/ViperRequestsTest/App/main.vp index 4126034..e78f73c 100644 --- a/ViperRequestsTest/App/main.vp +++ b/ViperRequestsTest/App/main.vp @@ -7,7 +7,6 @@ # 4) rhttps.post - HTTPS POST # # Usage: requests._mbuddy = my_mbuddy (https reuses the same memory pool) -import t, c from stdint import * import stdio import stdlib @@ -18,8 +17,8 @@ import requests import requests.https as rhttps import requests.download as rd import zlib.pyzlib as pyzlib -import w32.win32file as wf -import w32.win32base as wb +import win32.win32file as wf +import win32.win32base as wb # Global MBuddy pointer @@ -298,4 +297,4 @@ def main() -> int: socket.SocketCleanup() stdio.printf("\nViperRequestsTest: DONE\n") return 0 - + diff --git a/ViperTestProject/App/main._vp b/ViperTestProject/App/main._vp deleted file mode 100644 index 5335a18..0000000 --- a/ViperTestProject/App/main._vp +++ /dev/null @@ -1,143 +0,0 @@ -import w32.win32console as w32cmd -import stdio -import t, c -from stdint import * -from t import CInt as MyInt -from stdint import BYTE as MyByte -import main2 - -pagecode: t.CDefine = 65001 - -# 类型系统收敛测试:typedef 值引用 from-import 别名(阶段1a 别名链) -MyWord: t.CTypedef = MyInt -MyDword: t.CTypedef = DWORD - - -class TestStruct(): - a: t.CInt - b: t.CInt - - -class Obj(): - val: t.CInt - - -export def main() -> int: - w32cmd.SetConsoleOutputCP(pagecode) - w32cmd.SetConsoleCP(pagecode) - print("=== Unary * / & (Deref/AddrOf) Test ===") - - # --- Test 1: 标量 & 取地址 + * 解引用 --- - x: int = 42 - px: int* = &x - d: int = *px - print(f"T1: x={x} *(&x)={d} (expect 42, 42)") - if d == 42: - print("T1 OK") - else: - print("T1 FAIL") - - # --- Test 2: 通过指针写回(c.DerefAs 兼容形式) --- - #*px = 100 - - #k: int** - #l = *k - c.DerefAs(px, 100) - print(f"T2: after c.DerefAs(px, 100) x={x} (expect 100)") - if x == 100: - print("T2 OK") - else: - print("T2 FAIL") - - # --- Test 3: 数组元素地址 &arr[i] + * 解引用 --- - a: t.CArray[t.CInt, 4] - a[0] = 7 - pa: t.CInt | t.CPtr = &a[0] - v3: int = *pa - print(f"T3: a[0]={a[0]} *&a[0]={v3} (expect 7, 7)") - if v3 == 7: - print("T3 OK") - else: - print("T3 FAIL") - - # --- Test 4: 结构体字段地址 &s.f + * 解引用 --- - s: TestStruct - s.a = 10 - pf: t.CInt | t.CPtr = &s.a - v4: int = *pf - print(f"T4: s.a={s.a} *&s.a={v4} (expect 10, 10)") - if v4 == 10: - print("T4 OK") - else: - print("T4 FAIL") - - # --- Test 5: &obj 对象指针(对象变量即指针) --- - o: Obj - o.val = 99 - po: Obj | t.CPtr = &o - print(f"T5: o.val={o.val} &o->val={po.val} (expect 99, 99)") - if po.val == 99: - print("T5 OK") - else: - print("T5 FAIL") - - print("=== Unary * / & Test Done ===") - - # ============================================================ - # 类型系统收敛测试(阶段1a/1b/2/3) - # 验证:正常库分析优先(from-import 别名、库 typedef 动态表), - # t/c 库内部特判兜底(CInt/CBool/CPtr 等核心原语保留硬编码)。 - # ============================================================ - print("=== Type System Convergence Test ===") - - # --- T6: from-import 别名反查(阶段1a)--- - # from t import CInt as MyInt → 裸名 MyInt 注解经别名反查 → i32 - a6: MyInt = 123 - # MyWord: t.CTypedef = MyInt → typedef 值引用别名 → 链式解析 - b6: MyWord = 456 - # from stdint import BYTE as MyByte → 裸名别名 → t.CUnsignedChar - m6: MyByte = 65 - print(f"T6: MyInt={a6} MyWord={b6} MyByte={m6} (expect 123, 456, 65)") - if a6 == 123 and b6 == 456 and m6 == 65: - print("T6 OK") - else: - print("T6 FAIL") - - # --- T7: 库 typedef 裸名解析(阶段1b/2)--- - # 裸名 BYTE/DWORD 走 CTypedef 动态表(stdint.vp 声明权威) - bb7: BYTE = 200 - dd7: DWORD = 0x12345678 - # typedef 引用 typedef(MyDword = DWORD → CUInt32T) - jj7: MyDword = 0xABCD - # t/c 核心原语内部特判保留(t.CBool → i1 硬编码兜底) - kk7: t.CBool = True - print(f"T7: BYTE={bb7} DWORD={dd7} MyDword={jj7} CBool={kk7} (expect 200, 305419896, 43981, 1)") - if bb7 == 200 and dd7 == 0x12345678 and jj7 == 0xABCD and kk7 == 1: - print("T7 OK") - else: - print("T7 FAIL") - - # --- T8: __sizeof__ 库 typedef(阶段3 尺寸联动)--- - s8a: int = BYTE.__sizeof__() - s8b: int = DWORD.__sizeof__() - s8c: int = MyWord.__sizeof__() - s8d: int = t.CBool.__sizeof__() - print(f"T8: sizeof(BYTE)={s8a} sizeof(DWORD)={s8b} sizeof(MyWord)={s8c} sizeof(CBool)={s8d} (expect 1, 4, 4, 1)") - if s8a == 1 and s8b == 4 and s8c == 4 and s8d == 1: - print("T8 OK") - else: - print("T8 FAIL") - - # --- T9: typedef 联合(BYTE | t.CPtr → 指针包装,* 解引用)--- - p9: BYTE | t.CPtr = &bb7 - v9: BYTE = *p9 - print(f"T9: *(BYTE|CPtr)={v9} (expect 200)") - if v9 == 200: - print("T9 OK") - else: - print("T9 FAIL") - - print("=== Type System Convergence Test Done ===") - - main2.m() - return 0 diff --git a/ViperTestProject/App/main2.vp b/ViperTestProject/App/main2.vp index 58d332e..ffd9c2b 100644 --- a/ViperTestProject/App/main2.vp +++ b/ViperTestProject/App/main2.vp @@ -1,4 +1,3 @@ -import t, c import stdio diff --git a/ViperZipfileProject/App/main.vp b/ViperZipfileProject/App/main.vp index f458dea..6231f4e 100644 --- a/ViperZipfileProject/App/main.vp +++ b/ViperZipfileProject/App/main.vp @@ -5,14 +5,13 @@ # 2) ZipFile("r") reads back: entry count / name / size / compress_size checks + per-member content compare # (CRC32 verification is done inside zipfile.read) # 3) Corrupt one payload byte of a stored member -> a second read must return None with error ZIP_ERR_CRC -import t, c from stdint import * import stdio import stdlib import string import zipfile -import w32.win32base as wb -import w32.win32file as wf +import win32.win32base as wb +import win32.win32file as wf ZIP_PATH: str = "zip_roundtrip.zip"