mirror of
https://github.com/carp-lang/Carp.git
synced 2024-09-11 05:25:28 +03:00
* feat: 'delete' interface (deciding whether a type is managed or not) * refactor: Move implements function to Interface module * feat: Automatically implement 'delete' for types defined with `deftype` * fix: Don't implement `delete` for Pointer * refactor: Clarify `memberInfo` function * fix: Also check if function types are managed * fix: Implement 'delete' for String and StaticArray. * fix: Manage String and Pattern. Tests run! * feat: Add `managed?` primitive * docs: Note about primitiveIsManaged * test: Basic test cases for managed / nonmanaged external types * test: Make sure `managed?` primitive works * test: Inactivate sanitizer since we're creating leaks intentionally * feat: Removed 'isExternalType' function * refactor: Decide if struct member takes ref or not when printing ..based on blitable interface, and 'prn' implemntation * refactor: Use 'blit' everywhere * refactor: Implement `strTakesRefOrNot` in terms of `memberStrCallingConvention` * refactor: Use `remove` over `filter not`
67 lines
1.6 KiB
Plaintext
67 lines
1.6 KiB
Plaintext
(load-and-use Test)
|
|
|
|
(defn assert-memory-balance [state f expected-balance descr]
|
|
(do
|
|
(Debug.reset-memory-balance!)
|
|
(f)
|
|
(assert-equal state expected-balance (Debug.memory-balance) descr)))
|
|
|
|
(register-type A "void*")
|
|
(register-type B "void*")
|
|
|
|
(defmodule A
|
|
(deftemplate init (Fn [] A)
|
|
"void* $NAME()" "$DECL { return CARP_MALLOC(128); }")
|
|
|
|
(deftemplate copy (Fn [&A] A)
|
|
"void* $NAME(void **p)" "$DECL { return CARP_MALLOC(128); }")
|
|
(implements copy A.copy)
|
|
|
|
(deftemplate delete (Fn [A] ())
|
|
"void $NAME(void *p)" "$DECL { CARP_FREE(p); }")
|
|
(implements delete A.delete))
|
|
|
|
(defmodule B
|
|
(deftemplate init (Fn [] B)
|
|
"void* $NAME()" "$DECL { return CARP_MALLOC(128); }")
|
|
|
|
(deftemplate copy (Fn [&B] B)
|
|
"void* $NAME(void **p)" "$DECL { return CARP_MALLOC(128); }")
|
|
(implements copy B.copy)
|
|
|
|
;; 'B' does *not* implement delete!
|
|
;; The user would have to call delete / free on it manually to avoid a leak.
|
|
)
|
|
|
|
(defn f-a []
|
|
(let [a (A)]
|
|
()))
|
|
|
|
(defn f-b []
|
|
(let [b (B)]
|
|
()))
|
|
|
|
(defn f-copy-a []
|
|
(let [a (A)
|
|
a2 @&a]
|
|
()))
|
|
|
|
(defn f-copy-b []
|
|
(let [b (B)
|
|
b2 @&b]
|
|
()))
|
|
|
|
(eval ;; temporary workaround to force evaluation of top-level 'when'
|
|
(when (not (managed? A))
|
|
(macro-error "Fail - A should be managed.")))
|
|
|
|
(eval
|
|
(when (managed? B)
|
|
(macro-error "Fail - B should not be managed.")))
|
|
|
|
(deftest test
|
|
(assert-memory-balance test f-a 0l "f-a correct, does not leak")
|
|
(assert-memory-balance test f-b 1l "f-b correct, leaks 1 value")
|
|
(assert-memory-balance test f-copy-a 0l "f-copy-a correct, does not leak")
|
|
(assert-memory-balance test f-copy-b 2l "f-copy-b correct, leaks 2 values"))
|