Browse Source

Added unfortunate hack for introspection

Rather than setting the field-type-metadata in the initializer, set it
in an introspection runtime fixup function. This is necessary
especially when metadata references a type in another file. I'm not
happy with this, but I want to move forwards with my project that
depends on Introspection.
Macoy Madson 10 months ago
  1. 110


@ -110,6 +110,13 @@
(when (= -1 start-members)
(return false))
(defstruct non-constant-field-data
field-metadata-struct-name Token
field-index int)
(var non-constant-fields (template (in std vector) non-constant-field-data))
(var field-index int 0)
(each-token-argument-in tokens start-members end-token-index i
(var name-token (addr (const Token))
(addr (at i tokens)))
@ -128,10 +135,10 @@
(var tags-tokens (template (in std vector) Token))
(call-on resize tags-tokens (introspect-get-num-tags))
(each-in-range (call-on size tags-tokens) i
(set (at i tags-tokens) (deref type-token))
(set (field (at i tags-tokens) type) TokenType_Symbol)
(set (field (at i tags-tokens) contents) "null"))
(each-in-range (call-on size tags-tokens) tag-index
(set (at tag-index tags-tokens) (deref type-token))
(set (field (at tag-index tags-tokens) type) TokenType_Symbol)
(set (field (at tag-index tags-tokens) contents) "null"))
(var next-free-tag-token int 0)
(when (= TokenType_OpenParen (path annotations-token > type))
@ -242,7 +249,11 @@
type-metadata-pointer-name (sizeof type-metadata-pointer-name)
(call-on c_str (path core-type-token > contents)))
(set (field field-type-metadata-token contents) type-metadata-pointer-name))
(set (field field-type-metadata-token contents) type-metadata-pointer-name)
(var new-non-const-field non-constant-field-data)
(set (field new-non-const-field field-metadata-struct-name) field-type-metadata-token)
(set (field new-non-const-field field-index) field-index)
(call-on push_back non-constant-fields new-non-const-field))
(var field-count Token (deref core-type-token))
(unless array-count-token
@ -251,7 +262,10 @@
(set array-count-token (addr field-count)))
(var field-type-metadata-reference (template (in std vector) Token))
(if (call-on empty (field field-type-metadata-token contents))
;; This used to output the type metadata struct pointer, but when fields reference types in
;; other modules, that causes a non-const initializer, which is not allowed in C. Now, all
;; metadata struct pointers will be set in introspect-initialize at runtime.
(if (or true (call-on empty (field field-type-metadata-token contents)))
(tokenize-push field-type-metadata-reference null)
(tokenize-push field-type-metadata-reference
(token-splice-addr field-type-metadata-token)))
@ -275,7 +289,8 @@
(offsetof (type (token-splice struct-name)) (token-splice name-token))
(token-splice-array field-type-element-size)
(token-splice array-count-token)
(array (token-splice-array tags-tokens)))))
(array (token-splice-array tags-tokens))))
(incr field-index))
;; Output regular struct fields
(PushBackTokenExpression (deref processed-arguments) name-token)
@ -313,8 +328,13 @@
(defstruct (token-splice struct-name)
(token-splice-array (deref processed-arguments)))
(var (token-splice-addr metadata-fields-name) (const (array metadata-field))
(array (token-splice-array (deref fields-metadata))))
(forward-declare (struct metadata-field))
;; This is a hidden global so Introspection.cake can access it, but no other modules should have
;; easy access without the programmer going out of their way to expose it.
(token-splice-addr metadata-fields-name)
(array metadata-field)
(array (token-splice-array (deref fields-metadata))))
(var (token-splice-addr metadata-name) (const metadata-struct)
(array (token-splice-addr struct-name-to-str)
(token-splice-addr metadata-fields-name)
@ -324,7 +344,25 @@
;; Allow access to the metadata without having to declare all the types in the header
(forward-declare (struct metadata-struct)) ;; TODO Would be nice to not do this for every struct
(var-global (token-splice-addr metadata-pointer-name) (const (addr (const metadata-struct)))
(addr (token-splice-addr metadata-name))))
(addr (token-splice-addr metadata-name))))
;; Non-constant fields must be set at runtime
(unless (call-on empty non-constant-fields)
(get-or-create-comptime-var environment runtime-fixup (template (in std vector) Token))
(tokenize-push (deref runtime-fixup)
(declare-external (var (token-splice-addr metadata-fields-name) (array metadata-field))))
(each-in-range (call-on size non-constant-fields) non-const-field-index
(var non-const-field (addr non-constant-field-data)
(addr (at non-const-field-index non-constant-fields)))
(var field-index-token Token (path non-const-field > field-metadata-struct-name))
(token-contents-snprintf field-index-token "%d" (path non-const-field > field-index))
(tokenize-push (deref runtime-fixup)
(declare-external (var (token-splice-addr (path non-const-field > field-metadata-struct-name))
(addr (const metadata-struct))))
(set (field (at (token-splice-addr field-index-token) (token-splice-addr metadata-fields-name))
(token-splice-addr (path non-const-field > field-metadata-struct-name))))))
(return true))
;; TODO: This is a limitation of not being able to declare and reference new types in comptime
@ -704,6 +742,58 @@
(add-compile-time-hook post-references-resolved introspect-overrides-install)
(defun introspect-fixup-runtime-pointers ())
(defmacro introspect-initialize ()
(get-or-create-comptime-var environment introspect-initialize-called bool false)
(set (deref introspect-initialize-called) true)
(tokenize-push output (introspect-fixup-runtime-pointers))
(return true))
(defun-comptime introspect-runtime-fixup-install (environment (ref EvaluatorEnvironment)
&return bool)
;; TODO: Validate the user calls the fixup function much like data-bundle
(get-or-create-comptime-var environment runtime-fixup (template (in std vector) Token))
(get-or-create-comptime-var environment num-runtime-fixups-installed int)
(when (= (deref num-runtime-fixups-installed) (call-on-ptr size runtime-fixup))
(return true))
(set (deref num-runtime-fixups-installed) (call-on-ptr size runtime-fixup))
(var runtime-fixup-function (addr (template (in std vector) Token))
(new (template (in std vector) Token)))
;; Environment will handle freeing tokens for us
(call-on push_back (field environment comptimeTokens) runtime-fixup-function)
(tokenize-push (deref runtime-fixup-function)
(defun introspect-fixup-runtime-pointers ()
(token-splice-array (deref runtime-fixup))))
(unless (ReplaceAndEvaluateDefinition
(deref runtime-fixup-function))
(return false))
(return true))
(add-compile-time-hook post-references-resolved introspect-runtime-fixup-install)
(defun-comptime introspect-check-initialize-called (manager (ref ModuleManager)
module (addr Module)
&return bool)
(field manager environment)
num-runtime-fixups-installed int)
(unless (deref num-runtime-fixups-installed)
;; No reason to call introspect-initialize because no fixups are necessary
(return true))
(field manager environment)
introspect-initialize-called bool false)
(unless (deref introspect-initialize-called)
(Log "error: call (introspect-initialize) somewhere in your program initialization in " \
"order to properly set introspection metadata.\n")
(return false))
(return true))
(add-compile-time-hook-module pre-build introspect-check-initialize-called)
;; Types