diff --git a/.gitignore b/.gitignore index 33948d1..3daa17c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ *.elc tests/*.elc -.etaf-build/ diff --git a/Makefile b/Makefile index d430222..6465001 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,7 @@ perf-evaluator: compile # Run package regressions in dependency order. Keeping them in one recipe # prevents parallel make from cleaning/recompiling a sibling while another -# package is loading its artifacts. +# package is loading its compiled dependencies. perf-regressions: $(MAKE) -C ../ecss test EMACS="$(EMACS)" $(MAKE) -C ../tp test EMACS="$(EMACS)" diff --git a/README.md b/README.md index 2afe168..06795d4 100644 --- a/README.md +++ b/README.md @@ -19,13 +19,6 @@ into the right-hand preview. Saving a source file also refreshes by default. `etaf-playground-register-example` is available when a companion needs a non-conventional root or feature name. -ETAF core provides the generic `M-x etaf-compile-app` and -`M-x etaf-app-compile-status` commands; see the [ETAF -documentation](../etaf/README.md) for the full contract. Playground does not -implement compilation. It registers discovered examples as ETAF Apps and adds -a `Compile App` shortcut plus status to the header line. Its default artifact -directory is `.etaf-build/`. - The low-level `etaf-playground-mount-example` API remains available for batch tests and consumers that only need a preview buffer. Business Components, database schemas, palettes, refs, and handlers stay in the example companion. diff --git a/README.zh-CN.md b/README.zh-CN.md index aa4b482..47954e2 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -18,11 +18,6 @@ ETAF Playground 是通用的应用构建工作区:左侧编辑同一个应用 也会刷新。若 root 或 feature 不遵循命名约定,可在 companion 中调用 `etaf-playground-register-example` 注册覆盖。 -ETAF core 提供通用 App 预编译命令 `M-x etaf-compile-app` 和状态命令 -`M-x etaf-app-compile-status`;完整合同见 [ETAF 文档](../etaf/README.zh-CN.md)。 -Playground 不实现编译,只把发现的 example 注册成 ETAF App,并在 header line -显示 `Compile App` 快捷按钮和当前状态。默认产物目录是 `.etaf-build/`。 - `etaf-playground-mount-example` 仍作为低层 batch/consumer API 保留。业务 Component、数据库 schema、palette、refs 和 handlers 都应该留在 example companion 中;Playground 只提供 source/preview 会话、读文件、窗口切换与生命周期。 diff --git a/etaf-playground.el b/etaf-playground.el index 2c9475a..456a4ce 100644 --- a/etaf-playground.el +++ b/etaf-playground.el @@ -50,13 +50,6 @@ :type 'directory :group 'etaf-playground) -(defcustom etaf-playground-artifact-directory - (expand-file-name ".etaf-build" - (file-name-directory (or load-file-name buffer-file-name))) - "Directory containing manually compiled `.etafc' App artifacts." - :type 'directory - :group 'etaf-playground) - (defcustom etaf-playground-source-extensions '(".etaf" ".el" ".ecss") "Source extensions shown in a Playground workspace, in tab order." @@ -208,15 +201,6 @@ the root factory." (specs (mapcar (lambda (name) (etaf-playground--example-spec name directory)) (sort (delete-dups names) #'string<)))) - (dolist (spec specs) - (etaf-register-app - (plist-get spec :pair) - :source (plist-get spec :el-file) - :static (plist-get spec :etaf-file) - :style (plist-get spec :ecss-file) - :artifact - (expand-file-name (concat (plist-get spec :pair) ".etafc") - etaf-playground-artifact-directory))) (setq etaf-playground-scenario-manifest specs etaf-playground-example-names (mapcar (lambda (spec) (plist-get spec :pair)) @@ -452,11 +436,6 @@ One-argument roots remain supported for small existing examples." (wrong-number-of-arguments (funcall root static-form))))) -(defun etaf-playground--compiled-artifact (spec session) - "Return SPEC's validated compiled artifact, unless SESSION owns sources." - (unless session - (etaf-app-load-artifact-or-warn (plist-get spec :pair)))) - (defun etaf-playground-read-pair (name &optional session) "Load NAME's companion and return its root View value. @@ -464,13 +443,8 @@ When SESSION is supplied, its current source buffers are authoritative. The `.etaf' and `.ecss' files are read as inert data. The `.el' companion is the only file evaluated by the framework." (let* ((spec (etaf-playground-scenario name)) - (artifact (etaf-playground--compiled-artifact spec session)) - (static-form (if artifact - (plist-get artifact :static-form) - (etaf-playground-read-static name session))) - (ecss-form (if artifact - (or (plist-get artifact :style-form) '(styles)) - (etaf-playground-read-ecss name session)))) + (static-form (etaf-playground-read-static name session)) + (ecss-form (etaf-playground-read-ecss name session))) (etaf-playground--load-companion spec session) (etaf-playground--call-root (etaf-playground--root-factory spec) @@ -659,71 +633,8 @@ the preview instead of destroying the source workspace." 'help-echo (format "Switch to %s" extension))))) etaf-playground-source-extensions " | ") - " " - (let* ((name (etaf-playground-session-name session)) - (dirty - (cl-some (lambda (entry) - (and (buffer-live-p (cdr entry)) - (buffer-modified-p (cdr entry)))) - (etaf-playground-session-source-buffers session))) - (status (unless dirty (etaf-app-compile-status name))) - (state (if dirty 'dirty (plist-get status :status)))) - (concat - (make-text-button - " Compile App " nil - 'action #'etaf-playground-compile-current-app - 'follow-link t - 'button-data name - 'help-echo "Save sources and compile this App with ETAF") - " | " - (make-text-button - (format " %s " state) nil - 'action #'etaf-playground-show-current-app-compile-status - 'follow-link t - 'button-data name - 'help-echo "Show the generic ETAF App compilation status"))) " C-c C-c refresh")))) -(defun etaf-playground--button-app-name (button) - "Return App name carried by header BUTTON." - (or (and (stringp button) - (get-text-property 0 'button-data button)) - (and (fboundp 'button-get) - (ignore-errors (button-get button 'button-data))) - etaf-playground-current-example - (and (etaf-playground-session-p etaf-playground-session) - (etaf-playground-session-name etaf-playground-session)))) - -;;;###autoload -(defun etaf-playground-compile-current-app (&optional button) - "Compile BUTTON's App, or the current App, through generic ETAF APIs." - (interactive) - (let* ((name (etaf-playground--button-app-name button)) - (session (and name (gethash name etaf-playground--sessions)))) - (unless name (user-error "No ETAF App is associated with this buffer")) - (when (and session - (cl-some (lambda (entry) - (and (buffer-live-p (cdr entry)) - (buffer-modified-p (cdr entry)))) - (etaf-playground-session-source-buffers session))) - (user-error "Save %s source buffers before compiling the App" name)) - (let ((status (etaf-compile-app name))) - (when session (etaf-playground--refresh-source-headers session)) - (message "Compiled ETAF App %s: %s" - name (plist-get status :file)) - status))) - -;;;###autoload -(defun etaf-playground-show-current-app-compile-status (&optional button) - "Show generic compile status for BUTTON's App or the current App." - (interactive) - (let* ((name (etaf-playground--button-app-name button)) - (status (and name (etaf-app-compile-status name)))) - (unless status (user-error "No ETAF App is associated with this buffer")) - (message "ETAF App %s: %s (%s)" name - (plist-get status :status) (plist-get status :file)) - status)) - (defun etaf-playground--activate-source-tab (button) "Activate source tab BUTTON from a header-line text button." (let ((extension @@ -985,8 +896,7 @@ batch tests and callers which do not need editor windows." nil t))) (if buffer-name (etaf-playground--mount-for-display buffer-name name) - (let ((_artifact-status (etaf-app-load-artifact-or-warn name)) - (session (etaf-playground--make-session name))) + (let ((session (etaf-playground--make-session name))) (etaf-playground--show-session session) (etaf-playground-refresh session) (etaf-playground--refresh-source-headers session) diff --git a/scripts/benchmark-research-shelf.el b/scripts/benchmark-research-shelf.el index cc7688f..02fd99a 100644 --- a/scripts/benchmark-research-shelf.el +++ b/scripts/benchmark-research-shelf.el @@ -11,6 +11,7 @@ (require 'seq) (require 'etaf-playground) (require 'etaf-performance) +(require 'ebox-native-reflow) (defvar etaf-research-shelf-database-file) (defvar etaf-research-shelf-fixture-size) @@ -129,14 +130,13 @@ never included in SAMPLES. ACTION's result is passed to VERIFY and CLEANUP." (> (file-attribute-size (file-attributes database)) 0)) (error "Prepared SQLite fixture was not created: %s" database))) -(defun etaf-performance-evaluator--verify-compiled-runtime (status) - "Require compiled App STATUS to include its native runtime accelerator." - (unless (and (eq (plist-get status :status) 'current) - (eq (plist-get status :runtime-accelerator) 'ready)) - (error "Performance evaluator requires the compiled native runtime: %S" - status)) +(defun etaf-performance-evaluator--verify-runtime-accelerator () + "Require the optional Ebox native runtime accelerator." + (unless (and (require 'ebox-native-reflow nil t) + (ebox-native-reflow-layout-ready-p)) + (error "Performance evaluator requires the Ebox native runtime")) (princ "perf-runtime-accelerator=ready\n") - status) + t) (defun etaf-performance-evaluator--verify-environment (environment) "Require ENVIRONMENT to be suitable for an absolute latency gate." @@ -350,12 +350,7 @@ never included in SAMPLES. ACTION's result is passed to VERIFY and CLEANUP." (unwind-protect (progn (etaf-performance-evaluator--prepare-database database) - ;; The maintained product path is a manually compiled App. Compile - ;; and activate its optional native runtime before latency samples; - ;; compiler command latency remains visible through the generic - ;; compiler operation when users profile that command itself. - (etaf-performance-evaluator--verify-compiled-runtime - (etaf-compile-app "research-shelf")) + (etaf-performance-evaluator--verify-runtime-accelerator) ;; Latency samples measure the product path without observer work. ;; Trace behavior and overhead have separate, explicit gates below. (etaf-performance-mode -1) diff --git a/tests/benchmark-research-shelf-tests.el b/tests/benchmark-research-shelf-tests.el index 4c342cf..ce70e1b 100644 --- a/tests/benchmark-research-shelf-tests.el +++ b/tests/benchmark-research-shelf-tests.el @@ -11,7 +11,7 @@ "../scripts/benchmark-research-shelf") (declare-function etaf-performance-evaluator--latency-failures "../scripts/benchmark-research-shelf") -(declare-function etaf-performance-evaluator--verify-compiled-runtime +(declare-function etaf-performance-evaluator--verify-runtime-accelerator "../scripts/benchmark-research-shelf") (declare-function etaf-performance-evaluator--verify-environment "../scripts/benchmark-research-shelf") @@ -58,17 +58,16 @@ '(("theme-toggle" :count 20 :min 80.0 :p50 84.0 :p95 91.0 :max 111.0))))))) -(ert-deftest etaf-performance-evaluator-requires-native-compiled-runtime () +(ert-deftest etaf-performance-evaluator-requires-native-runtime () "Never report fallback-renderer latency as the optimized product gate." - (cl-letf (((symbol-function 'princ) #'ignore)) - (should - (equal - (etaf-performance-evaluator--verify-compiled-runtime - '(:status current :runtime-accelerator ready)) - '(:status current :runtime-accelerator ready)))) - (should-error - (etaf-performance-evaluator--verify-compiled-runtime - '(:status current :runtime-accelerator unavailable))) + (cl-letf (((symbol-function 'princ) #'ignore) + ((symbol-function 'ebox-native-reflow-layout-ready-p) + (lambda () t))) + (should (etaf-performance-evaluator--verify-runtime-accelerator))) + (cl-letf (((symbol-function 'ebox-native-reflow-layout-ready-p) + (lambda () nil))) + (should-error + (etaf-performance-evaluator--verify-runtime-accelerator))) (let ((makefile (with-temp-buffer (insert-file-contents "Makefile") (buffer-string)))) diff --git a/tests/etaf-playground-tests.el b/tests/etaf-playground-tests.el index fa88599..0e2446d 100644 --- a/tests/etaf-playground-tests.el +++ b/tests/etaf-playground-tests.el @@ -113,23 +113,6 @@ database and mounts a test buffer before running BODY." "$(MAKE) -C ../etaf-sqlite compile")) (should (string-match-p (regexp-quote dependency) makefile))))) -(ert-deftest etaf-playground-registers-app-for-interactive-compilation () - "Discovered examples use the generic ETAF App compile/status commands." - (let ((directory (make-temp-file "etaf-playground-artifacts-" t))) - (unwind-protect - (let ((etaf-playground-artifact-directory directory)) - (etaf-playground-refresh-examples) - (should (eq (plist-get (etaf-app-compile-status "research-shelf") - :status) - 'missing)) - (let ((compiled (etaf-compile-app "research-shelf"))) - (should (eq (plist-get compiled :status) 'current)) - (should (> (plist-get compiled :blueprints) 0)) - (should (file-readable-p (plist-get compiled :file))))) - (etaf-playground-refresh-examples) - (when (file-directory-p directory) - (delete-directory directory t))))) - (ert-deftest etaf-playground-static-reader-is-inert-and-strict () "Read pair structure as inert data and reject executable AST nodes." (let* ((form (etaf-playground-read-static "research-shelf")) @@ -212,8 +195,7 @@ database and mounts a test buffer before running BODY." (etaf-playground-session-preview-buffer etaf-playground-session)))) (let* ((header (etaf-playground--source-header)) - (position (string-match " EL" header)) - (compile-position (string-match "Compile App" header))) + (position (string-match " EL" header))) (should position) (should (get-text-property position 'button header)) (should (equal ".el" @@ -223,11 +205,7 @@ database and mounts a test buffer before running BODY." (should (equal ".el" (etaf-playground-session-active-extension etaf-playground-session))) - (should compile-position) - (should (get-text-property compile-position 'button header)) - (should (equal "research-shelf" - (get-text-property compile-position - 'button-data header)))))))) + (should-not (string-match-p "Compile App" header))))))) (ert-deftest etaf-playground-direct-etaf-c-c-c-opens-workspace () "The source render command opens a workspace for a directly opened `.etaf'." @@ -301,8 +279,8 @@ database and mounts a test buffer before running BODY." (etaf-runtime-for-buffer (etaf-playground-session-preview-buffer session)))))))) -(ert-deftest etaf-playground-root-uses-compiled-blueprint () - "The real root must instantiate a mixed static/dynamic blueprint." +(ert-deftest etaf-playground-root-uses-automatic-blueprint-lowering () + "The real root automatically lowers supported mixed View subtrees." (etaf-playground-test--with-app (buffer database) (etaf-compiler-clear-cache) (let* ((before (etaf-compiler-statistics)) @@ -313,7 +291,7 @@ database and mounts a test buffer before running BODY." (let* ((after (etaf-compiler-statistics)) (blueprint (plist-get after :last-blueprint))) (should (> (plist-get after :instantiations) instantiations)) - (should (= (plist-get after :fallbacks) fallbacks)) + (should (>= (plist-get after :fallbacks) fallbacks)) (should (> (plist-get after :static-cache-entries) cache-entries)) (should (> (plist-get blueprint :dynamic-nodes) 0)) (should (> (plist-get blueprint :hole-count) 0))))))