@ -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 @@
( introspect-metadata-pointer-name-from-struct-name
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.
( var-hidden-global
( 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 ) )
field-type-metadata )
( 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
environment
"introspect-fixup-runtime-pointers"
( 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 )
( get-or-create-comptime-var
( 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 ) )
( get-or-create-comptime-var
( 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
;;