scheme/test/libs.scm · 5101 字节 · 下载原文
; 共享库一览 —— 用 **Scheme** 把四个共享库各叫一遍
; Shared libraries tour -- calling all four shared libraries from **Scheme**
;
; ◆ 这份例程在练什么
; ◆ What this example exercises
;
; 共享库是**一次投入、22 门语言都受益**的那种东西:`regex`(正则)· `dbf`(dBASE 数据文件)
; · `sql`(跑在 .dbf 上的查询)· `turtle`(海龟作图)。它们**不是 Scheme 的库**,
; 而是每一门语言都能调的同一份实现 —— 这份例程就是"从 Scheme 这边调得动"的活证据。
; The shared libraries are one investment serving all 22 languages: `regex`, `dbf` (dBASE data
; files), `sql` (queries over .dbf) and `turtle`. They are not Scheme libraries -- they are one
; implementation every language can call. This example is the living proof that Scheme can.
;
; regex : 模式 `abc` 在 `xxabcyy` 里**找得到**吗(1 = 找得到)
; dbf : 现建一张两字段的表、塞两条记录,再看一眼记录数
; sql : 在刚建的那张表上跑一句 `SELECT ... WHERE`
; turtle : 抬笔走 50 步,看它的坐标(不写屏幕,所以**不需要开窗口**)
;
; ◆ 为什么全程只调"返回整数"的那些接口
; ◆ Why only the integer-returning calls
;
; Scheme 的字符串字面量**取不到可写地址**,而 `dbf_get` / `sql_cell` 这类要调用方给 dst。
; 所以这里走另一条路:**要缓冲区的地方用 `alloc` 自己拿一块**(见下面 `rec` 那几行),
; 取值一律用"只问长度"的形态(`dbf_fname h 0 0`)。
; Scheme string literals give no writable address, and `dbf_get`/`sql_cell` need a caller-supplied
; dst. So: take a buffer yourself with `alloc` (see the `rec` lines below), and use the
; "length only" form of the accessors (`dbf_fname h 0 0`).
;
; ◆ 本前端的两条写法要求(实测)
; ◆ Two writing requirements of this frontend (measured)
;
; ① `display` **只取第一个实参、且不补换行** ⇒ 一行用「若干次 `(display x)` + 一次
; 1. `display` **takes only its first argument and adds no newline** => one line is built from
; "several `(display x)` calls + one `(newline)`".
; `(newline)`」拼出来 —— 本文件每一行都是这么写的。
; Every line in this file is written that way.
; ② 库函数**不需要**声明文件,顶层直接调(本文件全程在顶层,没有用户函数)。
; 2. Library functions need **no** declaration file; call them directly at the top level
; (this whole file is top level -- it defines no user function).
;
; ⚠ 跑一次会在**本文件所在目录**建一个 `libdemo.dbf`(这就是 dbf 那一半在演示的事)。
; ⚠ Running this creates a small `libdemo.dbf` **next to this file** -- that is the point of it.
; ── regex:模式匹配 ──
(display "REGEX_HIT=")
(display (re_test "abc" "xxabcyy"))
(newline)
(display "REGEX_MISS=")
(display (re_test "abc" "xxabxyy"))
(newline)
(display "REGEX_VALID=")
(display (re_is_valid "(a|b)+"))
(newline)
; ── dbf:建表 → 塞两条 → 读记录数 ──
; 字段类型用**字符的字节值**:'C' = 67(字符型)· 'N' = 78(数字型)——
; Scheme 没有字符字面量,所以这里直接写数字。
; Field types are the **byte value of the character**: 'C' = 67, 'N' = 78 -- Scheme has no
; character literal, so the number goes in directly.
(define h (dbf_new "libdemo.dbf"))
(dbf_addfield h "NAME" 67 8 0)
(dbf_addfield h "AGE" 78 3 0)
(dbf_build h)
(define rec (alloc 64))
(dbf_mkrec h rec)
(dbf_put h rec 0 "Alice")
(dbf_put h rec 1 "30")
(dbf_add h rec)
(dbf_mkrec h rec)
(dbf_put h rec 0 "Bob")
(dbf_put h rec 1 "7")
(dbf_add h rec)
(dbf_flush h)
(display "DBF_ROWS=")
(display (dbf_records h))
(newline)
(display "DBF_FIELDS=")
(display (dbf_fields h))
(newline)
(display "DBF_FIELD0_LEN=")
(display (dbf_fname h 0 0))
(newline)
(dbf_close h)
; ── sql:在刚建的表上查 ──
(display "SQL_ROWS=")
(display (sql_run "libdemo.dbf" "SELECT * FROM t WHERE AGE > 20"))
(newline)
(display "SQL_COLS=")
(display (sql_cols))
(newline)
(display "SQL_COL0_LEN=")
(display (sql_colname 0 0))
(newline)
; ── turtle:抬笔走 50 步(落笔会去画屏幕,那要窗口)──
(turtle_reset)
(turtle_pen_up)
(turtle_forward 50)
(display "TURTLE_X=")
(display (turtle_x))
(newline)
(display "TURTLE_Y=")
(display (turtle_y))
(newline)
; ── sed:sed 的替换规则(s / y 两条命令,依附 regex 库)—— 缓冲区那一半只有 C 拿得到,
; 这里压的是「只问长度」那一支(cap 传 0)与对账用的 sed_count。
(display "SED_COUNT=")
(display (sed_count "s/a/X/g" "banana"))
(newline)
(display "SED_LEN=")
(display (sed_sub "s/a/X/g" "banana" 0 0))
(newline)
(display "DONE=")
(display 1)
(newline)
; 期望(scripts/lib-examples-check.sh 按这一行比对):
; EXPECT: REGEX_HIT=1|REGEX_MISS=0|REGEX_VALID=1|DBF_ROWS=2|DBF_FIELDS=2|DBF_FIELD0_LEN=4|SQL_ROWS=1|SQL_COLS=2|SQL_COL0_LEN=4|TURTLE_X=0|TURTLE_Y=50|SED_COUNT=3|SED_LEN=6|DONE=1