make-sod-slot-initarg generic
make-sod-slot-initarg-using-slot generic
make-sod-user-initarg generic
+ make-static-instance generic
sod-initarg-argument generic
sod-message-method-class generic
class-output.lisp
*instance-class* variable
+ *static-instance* variable
+ declare-static-instance generic
emit-class-conversion-macro generic
emit-class-object-decl generic
emit-class-typedef generic
emit-message-macro generic
emit-message-macro-defn generic
+ output-static-instance-initializer generic
class-utilities.lisp
argument-lists-compatible-p function
sod-slot-name generic
sod-slot-type generic
sod-user-initarg class
+ static-instance class
+ static-instance-class generic
+ static-instance-const-p generic
+ static-instance-extern-p generic
+ static-instance-initializers generic setf-generic
+ static-instance-name generic
codegen-impl.lisp
codegen class
delegating-direct-method
sod-slot
sod-class-slot
+ static-instance
temporary-name
temporary-argument
temporary-function
sod-class
compute-vtmsgs
sod-class sod-class sod-class sod-class
+declare-static-instance
+ t t
decode-property
cl:character
cl:cons
sod-message
sod-method
sod-slot
+ static-instance
finalize-module
module
finalize-sod-class
code-fragment-item t t
delegating-direct-method (eql :c) t
effective-slot (eql cl:class) t
+ effective-slot (eql static-instance) t
ichain (eql :h) t
ichain (eql cl:class) t
ichain (eql ilayout) t
+ ichain (eql static-instance) t
ichain t t [:after]
ilayout (eql :h) t [:after]
ilayout (eql :h) t
ilayout t t [:after]
islots (eql :h) t
islots (eql cl:class) t
+ islots (eql static-instance) t
islots t t [:after]
method-entry (eql :c) t
method-entry (eql vtmsgs) t
sod-class (eql :c) t
sod-class (eql :h) t [:after]
sod-class (eql :h) t
+ sod-class (eql static-instance) t
sod-class t t [:after]
sod-class-effective-slot (eql cl:class) t
sod-method (eql :c) t
sod-method (eql :h) t
sod-slot (eql islots) t
+ static-instance (eql :c) t [:after]
+ static-instance (eql :c) t
+ static-instance (eql :h) t
vtable (eql :c) t
vtable (eql :h) t
vtable t t [:after]
vtable-pointer (eql :h) t
vtable-pointer (eql cl:class) t
+ vtable-pointer (eql static-instance) t
vtmsgs (eql :c) t
vtmsgs (eql :h) t
vtmsgs (eql vtmsgs) t
sod-class t sod-slot t
make-sod-user-initarg
sod-class t t t
+make-static-instance
+ sod-class t t t t
method-entry-chain-head
method-entry
method-entry-chain-tail
module
(setf module-state)
t module
+output-static-instance-initializer
+ static-instance effective-slot t
pprint-c-storage-specifier
cl:symbol t
alignas-storage-specifier t
sod-slot t
sod-slot-initarg t
sod-user-initarg t
+ static-instance t
temporary-name t
update-inst t
var-inst t
sod-method t [:after]
sod-slot t [:after]
sod-token-scanner t [:after]
+ static-instance t [:after]
simple-method-body
aggregating-effective-method t t
sod::lifecycle-effective-method t t
sod-class-slot
sod-slot-type
sod-slot
+static-instance-class
+ static-instance
+static-instance-const-p
+ static-instance
+static-instance-extern-p
+ static-instance
+static-instance-initializers
+ static-instance
+(setf static-instance-initializers)
+ t static-instance
+static-instance-name
+ static-instance
temp-tag
temporary-name
temporary-var
sod:sod-message
sod:sod-method
sod:sod-slot
+ sod:static-instance
character-scanner
charbuf-scanner-place
condition-with-location
{check-method-argument-lists @<method-type> @<message-type>}
\end{describe}
+\begin{describe}{cls}
+ {static-instance ()
+ \&key :name :location :externp :constp :class :initializers}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{gf}{static-instance-name @<static-instance> @> @<string>}
+ \dhead{gf}{static-instance-extern-p @<static-instance>
+ @> @<generalized-boolean>}
+ \dhead{gf}{static-instance-const-p @<static-instance>
+ @> @<generalized-boolean>}
+ \dhead{gf}{static-instance-class @<static-instance> @> @<class>}
+ \dhead{gf}{static-instance-initializers @<static-instance> @> @<list>}
+ \dhead{gf}
+ {setf (static-instance-initializers @<static-instance>) @<list>}}
+\end{describe*}
+
+\begin{describe}{gf}
+ {make-static-instance @<class> @<name> @<initializers>
+ @<pset> @<location> \&key
+ \nlret @<static-instance>}
+\end{describe}
+
%%%--------------------------------------------------------------------------
\section{Class finalization protocol} \label{sec:meta.finalization}
%
(:classes :end) \\ \hlx{v/}
%
+ (:static-instances :start) & static-instance, :h
+ & \begin{nprog} \banner{Public static instances} \\ \end{nprog}
+ \\*\hlx{v}
+ :static-instances & static-instance, :h
+ & \begin{nprog}
+ extern $[@"const"]$ struct @<class>{}__ilayout
+ @<inst>{}__instance; \\
+ \#define @<inst> (\&@<inst>{}__instance.@<h>.@<c>)
+ \end{nprog} \\*
+ (:static-instances :end) & static-instance, :h
+ & \\ \hlx{v/}
+ %
(:user :start) \\*
:user \\*
(:user :end) \\ \hlx{v/}
:early \\*
(:early-user :end) \\ \hlx{v/}
%
+ (:static-instances :start) & static-instance, :c
+ & \begin{nprog} \banner{Static instance definitions} \\ \end{nprog}
+ \\*\hlx{v}
+ (:static-instances :decls) & static-instance, :c
+ & \begin{nprog}
+ /* Forward declarations. */ \\+
+ static $[@"const"]$ struct @<class>{}__ilayout
+ @<inst>{}__instance; \\
+ \#define @<inst> (\&@<inst>{}__instance.@<h>.@<c>)
+ \end{nprog} \\*
+ (:static-instances :gap) & static-instance, :c
+ & \\
+ (@<inst> :start) & sod-class, 'static-instance
+ & \begin{nprog}
+ /* Static instance `@<inst>'. */ \\
+ $[@"static"]$ $[@"const"]$ struct @<inst>{}__ilayout
+ @<inst>{}__instance = \{
+ \end{nprog} \\*\hlx{v}
+ (@<inst> :chain @<chain-head> :start) & ichain, 'static-instance
+ & \quad \{ \{ /* @<n> ichain */ \\*
+ (@<inst> :vtable @<chain-head>) & vtable-pointer, 'static-instance
+ & \slotlabel{3}{_vt} \&@<class>{}__vtable_@<h>.@<c>, \\*
+ (@<inst> :slots @<super> :start) & islots, 'static-instance
+ & \quad\quad \{ /* Class @<super> */ \\*
+ (@<inst> :slots @<super>) & effective-slot, 'static-instance
+ & \slotlabel{4}{@<slot>} @<value>, \\*
+ (@<inst> :slots @<super> :end) & islots, 'static-instance
+ & \quad\quad \}, \\*
+ (@<inst> :chain @<chain-head> :end) & ichain, 'static-instance
+ & \quad \} \}, \\*
+ (@<inst> :end) & sod-class, 'static-instance
+ & \begin{nprog} \}; \\ \end{nprog} \\ \hlx{v/}
+ %
(:classes :start) \\*\hlx{v}
%
(@<class> :banner) & sod-class, :c
\>@<in-names> @<out-names> @<stream>}}
\end{describe*}
+\begin{describe}{var}{*static-instance*}
+\end{describe}
+
+\begin{describe}{gf}{declare-static-instance @<static-instance> @<stream>}
+\end{describe}
+
+\begin{describe}{gf}
+ {output-static-instance-initializer @<static-instance> @<effective-slot>
+ @<stream>}
+\end{describe}
+
%%%----- That's all, folks --------------------------------------------------
%%% Local variables:
elsewhere in the generated output files.
+\subsection{Static instance definitions} \label{sec:syntax.module.instance}
+
+\begin{grammar}
+<static-instance-definition> ::=
+ "instance" <identifier> <identifier>
+ @[":" <list>$[\mbox{@<instance-initializer>}]$@] ";"
+
+<instance-initializer> ::= <identifier> "." <identifier> "=" <c-fragment>
+\end{grammar}
+
+Properties:
+\begin{description}
+\item[@"extern"] A boolean flag: if true, then the instance is public, and
+ will be declared in the output header file; if false (the default), then
+ the instance is only available to code defined within the module.
+\item[@"const"] A boolean flag: if true (the default), then the instance is
+ read-only, and may end up in write-protected storage at run-time; if false,
+ then the instance will be writable.
+\end{description}
+
+
\subsection{Class definitions} \label{sec:syntax.module.class}
\begin{grammar}
(check-method-return-type-against-message type msgtype)
(check-method-argument-lists type msgtype)))
+;;;--------------------------------------------------------------------------
+;;; Static instances.
+
+(defmethod shared-initialize :after
+ ((instance static-instance) slot-names &key pset)
+ "Initialize a static instance."
+ (default-slot-from-property (instance 'externp slot-names)
+ (pset :extern :boolean)
+ nil)
+ (default-slot-from-property (instance 'constp slot-names)
+ (pset :const :boolean)
+ t))
+
+(defmethod make-static-instance ((class sod-class) name initializers
+ pset location &key)
+
+ ;; Check that the initializers are all for distinct slots.
+ (find-duplicates (lambda (initializer previous)
+ (let ((slot (sod-initializer-slot initializer)))
+ (cerror*-with-location initializer
+ "Duplicate initializer for ~
+ instance slot `~A' in ~
+ static instance `~A'"
+ slot name)
+ (info-with-location previous
+ "Previous definition was here")))
+ initializers
+ :key #'sod-initializer-slot)
+
+ ;; Ensure that every slot will have an initializer, either defined directly
+ ;; on the instance or as part of some class definition.
+ (let ((have (make-hash-table)))
+
+ ;; First, populate the hash table with all of the slots for which we have
+ ;; initializers.
+ (flet ((seen-slot-initializer (init)
+ (setf (gethash (sod-initializer-slot init) have) t)))
+ (mapc #'seen-slot-initializer
+ initializers)
+ (dolist (super (sod-class-precedence-list class))
+ (mapc #'seen-slot-initializer
+ (sod-class-instance-initializers super))))
+
+ ;; Now go through all of the slots and check that they have initializers.
+ (dolist (super (sod-class-precedence-list class))
+ (dolist (slot (sod-class-slots super))
+ (unless (gethash slot have)
+ (cerror*-with-location location
+ "No initializer for instance slot `~A', ~
+ required by static instance `~A'"
+ slot name)
+ (info-with-location slot "Slot `~A' defined here" slot)))))
+
+ ;; Make the instance.
+ (make-instance 'static-instance
+ :class class
+ :name name
+ :initializers initializers
+ :location (file-location location)
+ :pset pset))
+
;;;----- That's all, folks --------------------------------------------------
This is separated out of `shared-initialize', where it's called, so that
it can be overridden conveniently by subclasses."))
+;;;--------------------------------------------------------------------------
+;;; Static instances.
+
+(export 'make-static-instance)
+(defgeneric make-static-instance (class name initializers pset location &key)
+ (:documentation
+ "Construct a new static instance of the given CLASS.
+
+ This is the main constructor functoin for static instances. This is a
+ generic function so that the CLASS can construct static instances in a
+ special way."))
+
;;;----- That's all, folks --------------------------------------------------
(sod-class-nickname target-head)))))))
;;;--------------------------------------------------------------------------
+;;; Static instance declarations.
+
+(export 'declare-static-instance)
+(defgeneric declare-static-instance (instance stream)
+ (:documentation
+ "Write a declaration for the static INSTANCE to STREAM.
+
+ Note that, according to whether the instance is external or private, this
+ may be written as part of the `:h' or `:c' reasons."))
+(defmethod declare-static-instance (instance stream)
+ (with-slots ((class %class) name externp constp) instance
+ (format stream "~:[static~;extern~] ~:[~;const ~]struct ~
+ ~A ~A__instance;~%~
+ #define ~A (&~A__instance.~A.~A)~%"
+ externp constp (ilayout-struct-tag class) name
+ name name (sod-class-nickname (sod-class-chain-head class))
+ (sod-class-nickname class))))
+
+(defmethod hook-output
+ ((instance static-instance) (reason (eql :h)) sequencer)
+ "Write an `extern' declaration for an external static instance."
+ (with-slots (externp) instance
+ (when externp
+ (one-off-output 'static-instances-banner sequencer
+ '(:static-instances :start)
+ (lambda (stream)
+ (banner "Public static instances" stream)))
+ (one-off-output 'static-instances-end sequencer
+ '(:static-instances :end)
+ #'terpri)
+ (sequence-output (stream sequencer)
+ (:static-instances
+ (declare-static-instance instance stream))))))
+
+;;;--------------------------------------------------------------------------
;;; Implementation output.
(export '*instance-class*)
((instance :object super :slots)
(output-class-initializer slot instance stream))))))
+;;;--------------------------------------------------------------------------
+;;; Static instances.
+
+(export '*static-instance*)
+(defvar-unbound *static-instance*
+ "The static instance currently being output.
+
+ This is bound during the `hook-output' traversal of a static instance for
+ `:c', since the slots traversed need to be able to look up initializers
+ from the static instance definition.")
+
+(defmethod hook-output ((instance static-instance)
+ (reason (eql :c)) sequencer)
+ "Write a static instance definition."
+ (with-slots (externp) instance
+ (one-off-output 'static-instances-banner sequencer
+ '(:static-instances :start)
+ (lambda (stream)
+ (banner "Static instance definitions" stream)))
+ (unless externp
+ (one-off-output 'static-instances-forward sequencer
+ '(:static-instances :start)
+ (lambda (stream)
+ (format stream "/* Forward declarations. */~%")))
+ (one-off-output 'static-instances-forward-gap sequencer
+ '(:static-instances :gap)
+ #'terpri)
+ (sequence-output (stream sequencer)
+ ((:static-instances :decls)
+ (declare-static-instance instance stream))))))
+
+(defmethod hook-output ((class sod-class)
+ (reason (eql 'static-instance)) sequencer)
+ "Output the framing around a static instance initializer."
+ (let ((instance *static-instance*))
+ (with-slots ((class %class) name externp constp) instance
+ (sequence-output (stream sequencer)
+ :constraint ((:static-instances :gap)
+ (*static-instance* :start)
+ (*static-instance* :end)
+ (:static-instances :end))
+ ((*static-instance* :start)
+ (format stream "/* Static instance `~A'. */~%~
+ ~:[static ~;~]~:[~;const ~]~
+ struct ~A ~A__instance = {~%"
+ name
+ externp constp
+ (ilayout-struct-tag class) name))
+ ((*static-instance* :end)
+ (format stream "};~2%"))))))
+
+(defmethod hook-output ((ichain ichain)
+ (reason (eql 'static-instance)) sequencer)
+ "Output the initializer for an ichain."
+ (with-slots ((class %class) chain-head chain-tail) ichain
+ (sequence-output (stream sequencer)
+ :constraint ((*static-instance* :start)
+ (*static-instance* :ichain chain-head :start)
+ (*static-instance* :ichain chain-head :end)
+ (*static-instance* :end))
+ ((*static-instance* :ichain chain-head :start)
+ (format stream " { { /* ~A ichain */~%"
+ (sod-class-nickname chain-head)))
+ ((*static-instance* :ichain chain-head :end)
+ (format stream " } },~%")))))
+
+(defmethod hook-output ((islots islots)
+ (reason (eql 'static-instance)) sequencer)
+ "Initialize a static instance's slots."
+ (with-slots ((class %class)) islots
+ (let ((chain-head (sod-class-chain-head class)))
+ (sequence-output (stream sequencer)
+ :constraint
+ ((*static-instance* :ichain chain-head :start)
+ (*static-instance* :slots class :start)
+ (*static-instance* :slots class)
+ (*static-instance* :slots class :end)
+ (*static-instance* :ichain chain-head :end))
+ ((*static-instance* :slots class :start)
+ (format stream " { /* Class ~A */~%" class))
+ ((*static-instance* :slots class :end)
+ (format stream " },~%"))))))
+
+(defmethod hook-output ((vtptr vtable-pointer)
+ (reason (eql 'static-instance)) sequencer)
+ "Initialize a vtable pointer in a static instance.."
+ (with-slots ((class %class) chain-head chain-tail) vtptr
+ (sequence-output (stream sequencer)
+ :constraint ((*static-instance* :ichain chain-head :start)
+ (*static-instance* :vtable chain-head)
+ (*static-instance* :ichain chain-head :end))
+ ((*static-instance* :vtable chain-head)
+ (format stream " /* ~17@A = */ &~A.~A,~%"
+ "_vt"
+ (vtable-name class chain-head)
+ (sod-class-nickname chain-tail))))))
+
+(export 'output-static-instance-initializer)
+(defgeneric output-static-instance-initializer (instance slot stream)
+ (:documentation
+ "Output an initializer for an effective SLOT in a static INSTANCE."))
+(defmethod output-static-instance-initializer ((instance static-instance)
+ (slot effective-slot)
+ stream)
+ (let* ((direct-slot (effective-slot-direct-slot slot))
+ (init (or (find direct-slot
+ (static-instance-initializers instance)
+ :key #'sod-initializer-slot)
+ (effective-slot-initializer slot))))
+ (format stream " /* ~15@A = */ ~A,~%"
+ (sod-slot-name direct-slot)
+ (sod-initializer-value init))))
+
+(defmethod hook-output ((slot effective-slot)
+ (reason (eql 'static-instance)) sequencer)
+ "Initialize a slot in a static instance."
+ (with-slots ((class %class) initializers) *static-instance*
+ (with-slots ((dslot slot)) slot
+ (let ((super (sod-slot-class dslot))
+ (instance *static-instance*))
+ (sequence-output (stream sequencer)
+ ((instance :slots super)
+ (output-static-instance-initializer instance slot stream)))))))
+
+(defmethod hook-output :after
+ ((instance static-instance) (reason (eql :c)) sequencer)
+ (with-slots ((class %class)) instance
+ (let ((*static-instance* instance))
+ (hook-output class 'static-instance sequencer))))
+
;;;----- That's all, folks --------------------------------------------------
(sod-method-message method)
(sod-method-class method))))
+;;;--------------------------------------------------------------------------
+;;; Instances.
+
+(export '(static-instance static-instance-name static-instance-extern-p
+ static-instance-const-p static-instance-class
+ static-instance-initializers))
+(defclass static-instance ()
+ ((name :initarg :name :type string :reader static-instance-name)
+ (location :initarg :location :initform (file-location nil)
+ :type file-location :reader file-location)
+ (externp :initarg :extern :initform nil :type t
+ :reader static-instance-extern-p)
+ (constp :initarg :const :initform t :type t
+ :reader static-instance-const-p)
+ (%class :initarg :class :type sod-class :reader static-instance-class)
+ (initializers :initarg :initializers :initform nil
+ :type list :accessor static-instance-initializers))
+ (:documentation
+ "A static instance is a class instance built at (C) compile time.
+
+ The slots are as follows.
+
+ * The `name' gives the C identifier naming the instance, as a string.
+
+ * The `externp' flag is non-nil if the instance is to be visible outside
+ of the translation unit.
+
+ * The `location' states where, in the user's source, the instance was
+ defined. This gets used in error messages.
+
+ * The `class' specifies the class of the instance to construct.
+
+ * The `initializers' are a list of `sod-instance-initializer' objects
+ which override any existing slot initializers defined on the class."))
+
+(defmethod print-object ((instance static-instance) stream)
+ (with-slots (name (class %class) externp constp initializers) instance
+ (maybe-print-unreadable-object (instance stream :type t)
+ (format stream "~:[~;extern ~@_~]~:[~;const ~@_~]~A ~@_~A"
+ externp constp class name)
+ (when initializers
+ (princ ": " stream)
+ (pprint-indent :block 2 stream)
+ (let ((first t))
+ (dolist (init initializers)
+ (if first (setf first nil) (princ ", "))
+ (pprint-newline :linear stream)
+ (with-slots (slot (super %class) value) init
+ (format stream "~@<~A.~A = ~2I~@_~A~:>"
+ (sod-class-nickname super)
+ (sod-slot-name slot)
+ value))))))))
+
;;;----- That's all, folks --------------------------------------------------
(:includes :start) :includes :early-decls (:includes :end)
(:early-user :start) :early-user (:early-user :end)
(:classes :start) (:classes :end)
+ (:static-instances :start) :static-instances (:static-instances :end)
(:user :start) :user (:user :end)
(:guard :end)
:epilogue)
(:prologue
(:includes :start) :includes (:includes :end)
(:early-user :start) :early-user (:early-user :end)
+ (:static-instances :start)
+ (:static-instances :decls) (:static-instances :gap)
+ (:static-instances :end)
(:classes :start) (:classes :end)
(:user :start) :user (:user :end)
:epilogue)
(eval sexp)))))
;;;--------------------------------------------------------------------------
+;;; Static instances.
+
+(define-pluggable-parser module instance (scanner pset)
+ ;; `instance' id id list[slot-initializer] `;'
+ (with-parser-context (token-scanner-context :scanner scanner)
+ (let ((duff nil)
+ (floc nil)
+ (empty-pset (make-property-set)))
+ (parse (seq ("instance"
+ (class (seq ((class-name (must :id)))
+ (setf floc (file-location scanner))
+ (restart-case (find-sod-class class-name)
+ (continue ()
+ (setf duff t)
+ nil))))
+ (name (must :id))
+ (inits (? (seq (#\:
+ (inits (list (:min 0)
+ (seq ((nick (must :id))
+ #\.
+ (name (must :id))
+ (value
+ (parse-delimited-fragment
+ scanner #\= '(#\, #\;)
+ :keep-end t)))
+ (make-sod-instance-initializer
+ class nick name value
+ empty-pset
+ :add-to-class nil
+ :location scanner))
+ #\,)))
+ inits)))
+ #\;)
+ (unless duff
+ (acond ((find-if (lambda (item)
+ (and (typep item 'static-instance)
+ (string= (static-instance-name item)
+ name)))
+ (module-items *module*))
+ (cerror*-with-location floc
+ "Instance with name `~A' ~
+ already defined."
+ name)
+ (info-with-location (file-location it)
+ "Previous definition was ~
+ here."))
+ (t
+ (add-to-module *module*
+ (make-static-instance class name
+ inits
+ pset
+ floc))))))))))
+
+;;;--------------------------------------------------------------------------
;;; Class declarations.
(export 'class-item)
* test/bad.sod:40:11: note: Previous definition was here
* test/bad.sod:40:2: error: Duplicate primary direct method for message `void wrong.frob(void)' in classs `Wrong'
* test/bad.sod:38:2: note: Previous definition was here
-* test/bad.sod:48:29: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `{'
-* test/bad.sod:48:49: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `}'
-* test/bad.sod:49:0: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `}'
+* test/bad.sod:48:29: syntax error: Expected `class', `lisp', `load', `import', `typename', `code', `set', `instance', or `demo' but found `{'
+* test/bad.sod:48:49: syntax error: Expected `class', `lisp', `load', `import', `typename', `code', `set', `instance', or `demo' but found `}'
+* test/bad.sod:49:0: syntax error: Expected `class', `lisp', `load', `import', `typename', `code', `set', `instance', or `demo' but found `}'
* test/bad.sod:54:30: error: Type mismatch for keyword argument `x' in methods for message `void fail.badkw(?int x)' applicable to class `Arrgh'
* test/bad.sod:56:2: note: Type `double' declared in primary direct method of `Arrgh' (defined here)
* test/bad.sod:51:43: note: Type `int' declared in message definition in `Fail' (here)
* test/bad.sod:90:0: error: Class `dismissed' is incomplete
* test/bad.sod:90:0: syntax error: Expected `{' but found `;'
* test/bad.sod:90:0: syntax error: Expected `}' but found `;'
-* test/bad.sod:90:0: syntax error: Expected `class', `set', `code', `typename', `import', `load', `lisp', or `demo' but found `;'
-* sod: Finished with 38 errors
+* test/bad.sod:90:0: syntax error: Expected `class', `lisp', `load', `import', `typename', `code', `set', `instance', or `demo' but found `;'
+* test/bad.sod:93:16: error: No initializer for instance slot `int st.x', required by static instance `noinit'
+* test/bad.sod:92:43: note: Slot `int st.x' defined here
+* test/bad.sod:93:16: error: No initializer for instance slot `int st.y', required by static instance `noinit'
+* test/bad.sod:92:46: note: Slot `int st.y' defined here
+* test/bad.sod:94:43: error: Duplicate initializer for instance slot `int st.x' in static instance `dupinit'
+* test/bad.sod:94:33: note: Previous definition was here
+* sod: Finished with 41 errors
; rc = 2
class hopeful: dismissed
;
+
+[nick = st] class Static: SodObject { int x, y; }
+instance Static noinit;
+instance Static dupinit: st.x = 1, st.x = 2, st.y = 3;
DONE(3);
}
+/*----- Static instances --------------------------------------------------*/
+
+[link = SodObject, nick = st]
+class StaticObject: SodObject {
+ int x, y = 2, z = 3;
+ [readonly = t] void step() { STEP(me->st.x); }
+}
+
+[extern = t] instance StaticObject mystatic: st.x = 0, st.z = 69;
+[const = nil] instance StaticObject otherstatic: st.x = 3, st.y = 42;
+
+code c: tests {
+ prepare("static instance");
+ StaticObject_step(mystatic);
+ if (mystatic->st.y == 2) STEP(1);
+ if (mystatic->st.z == 69) STEP(2);
+ StaticObject_step(otherstatic);
+ if (otherstatic->st.y == 42) STEP(4);
+ if (otherstatic->st.z == 3) STEP(5);
+ DONE(6);
+}
+
/*----- That's all, folks -------------------------------------------------*/