Merge remote-tracking branch 'origin/loops/tcl' into architecture
This commit is contained in:
@@ -292,13 +292,15 @@
|
||||
(> (len result-stack) caller-stack-len)
|
||||
(nth result-stack caller-stack-len)
|
||||
(get interp :frame))))
|
||||
(assoc interp
|
||||
; Forward result-interp as base so state changes inside
|
||||
; the proc (e.g. :fileevents, :timers, :procs) propagate;
|
||||
; restore caller's frame/stack/result/output/code.
|
||||
(assoc result-interp
|
||||
:frame updated-caller
|
||||
:frame-stack updated-below
|
||||
:result result-val
|
||||
:output (str caller-output proc-output)
|
||||
:code (if (= code 2) 0 code)
|
||||
:commands (get result-interp :commands))))))))))))))
|
||||
:code (if (= code 2) 0 code))))))))))))))
|
||||
|
||||
(define
|
||||
tcl-eval-cmd
|
||||
@@ -2887,12 +2889,54 @@
|
||||
((equal? sub "seconds") (assoc interp :result (str (clock-seconds))))
|
||||
((equal? sub "milliseconds") (assoc interp :result (str (clock-milliseconds))))
|
||||
((equal? sub "format")
|
||||
(assoc interp :result (clock-format
|
||||
(floor (parse-int (first rest-args)))
|
||||
(if (> (len rest-args) 1) (nth rest-args (- (len rest-args) 1)) "%a %b %e %H:%M:%S %Z %Y"))))
|
||||
((equal? sub "scan") (assoc interp :result "0"))
|
||||
; clock format $secs ?-format $fmt? ?-timezone $tz? ?-gmt 0|1?
|
||||
(let
|
||||
((t (floor (parse-int (first rest-args))))
|
||||
(opts (rest rest-args)))
|
||||
(let
|
||||
((fmt (tcl-clock-opt opts "-format" "%a %b %e %H:%M:%S %Z %Y"))
|
||||
(tz (tcl-clock-tz opts)))
|
||||
(assoc interp :result (clock-format t fmt tz)))))
|
||||
((equal? sub "scan")
|
||||
; clock scan $str ?-format $fmt? ?-timezone $tz? ?-gmt 0|1?
|
||||
(let
|
||||
((s (first rest-args)) (opts (rest rest-args)))
|
||||
(let
|
||||
((fmt (tcl-clock-opt opts "-format" "%Y-%m-%d %H:%M:%S"))
|
||||
(tz (tcl-clock-tz opts)))
|
||||
(assoc interp :result (str (clock-scan s fmt tz))))))
|
||||
(else (error (str "clock: unknown subcommand \"" sub "\""))))))))
|
||||
|
||||
; Helper: extract a -flag $val pair from clock args.
|
||||
(define
|
||||
tcl-clock-opt
|
||||
(fn
|
||||
(opts flag default)
|
||||
(cond
|
||||
((< (len opts) 2) default)
|
||||
((equal? (first opts) flag) (nth opts 1))
|
||||
(else (tcl-clock-opt (rest (rest opts)) flag default)))))
|
||||
|
||||
; Helper: derive tz string from clock opts (-timezone or -gmt).
|
||||
(define
|
||||
tcl-clock-tz
|
||||
(fn
|
||||
(opts)
|
||||
(let
|
||||
((tz-explicit (tcl-clock-opt opts "-timezone" nil))
|
||||
(gmt-flag (tcl-clock-opt opts "-gmt" nil)))
|
||||
(cond
|
||||
((not (nil? tz-explicit))
|
||||
(cond
|
||||
((equal? tz-explicit ":UTC") "utc")
|
||||
((equal? tz-explicit "UTC") "utc")
|
||||
((equal? tz-explicit "GMT") "utc")
|
||||
(else "local")))
|
||||
((equal? gmt-flag "1") "utc")
|
||||
((equal? gmt-flag "true") "utc")
|
||||
((not (nil? gmt-flag)) "local")
|
||||
(else "utc")))))
|
||||
|
||||
(define
|
||||
tcl-cmd-open
|
||||
(fn
|
||||
@@ -2973,26 +3017,31 @@
|
||||
(interp args)
|
||||
(let
|
||||
((chan (first args)) (rest-args (rest args)))
|
||||
(if
|
||||
(= 0 (len rest-args))
|
||||
(assoc
|
||||
interp
|
||||
:result (str "-blocking " (if (channel-blocking? chan) "1" "0")))
|
||||
(if
|
||||
(and
|
||||
(= 2 (len rest-args))
|
||||
(equal? (first rest-args) "-blocking"))
|
||||
(cond
|
||||
((= 0 (len rest-args))
|
||||
(assoc
|
||||
interp
|
||||
:result (str "-blocking " (if (channel-blocking? chan) "1" "0"))))
|
||||
((and
|
||||
(= 2 (len rest-args))
|
||||
(equal? (first rest-args) "-blocking"))
|
||||
(let
|
||||
((b (nth rest-args 1)))
|
||||
(let
|
||||
((_ (channel-set-blocking! chan (not (or (equal? b "0") (equal? b "false"))))))
|
||||
(assoc interp :result "")))
|
||||
(if
|
||||
(and
|
||||
(= 1 (len rest-args))
|
||||
(equal? (first rest-args) "-blocking"))
|
||||
(assoc interp :result (if (channel-blocking? chan) "1" "0"))
|
||||
(assoc interp :result "")))))))
|
||||
((_
|
||||
(channel-set-blocking!
|
||||
chan
|
||||
(not (or (equal? b "0") (equal? b "false"))))))
|
||||
(assoc interp :result ""))))
|
||||
((and
|
||||
(= 1 (len rest-args))
|
||||
(equal? (first rest-args) "-blocking"))
|
||||
(assoc interp :result (if (channel-blocking? chan) "1" "0")))
|
||||
((and
|
||||
(= 1 (len rest-args))
|
||||
(equal? (first rest-args) "-error"))
|
||||
(assoc interp :result (channel-async-error chan)))
|
||||
(else (assoc interp :result ""))))))
|
||||
|
||||
|
||||
; ============================================================
|
||||
@@ -3253,6 +3302,13 @@
|
||||
(assoc
|
||||
(tcl-fileevent-set interp server-chan "readable" handler)
|
||||
:result server-chan))))))
|
||||
((equal? (first args) "-async")
|
||||
(if
|
||||
(< (len args) 3)
|
||||
(error "socket: usage: socket -async host port")
|
||||
(let
|
||||
((host (nth args 1)) (port (parse-int (nth args 2))))
|
||||
(assoc interp :result (socket-connect-async host port)))))
|
||||
((= 2 (len args))
|
||||
(let
|
||||
((host (first args)) (port (parse-int (nth args 1))))
|
||||
@@ -3609,16 +3665,52 @@
|
||||
(equal? dot-idx "-1")
|
||||
nm
|
||||
(substring nm 0 (parse-int dot-idx)))))))
|
||||
((equal? sub "isfile") (assoc interp :result "0"))
|
||||
((equal? sub "isdir") (assoc interp :result "0"))
|
||||
((equal? sub "isdirectory") (assoc interp :result "0"))
|
||||
((equal? sub "readable") (assoc interp :result "0"))
|
||||
((equal? sub "writable") (assoc interp :result "0"))
|
||||
((equal? sub "size") (assoc interp :result "0"))
|
||||
((equal? sub "mkdir") (assoc interp :result ""))
|
||||
((equal? sub "copy") (assoc interp :result ""))
|
||||
((equal? sub "rename") (assoc interp :result ""))
|
||||
((equal? sub "delete") (assoc interp :result ""))
|
||||
((equal? sub "isfile")
|
||||
(assoc interp :result (if (file-isfile? (first rest-args)) "1" "0")))
|
||||
((equal? sub "isdir")
|
||||
(assoc interp :result (if (file-isdir? (first rest-args)) "1" "0")))
|
||||
((equal? sub "isdirectory")
|
||||
(assoc interp :result (if (file-isdir? (first rest-args)) "1" "0")))
|
||||
((equal? sub "readable")
|
||||
(assoc interp :result (if (file-readable? (first rest-args)) "1" "0")))
|
||||
((equal? sub "writable")
|
||||
(assoc interp :result (if (file-writable? (first rest-args)) "1" "0")))
|
||||
((equal? sub "size")
|
||||
(assoc interp :result (str (file-size (first rest-args)))))
|
||||
((equal? sub "mtime")
|
||||
(assoc interp :result (str (file-mtime (first rest-args)))))
|
||||
((equal? sub "atime")
|
||||
(let ((s (file-stat (first rest-args))))
|
||||
(assoc interp :result (if (nil? s) "0" (str (get s :atime))))))
|
||||
((equal? sub "type")
|
||||
(let ((s (file-stat (first rest-args))))
|
||||
(assoc interp :result (if (nil? s) "" (get s :type)))))
|
||||
((equal? sub "mkdir")
|
||||
(let ((_ (file-mkdir (first rest-args))))
|
||||
(assoc interp :result "")))
|
||||
((equal? sub "copy")
|
||||
(let
|
||||
((paths
|
||||
(filter (fn (a) (not (equal? (slice a 0 1) "-"))) rest-args)))
|
||||
(let ((_ (file-copy (first paths) (nth paths 1))))
|
||||
(assoc interp :result ""))))
|
||||
((equal? sub "rename")
|
||||
(let
|
||||
((paths
|
||||
(filter (fn (a) (not (equal? (slice a 0 1) "-"))) rest-args)))
|
||||
(let ((_ (file-rename (first paths) (nth paths 1))))
|
||||
(assoc interp :result ""))))
|
||||
((equal? sub "delete")
|
||||
(let
|
||||
((paths
|
||||
(filter (fn (a) (not (equal? (slice a 0 1) "-"))) rest-args)))
|
||||
(let
|
||||
((_
|
||||
(reduce
|
||||
(fn (acc p) (let ((_ (file-delete p))) acc))
|
||||
nil
|
||||
paths)))
|
||||
(assoc interp :result ""))))
|
||||
(else (error (str "file: unknown subcommand \"" sub "\""))))))))
|
||||
|
||||
(define
|
||||
|
||||
@@ -59,7 +59,7 @@ cat > "$TMPFILE" << EPOCHS
|
||||
(eval "tcl-test-summary")
|
||||
EPOCHS
|
||||
|
||||
OUTPUT=$(timeout 1200 "$SX_SERVER" < "$TMPFILE" 2>&1)
|
||||
OUTPUT=$(timeout 2400 "$SX_SERVER" < "$TMPFILE" 2>&1)
|
||||
[ "$VERBOSE" = "-v" ] && echo "$OUTPUT"
|
||||
|
||||
# Extract summary line from epoch 11 output
|
||||
|
||||
@@ -303,6 +303,118 @@
|
||||
:result)
|
||||
"3")
|
||||
|
||||
; 42-49. Phase 5d file metadata + ops
|
||||
(ok "file-isfile-true"
|
||||
(get
|
||||
(run
|
||||
"set f /tmp/tcl-phase5d-1.txt\nset c [open $f w]\nputs -nonewline $c x\nclose $c\nset r [file isfile $f]\nfile delete $f\nreturn $r")
|
||||
:result)
|
||||
"1")
|
||||
|
||||
(ok "file-isfile-false-on-dir"
|
||||
(get (run "file isfile /tmp") :result)
|
||||
"0")
|
||||
|
||||
(ok "file-isdir-true"
|
||||
(get (run "file isdir /tmp") :result)
|
||||
"1")
|
||||
|
||||
(ok "file-size"
|
||||
(get
|
||||
(run
|
||||
"set f /tmp/tcl-phase5d-2.txt\nset c [open $f w]\nputs -nonewline $c hello\nclose $c\nset s [file size $f]\nfile delete $f\nreturn $s")
|
||||
:result)
|
||||
"5")
|
||||
|
||||
(ok "file-readable-true"
|
||||
(get (run "file readable /tmp") :result)
|
||||
"1")
|
||||
|
||||
(ok "file-readable-missing"
|
||||
(get (run "file readable /no/such/path/here") :result)
|
||||
"0")
|
||||
|
||||
(ok "file-mkdir-then-isdir"
|
||||
(get
|
||||
(run
|
||||
"set d /tmp/tcl-phase5d-mkdir/sub\nfile mkdir $d\nset r [file isdir $d]\nfile delete $d\nfile delete /tmp/tcl-phase5d-mkdir\nreturn $r")
|
||||
:result)
|
||||
"1")
|
||||
|
||||
(ok "file-copy-roundtrip"
|
||||
(get
|
||||
(run
|
||||
"set s /tmp/tcl-phase5d-src.txt\nset d /tmp/tcl-phase5d-dst.txt\nset c [open $s w]\nputs -nonewline $c copydata\nclose $c\nfile copy $s $d\nset c [open $d r]\nset out [read $c]\nclose $c\nfile delete $s\nfile delete $d\nreturn $out")
|
||||
:result)
|
||||
"copydata")
|
||||
|
||||
(ok "file-rename-then-exists"
|
||||
(get
|
||||
(run
|
||||
"set s /tmp/tcl-phase5d-r1.txt\nset d /tmp/tcl-phase5d-r2.txt\nset c [open $s w]\nputs -nonewline $c x\nclose $c\nfile rename $s $d\nset r [list [file exists $s] [file exists $d]]\nfile delete $d\nreturn $r")
|
||||
:result)
|
||||
"0 1")
|
||||
|
||||
(ok "file-mtime-positive"
|
||||
(get
|
||||
(run
|
||||
"set f /tmp/tcl-phase5d-mt.txt\nset c [open $f w]\nputs -nonewline $c x\nclose $c\nset m [file mtime $f]\nfile delete $f\nexpr {$m > 0}")
|
||||
:result)
|
||||
"1")
|
||||
|
||||
; 52-56. Phase 5e clock format options + clock scan
|
||||
(ok "clock-format-utc"
|
||||
(get
|
||||
(run "clock format 0 -format {%Y-%m-%d %H:%M:%S} -gmt 1")
|
||||
:result)
|
||||
"1970-01-01 00:00:00")
|
||||
|
||||
(ok "clock-format-fmt-default"
|
||||
(get
|
||||
(run "clock format 1710513000 -format {%Y-%m-%d} -gmt 1")
|
||||
:result)
|
||||
"2024-03-15")
|
||||
|
||||
(ok "clock-scan-roundtrip"
|
||||
(get
|
||||
(run "set t [clock scan {2024-06-15 12:00:00} -format {%Y-%m-%d %H:%M:%S} -gmt 1]\nclock format $t -format {%Y-%m-%d %H:%M:%S} -gmt 1")
|
||||
:result)
|
||||
"2024-06-15 12:00:00")
|
||||
|
||||
(ok "clock-scan-returns-int"
|
||||
(get
|
||||
(run "expr {[clock scan {1970-01-01 00:00:00} -format {%Y-%m-%d %H:%M:%S} -gmt 1] == 0}")
|
||||
:result)
|
||||
"1")
|
||||
|
||||
(ok "clock-format-percent-pct"
|
||||
(get
|
||||
(run "clock format 0 -format {%Y%%%m} -gmt 1")
|
||||
:result)
|
||||
"1970%01")
|
||||
|
||||
; 57-59. Phase 5f socket -async (non-blocking connect)
|
||||
(ok "socket-async-completes-writable"
|
||||
(get
|
||||
(run
|
||||
"proc h {sock host port} { close $sock }\nset srv [socket -server h 18930]\nset c [socket -async localhost 18930]\nset ready 0\nfileevent $c writable {global ready; set ready 1}\nvwait ready\nclose $c\nclose $srv\nset ready")
|
||||
:result)
|
||||
"1")
|
||||
|
||||
(ok "socket-async-then-write"
|
||||
(get
|
||||
(run
|
||||
"proc accept {sock host port} { global accepted_sock; set accepted_sock $sock; fileevent $sock readable [list reader $sock] }\nproc reader {sock} { global received; gets $sock line; set received $line; close $sock }\nset srv [socket -server accept 18931]\nset c [socket -async localhost 18931]\nfileevent $c writable {global wready; set wready 1; fileevent $::ch writable {}}\nset ::ch $c\nvwait wready\nputs $c async-data\nflush $c\nvwait received\nclose $c\nclose $srv\nset received")
|
||||
:result)
|
||||
"async-data")
|
||||
|
||||
(ok "socket-async-no-error"
|
||||
(get
|
||||
(run
|
||||
"proc h {sock host port} { close $sock }\nset srv [socket -server h 18932]\nset c [socket -async localhost 18932]\nset r 0\nfileevent $c writable {global r; set r 1}\nvwait r\nset err [fconfigure $c -error]\nclose $c\nclose $srv\nreturn $err")
|
||||
:result)
|
||||
"")
|
||||
|
||||
(dict
|
||||
"passed"
|
||||
tcl-idiom-pass
|
||||
|
||||
Reference in New Issue
Block a user