diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 07ac5ece..de893ea8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,7 @@ on: push: branches: - main - # - develop + - develop paths-ignore: - '**/README.md' - '**/CHANGELOG.md' diff --git a/src/vybe/c.clj b/src/vybe/c.clj index 492085ec..5fe970aa 100644 --- a/src/vybe/c.clj +++ b/src/vybe/c.clj @@ -1,5 +1,6 @@ (ns vybe.c (:require + [vybe.c :as vc] [babashka.process :as proc] [bling.core :as bling] [clojure.edn :as edn] @@ -773,11 +774,6 @@ int bs_lower_bound(float a[], int n, float x) { (cond (= (:op (:expr init)) :fn) (let [{:keys [params body]} (first (:methods (:expr init))) - #_ #_schema (::schema (meta (first (:form (first (:methods (:expr init))))))) - #_ #_schema (if-let [s (and (symbol? schema) - (resolve schema))] - @s - schema) return-tag (or (some-> (::schema (meta (first (:form (first (:methods (:expr init))))))) -adapt-type ->name) @@ -805,30 +801,6 @@ int bs_lower_bound(float a[], int n, float x) { (str/join ", ") parens) " {\n" - - #_(cond - (vp/component? schema) - (format " -if (setjmp(buf)) {return (%s){};}; -signal(SIGSEGV, sighandler); -" - return-tag) - - (str/includes? return-tag "*") - " -if (setjmp(buf)) return NULL; -signal(SIGSEGV, sighandler); -" - (= return-tag "void") - "" - - :else - " -if (setjmp(buf)) return -1; -signal(SIGSEGV, sighandler); -") - - ;; Add `return` only to the last expression (if applicable). (if (= return-tag "void") (emit body) @@ -858,6 +830,55 @@ signal(SIGSEGV, sighandler); -adapt-type ->name)))) + ;; TODO Maybe use `fnc` instead? + #_ (defn* ^:debug ddd :- :void + [] + ((fn- :- :int + [a :- :long] + (+ a 40 520.0)) + 15)) + + ;; Anonymous function. + :fn + (let [meth (first (:methods v)) + {:keys [params body]} meth + return-tag (or (some-> (::schema (meta (first (:form meth)))) + -adapt-type + ->name) + (some-> ^Class (:o-tag meth) + (.getName)))] + (str "^ " return-tag " " + (->> params + (mapv (fn [{:keys [tag form]}] + (str (case (.getName ^Class tag) + "[F" + "float*" + + "java.lang.Object" + (let [schema (::schema (meta form))] + (-adapt-type schema)) + + tag) + " " + (->name form)))) + (str/join ", ") + parens) + " {\n" + + ;; Add `return` only to the last expression (if applicable). + (if (= return-tag "void") + (emit body) + (str "\nreturn\n ({" (emit body) ";})")) + ";" + "\n}")) + + #_(do (def v v) + v) + #_(format "^ int () { return %s ;}" + (emit (:body (first (:methods v))))) + ;; ^ void () { printf(\"test\"); } ; + ;; __auto_type dddd = ^ void () { printf(\"test\"); } ; + :map (format "{%s}" (->> (mapv (fn [k v] @@ -892,6 +913,9 @@ signal(SIGSEGV, sighandler); (symbol? (:val v)) (->name (:val v)) + (float? (:val v)) + (str (:val v) "f") + :else (case (:val v) true 1 @@ -1097,6 +1121,17 @@ signal(SIGSEGV, sighandler); (mapv emit) (str/join ", ")))) + :prim-invoke + (format "(%s)(%s)" + (emit (:fn v)) + (->> (:args v) + (mapv emit) + (str/join ", "))) + + + :with-meta + (emit (:expr v)) + :var (let [my-var (:var v) var-value @my-var @@ -1188,7 +1223,7 @@ signal(SIGSEGV, sighandler); (throw e)) (let [error-map (merge {:ns *ns* - :transpilation *transpilation* + #_ #_:transpilation *transpilation* :raw-forms (:raw-forms v) :form (:form v) :metadata (:metadata v) @@ -1204,11 +1239,10 @@ signal(SIGSEGV, sighandler); (tap> {:label "Error when transpiling to C" :error error-map}) - (try - (let [{:keys [file line column]} (:metadata (ex-data e))] - (throw (clojure.lang.Compiler$CompilerException. file line column e))) - (catch Exception _e - (throw (ex-info "Error when transpiling to C" error-map)))))))) + (let [{:keys [file line column]} (:metadata (ex-data e))] + (throw (clojure.lang.Compiler$CompilerException. file line column e))) + #_(catch Exception _e + (throw (ex-info "Error when transpiling to C" error-map))))))) (defn- adapt-schema [schema] @@ -1466,7 +1500,7 @@ long long int: \"long long int\", unsigned long long int: \"unsigned long long i ([code-form {:keys [sym-meta sym sym-name] :as opts}] (let [{:keys [c-code ::c-data form-hash final-form init-struct-val]} (-> code-form - (transpile (assoc opts ::version 54))) + (transpile (assoc opts ::version 55))) obj-name (str "vybe_" sym-name "_" (when (or (:no-cache sym-meta) @@ -1842,6 +1876,13 @@ long long int: \"long long int\", unsigned long long int: \"unsigned long long i #_ (-> (find-symbol eita `eita__init) (vp/c-fn [:fn :void [:some_struct [:* :void]]])) +(defmacro fn- + {:clj-kondo/lint-as 'schema.core/fn} + [_ ret-schema & [args & fn-tail]] + `(fn ~(with-meta (adapt-fn-args args) + (adapt-schema ret-schema)) + ~@fn-tail)) + (defn p->fn "Convert a pointer (mem segment) so it can be called as a VybeCFn." @@ -2013,6 +2054,18 @@ long long int: \"long long int\", unsigned long long int: \"unsigned long long i [v c] v) +(defn ^:no-ns bs_lower_bound + "It works only in C for now. + + Using `eval*` + + (vc/eval* + (vc/bs_lower_bound (-> (vc/comptime (mapv float [1.0 2.0 4.0 5.0 5.5])) + (vp/as [:vec :float])) + 5 + 5.4))" + [arr n v]) + (defmethod c-macroexpand #'cast* [{:keys [args]}] `(let [v# ~(first args)] @@ -2043,8 +2096,7 @@ long long int: \"long long int\", unsigned long long int: \"unsigned long long i ^:no-ns zapgremlins) (declare ^:no-ns malloc ^:no-ns calloc - ^:no-ns free - ^:no-ns bs_lower_bound) + ^:no-ns free) (defmethod c-invoke #'printf [node] diff --git a/src/vybe/game/system.clj b/src/vybe/game/system.clj index 69db64fb..a321c976 100644 --- a/src/vybe/game/system.clj +++ b/src/vybe/game/system.clj @@ -156,7 +156,7 @@ (when-not raycast [:vg/raycast :vg/enabled])]}))) -(vf/defsystem-c ^:debug update-physics-2 w +(vf/defsystem-c update-physics-2 w [ ;; TODO Derive it from transform-global. scale vt/Scale {aabb-min :min aabb-max :max} vt/Aabb @@ -173,56 +173,67 @@ ;; TODO `e` should be a `VybeFlecsEntitySet` instead of a `long`. e :vf/entity it :vf/iter] - #_(let [half #(max (/ (- (% aabb-max) - (% aabb-min)) - 2.0) - 0.1) - center #(+ (* (/ (+ (% aabb-max) - (% aabb-min)) - 2.0))) - scaled #(* (half %) 2 (scale %)) - {:keys [x y z]} (vm/matrix->translation - (-> (vr.c/matrix-translate (center :x) (center :y) (center :z)) - (vr.c/matrix-multiply transform-global))) - body (if vy-body - (do (when kinematic - #_(println :KINEMATIC (matrix->rotation transform-global)) - (vj/move vy-body (vt/Vector3 [x y z]) (vm/matrix->rotation transform-global) (:delta_time it))) - vy-body) - (let [body (vj/body-add phys (vj/BodyCreationSettings - (cond-> {:position #_(vt/Vector4 [0 0 0 1]) - (vt/Vector4 [x y z 1]) - :rotation #_(vt/Rotation [0 0 0 1]) - (vm/matrix->rotation transform-global) - :shape (vj/box (vj/HalfExtent [(half :x) (half :y) (half :z)]) - scale - #_(vt/Vector4 [x y z 1]) - #_(vt/Translation [0 0 0]) - #_(matrix->rotation transform-global))} - kinematic - (assoc :motion_type (jolt/JPC_MOTION_TYPE_KINEMATIC)) - - sensor - (assoc :is_sensor true) - - dynamic - (assoc :motion_type (jolt/JPC_MOTION_TYPE_DYNAMIC) - :object_layer :vj.layer/moving))))] - (when (= (vf/get-name e) (vf/path [:my/model :vg.gltf/my-cube])) - #_(clojure.pprint/pprint (-> (vj/-body-get phys (:id body)) - :motion_properties - #_(vp/p->map vj/MotionProperties)))) - body)) - {:keys [mesh material]} (when-not vy-body - (gen-cube {:x (scaled :x) :y (scaled :y) :z (scaled :z)} - (rand-int 10)))] - (merge w {(body-path body) - [:vg/debug mesh material phys body - (vt/Eid e)] - - e [phys body - (when-not raycast - [:vg/raycast :vg/enabled])]}))) + (let [half (vc/fn- :- :float + [choice :- :int] + (let [diff (cond + (= choice 0) + (- (:x aabb-max) + (:x aabb-min)) + + (= choice 1) + (- (:y aabb-max) + (:y aabb-min)) + + (= choice 2) + (- (:z aabb-max) + (:z aabb-min)))] + (max (/ diff 2.0) 0.1))) + #_ #_center #(+ (* (/ (+ (% aabb-max) + (% aabb-min)) + 2.0))) + #_ #_scaled #(* (half %) 2 (scale %)) + #_ #_{:keys [x y z]} (vm/matrix->translation + (-> (vr.c/matrix-translate (center :x) (center :y) (center :z)) + (vr.c/matrix-multiply transform-global))) + #_ #_body (if vy-body + (do (when kinematic + #_(println :KINEMATIC (matrix->rotation transform-global)) + (vj/move vy-body (vt/Vector3 [x y z]) (vm/matrix->rotation transform-global) (:delta_time it))) + vy-body) + (let [body (vj/body-add phys (vj/BodyCreationSettings + (cond-> {:position #_(vt/Vector4 [0 0 0 1]) + (vt/Vector4 [x y z 1]) + :rotation #_(vt/Rotation [0 0 0 1]) + (vm/matrix->rotation transform-global) + :shape (vj/box (vj/HalfExtent [(half :x) (half :y) (half :z)]) + scale + #_(vt/Vector4 [x y z 1]) + #_(vt/Translation [0 0 0]) + #_(matrix->rotation transform-global))} + kinematic + (assoc :motion_type (jolt/JPC_MOTION_TYPE_KINEMATIC)) + + sensor + (assoc :is_sensor true) + + dynamic + (assoc :motion_type (jolt/JPC_MOTION_TYPE_DYNAMIC) + :object_layer :vj.layer/moving))))] + (when (= (vf/get-name e) (vf/path [:my/model :vg.gltf/my-cube])) + #_(clojure.pprint/pprint (-> (vj/-body-get phys (:id body)) + :motion_properties + #_(vp/p->map vj/MotionProperties)))) + body)) + #_ #_ {:keys [mesh material]} (when-not vy-body + (gen-cube {:x (scaled :x) :y (scaled :y) :z (scaled :z)} + (rand-int 10)))] + #_(merge w {(body-path body) + [:vg/debug mesh material phys body + (vt/Eid e)] + + e [phys body + (when-not raycast + [:vg/raycast :vg/enabled])]}))) (vf/defobserver body-removed w [:vf/events #{:remove} diff --git a/todo.md b/todo.md index 212a61b2..804d8d25 100644 --- a/todo.md +++ b/todo.md @@ -314,6 +314,8 @@ - [x] rotation - [x] use lerp - [ ] move `update-physics` system + - [ ] support anon functions using clang blocks + - __auto_type dddd = ^ void () { printf(\"test\"); } ; dddd(); - [ ] built-in models - [x] minimal - [ ] more complex