Skip to content
Flecs v4.1
script.h
Go to the documentation of this file.
1/**
2 * @file addons/script.h
3 * @brief Flecs script module.
4 *
5 * For script examples, see examples/script.
6 */
7
8#ifdef FLECS_SCRIPT
9
10/**
11 * @defgroup c_addons_script Flecs script
12 * @ingroup c_addons
13 * DSL for loading scenes, assets, and configuration.
14 *
15 * @{
16 */
17
18#ifndef FLECS_META
19#define FLECS_META
20#endif
21
22#ifndef FLECS_DOC
23#define FLECS_DOC
24#endif
25
26#ifndef FLECS_PARSER
27#define FLECS_PARSER
28#endif
29
30#ifndef FLECS_SCRIPT_H
31#define FLECS_SCRIPT_H
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37#define FLECS_SCRIPT_FUNCTION_ARGS_MAX (16)
38
39/* Must be the same as EcsPrimitiveKindLast */
40#define FLECS_SCRIPT_VECTOR_FUNCTION_COUNT (18)
41
42FLECS_API
44
45/* Relationship added to entities that are created by a template body. The
46 * target of the pair is the template that declares the statement that created
47 * the entity, which for nested templates is the innermost one. The pair is
48 * added to every entity created while instantiating a template body, at any
49 * scope depth (`if`/`else`, `with`, pair scopes, `for` loops and nested entity
50 * scopes), which makes it the way to tell entities that come from a template
51 * apart from entities that are declared by a plain script statement. */
52FLECS_API
53extern ECS_DECLARE(EcsScriptTemplate);
54
55FLECS_API
56extern ECS_DECLARE(EcsScriptTemplateManual);
57
58FLECS_API
59extern ECS_DECLARE(EcsScriptTemplatePending);
60
61FLECS_API
62int ecs_script_template_update(
63 ecs_world_t *world,
64 ecs_entity_t instance,
65 ecs_entity_t template_entity);
66
67FLECS_API
69
70FLECS_API
72
73FLECS_API
75
76FLECS_API
78
79FLECS_API
80extern ECS_DECLARE(EcsScriptVectorType);
81
82/* Script template. */
83typedef struct ecs_script_template_t ecs_script_template_t;
84
85/** Script variable. */
86typedef struct ecs_script_var_t {
87 const char *name; /**< Variable name. */
88 ecs_value_t value; /**< Variable value. */
89 const ecs_type_info_t *type_info; /**< Type information. */
90 int32_t sp; /**< Stack pointer. */
91 bool is_const; /**< Whether the variable is constant. */
92 bool owned; /**< Whether the scope owns the value storage. */
94
95/** Script variable scope. */
96typedef struct ecs_script_vars_t {
97 struct ecs_script_vars_t *parent; /**< Parent variable scope. */
98 int32_t sp; /**< Stack pointer for this scope. */
99
100 ecs_hashmap_t var_index; /**< Index for variable name lookups. */
101 ecs_vec_t vars; /**< Vector of variables in this scope. */
102
103 const ecs_world_t *world; /**< The world. */
104 struct ecs_stack_t *stack; /**< Stack allocator for variable storage. */
105 ecs_stack_cursor_t *cursor; /**< Cursor into the stack allocator. */
106 ecs_allocator_t *allocator; /**< General purpose allocator. */
108
109/** Script object. */
110typedef struct ecs_script_t {
111 ecs_world_t *world; /**< The world. */
112 const char *name; /**< Script name. */
113 const char *code; /**< Script source code. */
115
116/** Runtime for executing scripts. */
118
119/** Script component.
120 * This component is added to the entities of managed scripts and templates.
121 */
122typedef struct EcsScript {
123 char *filename; /**< Script filename. */
124 char *code; /**< Script source code. */
125 char *error; /**< Set if script evaluation had errors. */
126 ecs_script_t *script; /**< Parsed script object. */
127 ecs_script_template_t *template_; /**< Only set for template scripts. */
128 ecs_vec_t observers; /**< Observers for referenced components. */
129 ecs_vec_t dyn_observers; /**< Observers for refs resolved at runtime. */
130 bool skip_unknown; /**< Skip unknown components when loading. */
131 bool ir; /**< Evaluate script with IR runtime. */
133
134/** Script function context. */
135typedef struct ecs_function_ctx_t {
136 ecs_world_t *world; /**< The world. */
137 ecs_entity_t function; /**< The function entity. */
138 ecs_entity_t entity; /**< "this" entity (for methods and async functions). */
139 void *ctx; /**< User context. */
141
142/** Script function callback. */
144 const ecs_function_ctx_t *ctx,
145 int32_t argc,
146 const ecs_value_t *argv,
147 ecs_value_t *result);
148
149/** Script vector function callback. */
151 const ecs_function_ctx_t *ctx,
152 int32_t argc,
153 const ecs_value_t *argv,
154 ecs_value_t *result,
155 int32_t elem_count);
156
157/** Function argument type. */
159 const char *name; /**< Parameter name. */
160 ecs_entity_t type; /**< Parameter type. */
162
163/** Used with ecs_script_parse() and ecs_script_eval(). */
165 ecs_script_runtime_t *runtime; /**< Reusable runtime (optional). */
166
167 /** Skip unknown identifiers. When enabled, scripts that reference unknown
168 * components, component members or functions will still load. This makes
169 * it possible to load scripts for an application without having to load
170 * the application code that registers the components used by the script.
171 *
172 * When skip_unknown is enabled:
173 * - An unresolved identifier that is used as a component or tag creates a
174 * placeholder tag entity with that (scoped) name.
175 * - A value assigned to a placeholder, to a component without reflection
176 * data, or to an unknown member is parsed and discarded.
177 * - An expression that uses an unresolved function or identifier is
178 * discarded. This includes expressions that read an unknown component
179 * (`e[Unknown]`) or an unknown member (`e[Position].unknown`), and
180 * expressions that use a variable that was itself skipped, both directly
181 * and in an interpolated string. When the expression is the condition or
182 * collection of a statement (such as `for`), the statement is skipped.
183 * - A `using` statement with an unresolved identifier is skipped.
184 * - A function with an unresolved parameter or return type is skipped,
185 * which makes calls to that function unresolved expressions.
186 * - Unresolved references in `IsA` expressions, template base types and
187 * template instantiations are still errors, as those are structural.
188 *
189 * Every skipped name is reported once with ecs_warn(). */
191
192 /** Evaluate script with the IR runtime instead of the AST interpreter. */
193 bool ir;
195
196/** Used to capture error output from script evaluation. */
198 char *error; /**< Error message, or NULL if no error. Must be freed by the application. */
199 int32_t line; /**< Line number (1-based) of first error, or 0 if not available. */
200 int32_t column; /**< Column number (1-based) of first error, or 0 if not available. */
202
203#ifdef FLECS_SCRIPT_ASYNC
204#include "script_async.h"
205#endif
206
207/** Const component.
208 * This component describes a const variable that can be used from scripts. The
209 * value of a const variable is folded into expressions that use it.
210 */
211typedef struct EcsScriptConstVar {
212 ecs_value_t value;
213 const ecs_type_info_t *type_info;
215
216/** Mut component.
217 * This component describes a mutable global variable that can be used from
218 * scripts. Unlike a const variable, the value of a mut variable is never folded
219 * into expressions, and scripts that use it are reevaluated when it changes.
220 */
221typedef struct EcsScriptMutVar {
222 ecs_value_t value;
223 const ecs_type_info_t *type_info;
225
227 ecs_entity_t return_type;
228 ecs_vec_t params; /* vec<ecs_script_parameter_t> */
230#ifdef FLECS_SCRIPT_ASYNC
231 ecs_async_function_callback_t async_callback;
232 ecs_async_function_cancel_t async_cancel;
233#endif
234 ecs_vector_function_callback_t vector_callbacks[FLECS_SCRIPT_VECTOR_FUNCTION_COUNT];
235 void *ctx;
236 void *binding_ctx;
237 ecs_ctx_free_t binding_ctx_free;
238};
239
240/** Function component.
241 * This component describes a function that can be called from a script.
242 */
244
245/** Method component.
246 * This component describes a method that can be called from a script. Methods
247 * are functions that can be called on instances of a type. A method entity is
248 * stored in the scope of the type it belongs to.
249 */
251
252/* Parsing and running scripts */
253
254/** Parse script.
255 * This operation parses a script and returns a script object upon success. To
256 * run the script, call ecs_script_eval().
257 *
258 * When the result parameter is not NULL, the script will capture errors and
259 * return them in the output struct. If result.error is set, it must be freed
260 * by the application.
261 *
262 * @param world The world.
263 * @param name Name of the script (typically a file or module name).
264 * @param code The script code.
265 * @param desc Parameters for script runtime.
266 * @param result Output of script evaluation.
267 * @return Script object if success, NULL if failed.
268*/
269FLECS_API
271 ecs_world_t *world,
272 const char *name,
273 const char *code,
274 const ecs_script_eval_desc_t *desc,
276
277/** Evaluate script.
278 * This operation evaluates (runs) a parsed script.
279 *
280 * When the result parameter is not NULL, the script will capture errors and
281 * return them in the output struct. If result.error is set, it must be freed
282 * by the application.
283 *
284 * @param script The script.
285 * @param desc Parameters for script runtime.
286 * @param result Output of script evaluation (optional).
287 * @return Zero if success, non-zero if failed.
288*/
289FLECS_API
291 const ecs_script_t *script,
292 const ecs_script_eval_desc_t *desc,
294
295/** Free script.
296 * This operation frees a script object.
297 *
298 * Templates created by the script rely upon resources in the script object,
299 * and for that reason keep the script alive until all templates created by the
300 * script are deleted.
301 *
302 * @param script The script.
303 */
304FLECS_API
307
308/** Parse script.
309 * This parses a script and instantiates the entities in the world.
310 * This operation is the equivalent to doing:
311 *
312 * @code
313 * ecs_script_t *script = ecs_script_parse(world, name, code);
314 * ecs_script_eval(script);
315 * ecs_script_free(script);
316 * @endcode
317 *
318 * @param world The world.
319 * @param name The script name (typically the file).
320 * @param code The script.
321 * @param result Output of script evaluation (optional).
322 * @return Zero if success, non-zero otherwise.
323 */
324FLECS_API
326 ecs_world_t *world,
327 const char *name,
328 const char *code,
330
331/** Parse script and evaluate with options.
332 * Same as ecs_script_run(), but accepts a descriptor that configures parsing
333 * and evaluation, such as skip_unknown or the runtime (AST or IR) to use.
334 *
335 * @param world The world.
336 * @param name The script name (typically the file).
337 * @param code The script.
338 * @param desc Parse and evaluation options (optional).
339 * @param result Output of script evaluation (optional).
340 * @return Zero if success, non-zero if failed.
341 */
342FLECS_API
344 ecs_world_t *world,
345 const char *name,
346 const char *code,
347 const ecs_script_eval_desc_t *desc,
349
350/** Parse script file.
351 * This parses a script file and instantiates the entities in the world. This
352 * operation is equivalent to loading the file contents and passing it to
353 * ecs_script_run().
354 *
355 * @param world The world.
356 * @param filename The script file name.
357 * @return Zero if success, non-zero if failed.
358 */
359FLECS_API
361 ecs_world_t *world,
362 const char *filename);
363
364/** Parse script file and evaluate with options.
365 * Same as ecs_script_run_file(), but accepts a descriptor that configures
366 * parsing and evaluation.
367 *
368 * @param world The world.
369 * @param filename The script file name.
370 * @param desc Parse and evaluation options (optional).
371 * @return Zero if success, non-zero if failed.
372 */
373FLECS_API
375 ecs_world_t *world,
376 const char *filename,
377 const ecs_script_eval_desc_t *desc);
378
379/** Convert script IR to string.
380 * Compiles the script to IR if it hasn't been compiled yet, and returns a
381 * human readable listing of the instructions.
382 *
383 * @param script The script.
384 * @return The IR listing. Must be freed with ecs_os_free.
385 */
386FLECS_API
388 const ecs_script_t *script);
389
390#ifdef FLECS_SCRIPT_IR_PROFILE
391/** Reset IR runtime profiling counters (only available when compiled with
392 * FLECS_SCRIPT_IR_PROFILE). */
393FLECS_API
394void ecs_script_ir_profile_reset(void);
395
396/** Get IR runtime profiling counters as string (only available when compiled
397 * with FLECS_SCRIPT_IR_PROFILE). Must be freed with ecs_os_free. */
398FLECS_API
399char* ecs_script_ir_profile_str(void);
400#endif
401
402/** Create runtime for script.
403 * A script runtime is a container for any data created during script
404 * evaluation. By default, calling ecs_script_run() or ecs_script_eval() will
405 * create a runtime on the spot. A runtime can be created in advance and reused
406 * across multiple script evaluations to improve performance.
407 *
408 * When scripts are evaluated on multiple threads, each thread should have its
409 * own script runtime.
410 *
411 * A script runtime must be deleted with ecs_script_runtime_free().
412 *
413 * @return A new script runtime.
414 */
415FLECS_API
417
418/** Free script runtime.
419 * This operation frees a script runtime created by ecs_script_runtime_new().
420 *
421 * @param runtime The runtime to free.
422 */
423FLECS_API
425 ecs_script_runtime_t *runtime);
426
427/** Convert script AST to string.
428 * This operation converts the script abstract syntax tree to a string, which
429 * can be used to debug a script.
430 *
431 * @param script The script.
432 * @param buf The buffer to write to.
433 * @param colors Whether to include ANSI color codes in the output.
434 * @return Zero if success, non-zero if failed.
435 */
436FLECS_API
439 ecs_strbuf_t *buf,
440 bool colors);
441
442/** Convert script AST to string.
443 * This operation converts the script abstract syntax tree to a string, which
444 * can be used to debug a script.
445 *
446 * @param script The script.
447 * @param colors Whether to include ANSI color codes in the output.
448 * @return The string if success, NULL if failed.
449 */
450FLECS_API
453 bool colors);
454
455
456/* Source preserving script edits */
457
458/** Source location of a script statement.
459 * Returned by ecs_script_entity_source(). The offset and length are byte
460 * offsets into ecs_script_t::code.
461 */
462typedef struct ecs_script_source_t {
463 int32_t offset; /**< Offset of the first character of the statement. */
464 int32_t length; /**< Number of bytes occupied by the statement. */
465 int32_t line; /**< Line of the first character (1 based). */
466 int32_t column; /**< Column of the first character (1 based). */
467 bool has_scope; /**< Whether the statement is followed by a { } scope. */
468
469 /** Set when the statement is inside the body of a `template` statement.
470 * When set, this is the template entity that the body belongs to, and the
471 * statement is shared by every instance of that template: editing it
472 * changes all instances. Zero for regular entity statements. */
475
476/** Find the statement that declares an entity.
477 * This operation returns the source location of the entity statement that
478 * declared an entity. The script must have been evaluated at least once, as
479 * the mapping from entity to statement is established during evaluation.
480 *
481 * Entities that were created by instantiating a `template` declared by this
482 * script are resolved to the statement in the template body that created them.
483 * Because a template body statement is shared by all instances of the template,
484 * the same statement is returned for every instance, and
485 * ecs_script_source_t::template_ is set to the template entity. The template
486 * must be declared by this script; when a script instantiates a template that
487 * is declared by another script (for example a template from an included file),
488 * the body entities are reported by the script that declares the template, not
489 * by the script that instantiates it.
490 *
491 * The operation returns false when the entity was not created by an entity
492 * statement of this script. This is the case for:
493 *
494 * - entities that were not created by a script
495 * - entities created by a different script (an `include` statement evaluates
496 * the included file as a separate script object, so entities created by an
497 * included file are never reported by the including script)
498 * - entities created inside a `for` loop or a function body, also when the
499 * `for` loop is part of a template body
500 * - entities created by a template body statement with a computed name
501 * - entities created by a "new" expression
502 *
503 * An entity that carries the (EcsScriptTemplate, *) pair is never reported as a
504 * plain (non-template) statement, also not by the script that instantiates the
505 * template.
506 *
507 * When an entity is declared by more than one statement, the location of the
508 * first declaration is returned.
509 *
510 * The returned offsets stay valid until the script is freed or reparsed.
511 *
512 * @param script The script.
513 * @param entity The entity to find.
514 * @param source Out parameter with the source location (optional).
515 * @return True if the entity is declared by this script, false if not.
516 */
517FLECS_API
519 const ecs_script_t *script,
520 ecs_entity_t entity,
521 ecs_script_source_t *source);
522
523/** Find the managed script that declares an entity.
524 * This operation returns the entity of the managed script (see ecs_script())
525 * whose source code contains the statement that created the entity. The
526 * returned script entity is the one to use with ecs_script_entity_source() and
527 * ecs_script_edits_new():
528 *
529 * @code
530 * ecs_entity_t s = ecs_script_entity_owner(world, e);
531 * const EcsScript *sc = ecs_get(world, s, EcsScript);
532 * ecs_script_edits_t *edits = ecs_script_edits_new(sc->script);
533 * @endcode
534 *
535 * For entities that were created by a regular entity statement this is the
536 * script that created the entity. For entities that were created by a template
537 * body this is the script that *declares* the template, which is not
538 * necessarily the script that instantiates it.
539 *
540 * The operation returns 0 when the entity is not editable, which is the case
541 * when the entity was not created by a script, when the script that created it
542 * is not managed (see ecs_script_parse()), or when the statement that created
543 * the entity cannot be attributed to the entity (see
544 * ecs_script_entity_source()).
545 *
546 * @param world The world.
547 * @param entity The entity to find.
548 * @return The managed script entity, or 0 if the entity is not editable.
549 */
550FLECS_API
552 const ecs_world_t *world,
553 ecs_entity_t entity);
554
555/** Set of pending edits for a script.
556 * See ecs_script_edits_new().
557 */
559
560/** Create an edit set for a script.
561 * An edit set collects changes that are keyed by entity id, and turns them into
562 * new script source code with ecs_script_edits_apply(). Only the edited
563 * statements change; all other text (comments, whitespace, layout, expressions,
564 * include statements) is preserved byte for byte.
565 *
566 * The script must be evaluated before edits can be added, and must outlive the
567 * edit set.
568 *
569 * Edits are resolved to a source code span when they are recorded, not when
570 * they are applied. The entity is only used to find the statement at that
571 * moment; afterwards the recorded edit no longer depends on it. This means an
572 * edit set can outlive the entities it was recorded for, but it also means
573 * that a delete must be recorded *before* the entity is deleted:
574 *
575 * @code
576 * ecs_script_edits_delete(edits, e);
577 * ecs_delete(world, e);
578 * @endcode
579 *
580 * Recording an edit for an entity that is no longer alive fails, as the
581 * statement can no longer be found.
582 *
583 * A recorded edit can be dropped again with ecs_script_edits_clear(), which
584 * makes it possible to use a single edit set as an undo/redo buffer for an
585 * editing session.
586 *
587 * An edit set must be deleted with ecs_script_edits_free().
588 *
589 * @param script The script to edit.
590 * @return A new edit set, or NULL if the script is invalid.
591 */
592FLECS_API
595
596/** Free an edit set.
597 *
598 * @param edits The edit set.
599 */
600FLECS_API
602 ecs_script_edits_t *edits);
603
604/** Set a component value on an entity.
605 * If the entity scope already contains a statement for the component, only the
606 * value expression of that statement is replaced. The style of the existing
607 * initializer is preserved:
608 *
609 * - a named initializer ("{x: 10, y: 20}") stays named
610 * - a positional initializer ("{10, 20}") stays positional
611 * - an empty initializer ("{}") becomes positional
612 * - any other value form (a plain expression, a collection initializer, a match
613 * expression) is replaced with the default serialized form
614 *
615 * All members of the component are written, in the order in which they are
616 * defined by the type. Floating point members are written as the shortest
617 * decimal string that parses back to the same value ("1.2345" for a float with
618 * value 1.2345f, "1" for a float with value 1.0f), so values roundtrip without
619 * accumulating digits.
620 *
621 * When the entity was created by a template body statement (see
622 * ecs_script_entity_source()) the statement in the template body is edited,
623 * which changes the value for every instance of the template. Any expression
624 * that the body used for the value (such as a prop or const reference) is
625 * replaced by the literal value that is passed to this operation.
626 *
627 * If the entity scope does not contain a statement for the component, a new
628 * "Component: {...}" statement is appended to the end of the entity scope,
629 * using the indentation of the other statements in the scope (or the
630 * indentation of the entity statement plus four spaces when the scope is
631 * empty). When the entity statement has no scope, a scope is added.
632 *
633 * If the entity scope contains more than one statement for the component, the
634 * last statement is replaced. If the entity is declared by more than one
635 * statement, the first declaration is edited.
636 *
637 * Only statements in the scope of the entity itself are considered. A value
638 * that the entity inherits from an enclosing `with` statement is not modified;
639 * setting such a component adds a statement to the entity scope that overrides
640 * the `with` value.
641 *
642 * The component is written with the shortest name that resolves to the same
643 * component given the `using` and `module` statements of the script.
644 *
645 * @param edits The edit set.
646 * @param entity The entity to edit.
647 * @param component The component (or pair) to set.
648 * @param value Pointer to the component value.
649 * @return Zero if success, non-zero if failed.
650 */
651FLECS_API
653 ecs_script_edits_t *edits,
654 ecs_entity_t entity,
655 ecs_id_t component,
656 const void *value);
657
658/** Set a component value on an entity from an expression string.
659 * Same as ecs_script_edits_set(), but instead of serializing a value, the
660 * provided expression is written to the script verbatim. The expression is not
661 * validated.
662 *
663 * @param edits The edit set.
664 * @param entity The entity to edit.
665 * @param component The component (or pair) to set.
666 * @param expr The value expression (for example "{10, 20}").
667 * @return Zero if success, non-zero if failed.
668 */
669FLECS_API
671 ecs_script_edits_t *edits,
672 ecs_entity_t entity,
673 ecs_id_t component,
674 const char *expr);
675
676/** Remove a component from an entity.
677 * This removes the statement that adds the component (or tag) to the entity,
678 * including the line(s) the statement occupies. If the entity scope contains
679 * more than one statement for the component, the last statement is removed.
680 *
681 * The operation returns zero when the entity does not have a statement for the
682 * component, as the resulting source has the requested state.
683 *
684 * @param edits The edit set.
685 * @param entity The entity to edit.
686 * @param component The component (or pair) to remove.
687 * @return Zero if success, non-zero if failed.
688 */
689FLECS_API
691 ecs_script_edits_t *edits,
692 ecs_entity_t entity,
693 ecs_id_t component);
694
695/** Delete an entity.
696 * This removes the entity statement, its scope, and the line(s) the statement
697 * occupies. Comments that precede the statement are preserved. A trailing
698 * comment on the last line of the statement is removed together with the line.
699 *
700 * When the removed lines are surrounded by blank lines (where the start of the
701 * file, the opening brace of the enclosing scope, the closing brace of the
702 * enclosing scope and the end of the file count as blank), one of the blank
703 * lines is removed as well, so that the statements around the deleted statement
704 * stay separated by exactly one blank line.
705 *
706 * Other edits that fall inside the span of a deleted entity (such as edits to
707 * child entities) are absorbed by the deletion.
708 *
709 * When the entity was created by a template body statement (see
710 * ecs_script_entity_source()) the statement in the template body is deleted,
711 * which removes the entity from every instance of the template.
712 *
713 * The operation only records the source code span of the statement, it does
714 * not delete the entity. The edit must be recorded while the entity is still
715 * alive; the recorded edit remains valid after the entity is deleted with
716 * ecs_delete(). See ecs_script_edits_new().
717 *
718 * @param edits The edit set.
719 * @param entity The entity to delete.
720 * @return Zero if success, non-zero if failed.
721 */
722FLECS_API
724 ecs_script_edits_t *edits,
725 ecs_entity_t entity);
726
727/** Remove a recorded edit from an edit set.
728 * Edits are keyed by entity and component. This operation removes the edit
729 * that was recorded for the provided key, which undoes the effect that the
730 * edit would have had on ecs_script_edits_apply().
731 *
732 * Pass 0 for the component to clear the edit recorded by
733 * ecs_script_edits_delete(). Pass a component (or pair) to clear the edit
734 * recorded by ecs_script_edits_set(), ecs_script_edits_set_expr() or
735 * ecs_script_edits_remove() for that component.
736 *
737 * The entity is only used as a key. It does not have to be alive, which means
738 * an edit that was recorded before the entity was deleted can still be
739 * cleared afterwards.
740 *
741 * @param edits The edit set.
742 * @param entity The entity the edit was recorded for.
743 * @param component The component the edit was recorded for, or 0 for a delete.
744 * @return Zero if an edit was removed, non-zero if no edit was recorded.
745 */
746FLECS_API
748 ecs_script_edits_t *edits,
749 ecs_entity_t entity,
750 ecs_id_t component);
751
752/** Return the number of recorded edits in an edit set.
753 * Edits are keyed by entity and component, which means that recording an edit
754 * twice for the same key does not increase the count.
755 *
756 * @param edits The edit set.
757 * @return The number of recorded edits.
758 */
759FLECS_API
761 const ecs_script_edits_t *edits);
762
763/** Apply an edit set.
764 * This operation returns new script source code with the edits applied. The
765 * operation does not modify the script or the edit set, which means that
766 * applying the same edit set twice returns the same text.
767 *
768 * The operation returns NULL when two edits overlap in a way that cannot be
769 * resolved.
770 *
771 * @param edits The edit set.
772 * @return The new source code, must be freed with ecs_os_free(). NULL if
773 * failed.
774 */
775FLECS_API
777 const ecs_script_edits_t *edits);
778
779
780/* Managed scripts (script associated with entity that outlives the function) */
781
782/** Used with ecs_script_init(). */
783typedef struct ecs_script_desc_t {
784 ecs_entity_t entity; /**< Set to customize entity handle associated with script. */
785 const char *filename; /**< Set to load script from file. */
786 const char *code; /**< Set to parse script from string. */
787 bool skip_unknown; /**< Skip unknown identifiers (see ecs_script_eval_desc_t::skip_unknown). */
788 bool ir; /**< Evaluate script with IR runtime. */
790
791/** Load managed script.
792 * A managed script tracks which entities it creates, and keeps those entities
793 * synchronized when the contents of the script are updated. When the script is
794 * updated, entities that are no longer in the new version will be deleted.
795 *
796 * This feature is experimental.
797 *
798 * @param world The world.
799 * @param desc Script descriptor.
800 * @return The script entity.
801 */
802FLECS_API
804 ecs_world_t *world,
805 const ecs_script_desc_t *desc);
806
807#define ecs_script(world, ...)\
808 ecs_script_init(world, &(ecs_script_desc_t) __VA_ARGS__)
809
810/** Update script with new code.
811 *
812 * @param world The world.
813 * @param script The script entity.
814 * @param instance A template instance (optional).
815 * @param code The script code.
816 * @return Zero if success, non-zero if failed.
817 */
818FLECS_API
820 ecs_world_t *world,
822 ecs_entity_t instance,
823 const char *code);
824
825/** Clear all entities associated with script.
826 *
827 * @param world The world.
828 * @param script The script entity.
829 * @param instance The script instance.
830 */
831FLECS_API
833 ecs_world_t *world,
835 ecs_entity_t instance);
836
837
838/* Script variables */
839
840/** Create new variable scope.
841 * Create root variable scope. A variable scope contains one or more variables.
842 * Scopes can be nested, which allows variables in different scopes to have the
843 * same name. Variables from parent scopes will be shadowed by variables in
844 * child scopes with the same name.
845 *
846 * Use the `ecs_script_vars_push()` and `ecs_script_vars_pop()` functions to
847 * push and pop variable scopes.
848 *
849 * When a variable contains allocated resources (e.g., a string), its resources
850 * will be freed when `ecs_script_vars_pop()` is called on the scope, the
851 * ecs_script_vars_t::type_info field is initialized for the variable, and
852 * `ecs_type_info_t::hooks::dtor` is set.
853 *
854 * @param world The world.
855 * @return The new root variable scope.
856 */
857FLECS_API
859 ecs_world_t *world);
860
861/** Free variable scope.
862 * Free root variable scope. The provided scope should not have a parent. This
863 * operation calls `ecs_script_vars_pop()` on the scope.
864 *
865 * @param vars The variable scope.
866 */
867FLECS_API
869 ecs_script_vars_t *vars);
870
871/** Push new variable scope.
872 *
873 * Scopes created with ecs_script_vars_push() must be cleaned up with
874 * ecs_script_vars_pop().
875 *
876 * If the stack and allocator arguments are left to NULL, their values will be
877 * copied from the parent.
878 *
879 * @param parent The parent scope (provide NULL for root scope).
880 * @return The new variable scope.
881 */
882FLECS_API
884 ecs_script_vars_t *parent);
885
886/** Pop variable scope.
887 * This frees up the resources for a variable scope. The scope must be at the
888 * top of a vars stack. Calling ecs_script_vars_pop() on a scope that is not the
889 * last scope causes undefined behavior.
890 *
891 * @param vars The scope to free.
892 * @return The parent scope.
893 */
894FLECS_API
896 ecs_script_vars_t *vars);
897
898/** Declare a variable.
899 * This operation declares a new variable in the current scope. If a variable
900 * with the specified name already exists, the operation will fail.
901 *
902 * This operation does not allocate storage for the variable. This is done to
903 * allow for variables that point to existing storage, which prevents having
904 * to copy existing values to a variable scope.
905 *
906 * @param vars The variable scope.
907 * @param name The variable name.
908 * @return The new variable, or NULL if the operation failed.
909 */
910FLECS_API
912 ecs_script_vars_t *vars,
913 const char *name);
914
915/** Define a variable.
916 * This operation calls `ecs_script_vars_declare()` and allocates storage for
917 * the variable. If the type has a ctor, it will be called on the new storage.
918 *
919 * The scope's stack allocator will be used to allocate the storage. After
920 * `ecs_script_vars_pop()` is called on the scope, the variable storage will no
921 * longer be valid.
922 *
923 * The operation will fail if the type argument is not a type.
924 *
925 * @param vars The variable scope.
926 * @param name The variable name.
927 * @param type The variable type.
928 * @return The new variable, or NULL if the operation failed.
929 */
930FLECS_API
932 ecs_script_vars_t *vars,
933 const char *name,
934 ecs_entity_t type);
935
936#define ecs_script_vars_define(vars, name, type)\
937 ecs_script_vars_define_id(vars, name, ecs_id(type))
938
939/** Lookup a variable.
940 * This operation looks up a variable in the current scope. If the variable
941 * can't be found in the current scope, the operation will recursively search
942 * the parent scopes.
943 *
944 * @param vars The variable scope.
945 * @param name The variable name.
946 * @return The variable, or NULL if one with the provided name does not exist.
947 */
948FLECS_API
950 const ecs_script_vars_t *vars,
951 const char *name);
952
953/** Lookup a variable by stack pointer.
954 * This operation provides a faster way to lookup variables that are always
955 * declared in the same order in a ecs_script_vars_t scope.
956 *
957 * The stack pointer of a variable can be obtained from the ecs_script_var_t
958 * type. The provided frame offset must be valid for the provided variable
959 * stack. If the frame offset is not valid, this operation will panic.
960 *
961 * @param vars The variable scope.
962 * @param sp The stack pointer to the variable.
963 * @return The variable.
964 */
965FLECS_API
967 const ecs_script_vars_t *vars,
968 int32_t sp);
969
970/** Print variables.
971 * This operation prints all variables in the vars scope and parent scopes.
972 *
973 * @param vars The variable scope.
974 */
975FLECS_API
977 const ecs_script_vars_t *vars);
978
979/** Preallocate space for variables.
980 * This operation preallocates space for the specified number of variables. This
981 * is a performance optimization only, and is not necessary before declaring
982 * variables in a scope.
983 *
984 * @param vars The variable scope.
985 * @param count The number of variables to preallocate space for.
986 */
987FLECS_API
989 ecs_script_vars_t *vars,
990 int32_t count);
991
992/** Convert iterator to vars.
993 * This operation converts an iterator to a variable array. This allows for
994 * using iterator results in expressions. The operation only converts a
995 * single result at a time, and does not progress the iterator.
996 *
997 * Iterator fields with data will be made available as variables with as name
998 * the field index (e.g., "$1"). The operation does not check if reflection data
999 * is registered for a field type. If no reflection data is registered for the
1000 * type, using the field variable in expressions will fail.
1001 *
1002 * Field variables will only contain single elements, even if the iterator
1003 * returns component arrays. The offset parameter can be used to specify which
1004 * element in the component arrays to return. The offset parameter must be
1005 * smaller than it->count.
1006 *
1007 * The operation will create a variable for query variables that contain a
1008 * single entity.
1009 *
1010 * The operation will attempt to use existing variables. If a variable does not
1011 * yet exist, the operation will create it. If an existing variable exists with
1012 * a mismatching type, the operation will fail.
1013 *
1014 * Accessing variables after progressing the iterator or after the iterator is
1015 * destroyed will result in undefined behavior.
1016 *
1017 * If vars contains a variable that is not present in the iterator, the variable
1018 * will not be modified.
1019 *
1020 * @param it The iterator to convert to variables.
1021 * @param vars The variables to write to.
1022 * @param offset The offset to the current element.
1023 */
1024FLECS_API
1026 const ecs_iter_t *it,
1027 ecs_script_vars_t *vars,
1028 int offset);
1029
1030
1031/* Standalone expression evaluation */
1032
1033/** Used with ecs_expr_run(). */
1034typedef struct ecs_expr_eval_desc_t {
1035 const char *name; /**< Script name. */
1036 const char *expr; /**< Full expression string. */
1037 const ecs_script_vars_t *vars; /**< Variables accessible in expression. */
1038 ecs_entity_t type; /**< Type of parsed value (optional). */
1039 ecs_entity_t (*lookup_action)( /**< Function for resolving entity identifiers. */
1040 const ecs_world_t*,
1041 const char *value,
1042 void *ctx);
1043 void *lookup_ctx; /**< Context passed to lookup function. */
1044
1045 /** Disable constant folding (slower evaluation, faster parsing). */
1047
1048 /** This option instructs the expression runtime to lookup variables by
1049 * stack pointer instead of by name, which improves performance. Only enable
1050 * when provided variables are always declared in the same order. */
1052
1053 /** Allow for unresolved identifiers when parsing. Useful when entities can
1054 * be created in between parsing and evaluating. */
1056
1057 ecs_script_runtime_t *runtime; /**< Reusable runtime (optional). */
1058
1059 void *script_visitor; /**< For internal usage. */
1061
1062/** Run expression.
1063 * This operation runs an expression and stores the result in the provided
1064 * value. If the value contains a type that is different from the type of the
1065 * expression, the expression will be cast to the value.
1066 *
1067 * If the provided value for value.ptr is NULL, the value must be freed with
1068 * ecs_ptr_free() afterwards.
1069 *
1070 * @param world The world.
1071 * @param ptr The pointer to the expression to parse.
1072 * @param value The value containing type and pointer to write to.
1073 * @param desc Configuration parameters for the parser.
1074 * @return Pointer to the character after the last one read, or NULL if failed.
1075 */
1076FLECS_API
1077const char* ecs_expr_run(
1078 ecs_world_t *world,
1079 const char *ptr,
1080 ecs_value_t *value,
1081 const ecs_expr_eval_desc_t *desc);
1082
1083/** Parse expression.
1084 * This operation parses an expression and returns an object that can be
1085 * evaluated multiple times with ecs_expr_eval().
1086 *
1087 * @param world The world.
1088 * @param expr The expression string.
1089 * @param desc Configuration parameters for the parser.
1090 * @return A script object if parsing is successful, NULL if parsing failed.
1091 */
1092FLECS_API
1094 ecs_world_t *world,
1095 const char *expr,
1096 const ecs_expr_eval_desc_t *desc);
1097
1098/** Evaluate expression.
1099 * This operation evaluates an expression parsed with ecs_expr_parse()
1100 * and stores the result in the provided value. If the value contains a type
1101 * that is different from the type of the expression, the expression will be
1102 * cast to the value.
1103 *
1104 * If the provided value for value.ptr is NULL, the value must be freed with
1105 * ecs_ptr_free() afterwards.
1106 *
1107 * @param script The script containing the expression.
1108 * @param value The value in which to store the expression result.
1109 * @param desc Configuration parameters for the parser.
1110 * @return Zero if successful, non-zero if failed.
1111 */
1112FLECS_API
1114 const ecs_script_t *script,
1115 ecs_value_t *value,
1116 const ecs_expr_eval_desc_t *desc);
1117
1118/** Evaluate interpolated expressions in string.
1119 * This operation evaluates expressions in a string, and replaces them with
1120 * their evaluated result. Supported expression formats are:
1121 * - $variable_name
1122 * - {expression}
1123 *
1124 * The $, { and } characters can be escaped with a backslash (\‍).
1125 *
1126 * @param world The world.
1127 * @param str The string to evaluate.
1128 * @param vars The variables to use for evaluation.
1129 * @return String with interpolated expressions, or NULL if failed.
1130 */
1131FLECS_API
1133 ecs_world_t *world,
1134 const char *str,
1135 const ecs_script_vars_t *vars);
1136
1137
1138/* Global const variables */
1139
1140/** Used with ecs_const_var_init(). */
1141typedef struct ecs_const_var_desc_t {
1142 /** Variable name. */
1143 const char *name;
1144
1145 /** Variable parent (namespace). */
1147
1148 /** Variable type. */
1150
1151 /** Pointer to value of variable. The value will be copied to an internal
1152 * storage and does not need to be kept alive. */
1153 void *value;
1155
1156/** Create a const variable that can be accessed by scripts.
1157 *
1158 * @param world The world.
1159 * @param desc Const var parameters.
1160 * @return The const var, or 0 if failed.
1161 */
1162FLECS_API
1164 ecs_world_t *world,
1165 ecs_const_var_desc_t *desc);
1166
1167#define ecs_const_var(world, ...)\
1168 ecs_const_var_init(world, &(ecs_const_var_desc_t)__VA_ARGS__)
1169
1170
1171/** Return the value for a const variable.
1172 * This returns the value for a const variable that is created either with
1173 * ecs_const_var_init(), or in a script with "export const v = ...".
1174 *
1175 * @param world The world.
1176 * @param var The const variable.
1177 * @return The value of the const variable.
1178 */
1179FLECS_API
1181 const ecs_world_t *world,
1182 ecs_entity_t var);
1183
1184/** Return pointer to the value of a const variable.
1185 * This operation returns the value of a const variable, casted to the specified
1186 * type. If the type is equal to that of the const variable, no cast is
1187 * performed. If the variable cannot be casted to the specified type, the
1188 * operation will throw an error.
1189 *
1190 * The returned value is owned by the caller. If the returned value contains
1191 * allocated memory, this needs to be freed by the caller.
1192 *
1193 * This operation is intended to be used by the ecs_const_var_get_t macro.
1194 *
1195 * @param world The world.
1196 * @param name The name of the const variable.
1197 * @param type The requested type.
1198 * @param size The size of the requested type.
1199 * @param out Storage for the value of the const variable.
1200 * @return Pointer to the value of the const variable.
1201 */
1202FLECS_API
1204 const ecs_world_t *world,
1205 const char *name,
1206 ecs_entity_t type,
1207 ecs_size_t size,
1208 void *out);
1209
1210/** Return pointer to the value of a const variable.
1211 * This operation returns the value of a const variable, casted to the specified
1212 * type. If the type is equal to that of the const variable, no cast is
1213 * performed. If the variable cannot be casted to the specified type, the
1214 * operation will throw an error.
1215 *
1216 * The returned value is owned by the caller. If the returned value contains
1217 * allocated memory, this needs to be freed by the caller.
1218 *
1219 * When the operation fails, a zero initialized value is returned.
1220 *
1221 * @param world The world.
1222 * @param name The name of the const variable.
1223 * @param T The requested type.
1224 * @return The value of the const variable.
1225 */
1226#define ecs_const_var_get_t(world, name, T)\
1227 (*ECS_CAST(T*, ecs_const_var_get_w_type(\
1228 world, name, ecs_id(T), ECS_SIZEOF(T), &(T){0})))
1229
1230
1231/* Global mut variables */
1232
1233/** Used with ecs_mut_var_init(). */
1234typedef struct ecs_mut_var_desc_t {
1235 /** Variable name. */
1236 const char *name;
1237
1238 /** Variable parent (namespace). */
1240
1241 /** Variable type. */
1243
1244 /** Pointer to value of variable. The value will be copied to an internal
1245 * storage and does not need to be kept alive. */
1246 void *value;
1248
1249/** Create a mut variable that can be accessed by scripts.
1250 * Unlike a const variable the value of a mut variable is never folded into
1251 * expressions, which means scripts that use it are reevaluated when the value
1252 * changes.
1253 *
1254 * @param world The world.
1255 * @param desc Mut var parameters.
1256 * @return The mut var, or 0 if failed.
1257 */
1258FLECS_API
1260 ecs_world_t *world,
1261 ecs_mut_var_desc_t *desc);
1262
1263#define ecs_mut_var(world, ...)\
1264 ecs_mut_var_init(world, &(ecs_mut_var_desc_t)__VA_ARGS__)
1265
1266
1267/** Return the value for a mut variable.
1268 * This returns the value for a mut variable that is created either with
1269 * ecs_mut_var_init(), or in a script with "export mut v = ...".
1270 *
1271 * @param world The world.
1272 * @param var The mut variable.
1273 * @return The value of the mut variable.
1274 */
1275FLECS_API
1277 const ecs_world_t *world,
1278 ecs_entity_t var);
1279
1280/** Return pointer to the value of a mut variable.
1281 * This operation returns the value of a mut variable, casted to the specified
1282 * type. If the type is equal to that of the mut variable, no cast is
1283 * performed. If the variable cannot be casted to the specified type, the
1284 * operation will throw an error.
1285 *
1286 * The returned value is owned by the caller. If the returned value contains
1287 * allocated memory, this needs to be freed by the caller.
1288 *
1289 * This operation is intended to be used by the ecs_mut_var_get_t macro.
1290 *
1291 * @param world The world.
1292 * @param name The name of the mut variable.
1293 * @param type The requested type.
1294 * @param size The size of the requested type.
1295 * @param out Storage for the value of the mut variable.
1296 * @return Pointer to the value of the mut variable.
1297 */
1298FLECS_API
1300 const ecs_world_t *world,
1301 const char *name,
1302 ecs_entity_t type,
1303 ecs_size_t size,
1304 void *out);
1305
1306/** Return pointer to the value of a mut variable.
1307 * This operation returns the value of a mut variable, casted to the specified
1308 * type. If the type is equal to that of the mut variable, no cast is
1309 * performed. If the variable cannot be casted to the specified type, the
1310 * operation will throw an error.
1311 *
1312 * The returned value is owned by the caller. If the returned value contains
1313 * allocated memory, this needs to be freed by the caller.
1314 *
1315 * When the operation fails, a zero initialized value is returned.
1316 *
1317 * @param world The world.
1318 * @param name The name of the mut variable.
1319 * @param T The requested type.
1320 * @return The value of the mut variable.
1321 */
1322#define ecs_mut_var_get_t(world, name, T)\
1323 (*ECS_CAST(T*, ecs_mut_var_get_w_type(\
1324 world, name, ecs_id(T), ECS_SIZEOF(T), &(T){0})))
1325
1326/** Set the value of a mut variable.
1327 * This operation sets the value of a mut variable from a value of the
1328 * specified type. If the type is equal to that of the mut variable, no cast is
1329 * performed. If the value cannot be casted to the type of the mut variable,
1330 * the operation will throw an error.
1331 *
1332 * The provided value is copied into the storage of the mut variable and does
1333 * not need to be kept alive.
1334 *
1335 * On success, OnSet observers for the mut variable are notified, which causes
1336 * scripts that use the variable to be reevaluated.
1337 *
1338 * This operation is intended to be used by the ecs_mut_var_set_t macro.
1339 *
1340 * @param world The world.
1341 * @param name The name of the mut variable.
1342 * @param type The type of the provided value.
1343 * @param size The size of the provided type.
1344 * @param value Pointer to the value to set.
1345 * @return Zero if success, non-zero if failed.
1346 */
1347FLECS_API
1349 ecs_world_t *world,
1350 const char *name,
1351 ecs_entity_t type,
1352 ecs_size_t size,
1353 const void *value);
1354
1355/** Set the value of a mut variable.
1356 * This operation sets the value of a mut variable from a value of the
1357 * specified type. If the type is equal to that of the mut variable, no cast is
1358 * performed. If the value cannot be casted to the type of the mut variable,
1359 * the operation will throw an error.
1360 *
1361 * The provided value is copied into the storage of the mut variable and does
1362 * not need to be kept alive.
1363 *
1364 * On success, OnSet observers for the mut variable are notified, which causes
1365 * scripts that use the variable to be reevaluated.
1366 *
1367 * @param world The world.
1368 * @param name The name of the mut variable.
1369 * @param T The type of the provided value.
1370 * @return Zero if success, non-zero if failed.
1371 */
1372#define ecs_mut_var_set_t(world, name, T, ...)\
1373 ecs_mut_var_set_w_type(\
1374 world, name, ecs_id(T), ECS_SIZEOF(T), &(T)__VA_ARGS__)
1375
1376/** Mark mut var as modified.
1377 * This will notify OnSet observers.
1378 *
1379 * @param world The world.
1380 * @param var The mut variable.
1381 */
1382FLECS_API
1384 ecs_world_t *world,
1385 ecs_entity_t var);
1386
1387/* Functions */
1388
1389/** Vector function callbacks for different element types. */
1391 ecs_vector_function_callback_t i8; /**< Callback for i8 element type. */
1392 ecs_vector_function_callback_t i32; /**< Callback for i32 element type. */
1394
1395/** Used with ecs_function_init() and ecs_method_init(). */
1396typedef struct ecs_function_desc_t {
1397 /** Function name. */
1398 const char *name;
1399
1400 /** Parent of function. For methods the parent is the type for which the
1401 * method will be registered. */
1403
1404 /** Function parameters. */
1405 ecs_script_parameter_t params[FLECS_SCRIPT_FUNCTION_ARGS_MAX];
1406
1407 /** Function return type. */
1409
1410 /** Function implementation. */
1412
1413 /** Vector function implementations.
1414 * Set these callbacks if a function has one or more arguments of type
1415 * flecs.script.vector, and optionally a return type of flecs.script.vector.
1416 *
1417 * The flecs.script.vector type allows a function to be called with types
1418 * that meet the following constraints:
1419 * - The same type is provided for all arguments of type flecs.script.vector
1420 * - The provided type has one or more members of the same type
1421 * - The member type must be a primitive type
1422 * - The vector_callbacks array has an implementation for the primitive type.
1423 *
1424 * This allows for statements like:
1425 * @code
1426 * const a: Rgb = {100, 150, 250}
1427 * const b: Rgb = {10, 10, 10}
1428 * const r = lerp(a, b, 0.1)
1429 * @endcode
1430 *
1431 * which would otherwise have to be written out as:
1432 *
1433 * @code
1434 * const r: Rgb = {
1435 * lerp(a.r, b.r, 0.1),
1436 * lerp(a.g, b.g, 0.1),
1437 * lerp(a.b, b.b, 0.1)
1438 * }
1439 * @endcode
1440 *
1441 * To register vector functions, do:
1442 *
1443 * @code
1444 * ecs_function(world, {
1445 * .name = "lerp",
1446 * .return_type = EcsScriptVectorType,
1447 * .params = {
1448 * { .name = "a", .type = EcsScriptVectorType },
1449 * { .name = "b", .type = EcsScriptVectorType },
1450 * { .name = "t", .type = ecs_id(ecs_f64_t) }
1451 * },
1452 * .vector_callbacks = {
1453 * [EcsF32] = flecs_lerp32,
1454 * [EcsF64] = flecs_lerp64
1455 * }
1456 * });
1457 * @endcode
1458 *
1459 */
1460 ecs_vector_function_callback_t vector_callbacks[FLECS_SCRIPT_VECTOR_FUNCTION_COUNT];
1461
1462 /** Context passed to function implementation. */
1463 void *ctx;
1465
1466/** Create new function.
1467 * This operation creates a new function that can be called from a script.
1468 *
1469 * @param world The world.
1470 * @param desc Function init parameters.
1471 * @return The function, or 0 if failed.
1472*/
1473FLECS_API
1475 ecs_world_t *world,
1476 const ecs_function_desc_t *desc);
1477
1478#define ecs_function(world, ...)\
1479 ecs_function_init(world, &(ecs_function_desc_t)__VA_ARGS__)
1480
1481FLECS_API
1482int ecs_function_call(
1483 ecs_world_t *world,
1484 ecs_entity_t function,
1485 int32_t argc,
1486 const ecs_value_t *argv,
1487 ecs_value_t *result);
1488
1489/** Create new method.
1490 * This operation creates a new method that can be called from a script. A
1491 * method is like a function, except that it can be called on every instance of
1492 * a type.
1493 *
1494 * Methods automatically receive the instance on which the method is invoked as
1495 * first argument.
1496 *
1497 * @param world The world.
1498 * @param desc Method init parameters.
1499 * @return The method, or 0 if failed.
1500*/
1501FLECS_API
1503 ecs_world_t *world,
1504 const ecs_function_desc_t *desc);
1505
1506#define ecs_method(world, ...)\
1507 ecs_method_init(world, &(ecs_function_desc_t)__VA_ARGS__)
1508
1509FLECS_API
1510int ecs_method_call(
1511 ecs_world_t *world,
1512 ecs_entity_t method,
1513 const ecs_value_t *instance,
1514 int32_t argc,
1515 const ecs_value_t *argv,
1516 ecs_value_t *result);
1517
1518
1519/* Value serialization */
1520
1521/** Serialize value into expression string.
1522 * This operation serializes a value of the provided type to a string. The
1523 * memory pointed to must be large enough to contain a value of the used type.
1524 *
1525 * @param world The world.
1526 * @param type The type of the value to serialize.
1527 * @param data The value to serialize.
1528 * @return String with expression, or NULL if failed.
1529 */
1530FLECS_API
1532 const ecs_world_t *world,
1533 ecs_entity_t type,
1534 const void *data);
1535
1536/** Serialize value into expression buffer.
1537 * Same as ecs_ptr_to_expr(), but serializes to an ecs_strbuf_t instance.
1538 *
1539 * @param world The world.
1540 * @param type The type of the value to serialize.
1541 * @param data The value to serialize.
1542 * @param buf The strbuf to append the string to.
1543 * @return Zero if success, non-zero if failed.
1544 */
1545FLECS_API
1547 const ecs_world_t *world,
1548 ecs_entity_t type,
1549 const void *data,
1550 ecs_strbuf_t *buf);
1551
1552/** Similar to ecs_ptr_to_expr(), but serializes values to string.
1553 * Whereas the output of ecs_ptr_to_expr() is a valid expression, the output of
1554 * ecs_ptr_to_str() is a string representation of the value. In most cases the
1555 * output of the two operations is the same, but there are some differences:
1556 * - Strings are not quoted
1557 *
1558 * @param world The world.
1559 * @param type The type of the value to serialize.
1560 * @param data The value to serialize.
1561 * @return String with result, or NULL if failed.
1562 */
1563FLECS_API
1565 const ecs_world_t *world,
1566 ecs_entity_t type,
1567 const void *data);
1568
1569/** Serialize value into string buffer.
1570 * Same as ecs_ptr_to_str(), but serializes to an ecs_strbuf_t instance.
1571 *
1572 * @param world The world.
1573 * @param type The type of the value to serialize.
1574 * @param data The value to serialize.
1575 * @param buf The strbuf to append the string to.
1576 * @return Zero if success, non-zero if failed.
1577 */
1578FLECS_API
1580 const ecs_world_t *world,
1581 ecs_entity_t type,
1582 const void *data,
1583 ecs_strbuf_t *buf);
1584
1585typedef struct ecs_expr_node_t ecs_expr_node_t;
1586
1587/** Script module import function.
1588 * Usage:
1589 * @code
1590 * ECS_IMPORT(world, FlecsScript)
1591 * @endcode
1592 *
1593 * @param world The world.
1594 */
1595FLECS_API
1597 ecs_world_t *world);
1598
1599#ifdef __cplusplus
1600}
1601#endif
1602
1603#endif
1604
1605/** @} */
1606
1607#endif
FLECS_API ecs_value_t ecs_mut_var_get(const ecs_world_t *world, ecs_entity_t var)
Return the value for a mut variable.
FLECS_API void ecs_script_runtime_free(ecs_script_runtime_t *runtime)
Free script runtime.
FLECS_API int ecs_script_eval(const ecs_script_t *script, const ecs_script_eval_desc_t *desc, ecs_script_eval_result_t *result)
Evaluate script.
FLECS_API void ecs_script_vars_print(const ecs_script_vars_t *vars)
Print variables.
FLECS_API void * ecs_mut_var_get_w_type(const ecs_world_t *world, const char *name, ecs_entity_t type, ecs_size_t size, void *out)
Return pointer to the value of a mut variable.
FLECS_API void ecs_script_vars_set_size(ecs_script_vars_t *vars, int32_t count)
Preallocate space for variables.
FLECS_API bool ecs_script_entity_source(const ecs_script_t *script, ecs_entity_t entity, ecs_script_source_t *source)
Find the statement that declares an entity.
FLECS_API int ecs_script_edits_set_expr(ecs_script_edits_t *edits, ecs_entity_t entity, ecs_id_t component, const char *expr)
Set a component value on an entity from an expression string.
FLECS_API int ecs_ptr_to_expr_buf(const ecs_world_t *world, ecs_entity_t type, const void *data, ecs_strbuf_t *buf)
Serialize value into expression buffer.
struct ecs_script_edits_t ecs_script_edits_t
Set of pending edits for a script.
Definition script.h:558
FLECS_API ecs_script_t * ecs_expr_parse(ecs_world_t *world, const char *expr, const ecs_expr_eval_desc_t *desc)
Parse expression.
FLECS_API void ecs_script_vars_fini(ecs_script_vars_t *vars)
Free variable scope.
FLECS_API ecs_script_runtime_t * ecs_script_runtime_new(void)
Create runtime for script.
FLECS_API char * ecs_ptr_to_expr(const ecs_world_t *world, ecs_entity_t type, const void *data)
Serialize value into expression string.
FLECS_API int ecs_mut_var_set_w_type(ecs_world_t *world, const char *name, ecs_entity_t type, ecs_size_t size, const void *value)
Set the value of a mut variable.
FLECS_API ecs_entity_t ecs_function_init(ecs_world_t *world, const ecs_function_desc_t *desc)
Create new function.
FLECS_API char * ecs_ptr_to_str(const ecs_world_t *world, ecs_entity_t type, const void *data)
Similar to ecs_ptr_to_expr(), but serializes values to string.
struct ecs_script_function_t EcsScriptMethod
Method component.
Definition script.h:250
FLECS_API int32_t ecs_script_edits_count(const ecs_script_edits_t *edits)
Return the number of recorded edits in an edit set.
FLECS_API ecs_entity_t ecs_mut_var_init(ecs_world_t *world, ecs_mut_var_desc_t *desc)
Create a mut variable that can be accessed by scripts.
FLECS_API int ecs_script_update(ecs_world_t *world, ecs_entity_t script, ecs_entity_t instance, const char *code)
Update script with new code.
FLECS_API char * ecs_script_ast_to_str(ecs_script_t *script, bool colors)
Convert script AST to string.
FLECS_API ecs_entity_t ecs_script_init(ecs_world_t *world, const ecs_script_desc_t *desc)
Load managed script.
FLECS_API ecs_script_vars_t * ecs_script_vars_pop(ecs_script_vars_t *vars)
Pop variable scope.
FLECS_API ecs_script_var_t * ecs_script_vars_from_sp(const ecs_script_vars_t *vars, int32_t sp)
Lookup a variable by stack pointer.
FLECS_API void ecs_script_clear(ecs_world_t *world, ecs_entity_t script, ecs_entity_t instance)
Clear all entities associated with script.
FLECS_API ecs_script_var_t * ecs_script_vars_declare(ecs_script_vars_t *vars, const char *name)
Declare a variable.
FLECS_API ecs_value_t ecs_const_var_get(const ecs_world_t *world, ecs_entity_t var)
Return the value for a const variable.
FLECS_API ecs_script_var_t * ecs_script_vars_define_id(ecs_script_vars_t *vars, const char *name, ecs_entity_t type)
Define a variable.
struct ecs_script_function_t EcsScriptFunction
Function component.
Definition script.h:243
FLECS_API void * ecs_const_var_get_w_type(const ecs_world_t *world, const char *name, ecs_entity_t type, ecs_size_t size, void *out)
Return pointer to the value of a const variable.
FLECS_API int ecs_script_run_file_w_desc(ecs_world_t *world, const char *filename, const ecs_script_eval_desc_t *desc)
Parse script file and evaluate with options.
FLECS_API ecs_script_edits_t * ecs_script_edits_new(ecs_script_t *script)
Create an edit set for a script.
void(*) ecs_function_callback_t(const ecs_function_ctx_t *ctx, int32_t argc, const ecs_value_t *argv, ecs_value_t *result)
Script function callback.
Definition script.h:143
FLECS_API void ecs_script_vars_from_iter(const ecs_iter_t *it, ecs_script_vars_t *vars, int offset)
Convert iterator to vars.
FLECS_API int ecs_script_edits_clear(ecs_script_edits_t *edits, ecs_entity_t entity, ecs_id_t component)
Remove a recorded edit from an edit set.
FLECS_API void ecs_script_free(ecs_script_t *script)
Free script.
FLECS_API int ecs_script_ast_to_buf(ecs_script_t *script, ecs_strbuf_t *buf, bool colors)
Convert script AST to string.
FLECS_API ecs_entity_t ecs_method_init(ecs_world_t *world, const ecs_function_desc_t *desc)
Create new method.
FLECS_API int ecs_ptr_to_str_buf(const ecs_world_t *world, ecs_entity_t type, const void *data, ecs_strbuf_t *buf)
Serialize value into string buffer.
FLECS_API char * ecs_script_edits_apply(const ecs_script_edits_t *edits)
Apply an edit set.
FLECS_API int ecs_script_run(ecs_world_t *world, const char *name, const char *code, ecs_script_eval_result_t *result)
Parse script.
FLECS_API int ecs_script_edits_remove(ecs_script_edits_t *edits, ecs_entity_t entity, ecs_id_t component)
Remove a component from an entity.
FLECS_API ecs_script_vars_t * ecs_script_vars_init(ecs_world_t *world)
Create new variable scope.
FLECS_API int ecs_expr_eval(const ecs_script_t *script, ecs_value_t *value, const ecs_expr_eval_desc_t *desc)
Evaluate expression.
FLECS_API int ecs_script_run_w_desc(ecs_world_t *world, const char *name, const char *code, const ecs_script_eval_desc_t *desc, ecs_script_eval_result_t *result)
Parse script and evaluate with options.
FLECS_API int ecs_script_edits_delete(ecs_script_edits_t *edits, ecs_entity_t entity)
Delete an entity.
FLECS_API char * ecs_script_ir_to_str(const ecs_script_t *script)
Convert script IR to string.
FLECS_API ecs_script_vars_t * ecs_script_vars_push(ecs_script_vars_t *parent)
Push new variable scope.
FLECS_API ecs_script_t * ecs_script_parse(ecs_world_t *world, const char *name, const char *code, const ecs_script_eval_desc_t *desc, ecs_script_eval_result_t *result)
Parse script.
struct ecs_script_runtime_t ecs_script_runtime_t
Runtime for executing scripts.
Definition script.h:117
FLECS_API ecs_entity_t ecs_const_var_init(ecs_world_t *world, ecs_const_var_desc_t *desc)
Create a const variable that can be accessed by scripts.
FLECS_API void FlecsScriptImport(ecs_world_t *world)
Script module import function.
FLECS_API char * ecs_script_string_interpolate(ecs_world_t *world, const char *str, const ecs_script_vars_t *vars)
Evaluate interpolated expressions in string.
FLECS_API int ecs_script_edits_set(ecs_script_edits_t *edits, ecs_entity_t entity, ecs_id_t component, const void *value)
Set a component value on an entity.
void(*) ecs_vector_function_callback_t(const ecs_function_ctx_t *ctx, int32_t argc, const ecs_value_t *argv, ecs_value_t *result, int32_t elem_count)
Script vector function callback.
Definition script.h:150
FLECS_API int ecs_script_run_file(ecs_world_t *world, const char *filename)
Parse script file.
FLECS_API ecs_script_var_t * ecs_script_vars_lookup(const ecs_script_vars_t *vars, const char *name)
Lookup a variable.
FLECS_API void ecs_script_edits_free(ecs_script_edits_t *edits)
Free an edit set.
FLECS_API void ecs_mut_var_modified(ecs_world_t *world, ecs_entity_t var)
Mark mut var as modified.
FLECS_API ecs_entity_t ecs_script_entity_owner(const ecs_world_t *world, ecs_entity_t entity)
Find the managed script that declares an entity.
FLECS_API const char * ecs_expr_run(ecs_world_t *world, const char *ptr, ecs_value_t *value, const ecs_expr_eval_desc_t *desc)
Run expression.
ecs_id_t ecs_entity_t
An entity identifier.
Definition flecs.h:395
struct ecs_world_t ecs_world_t
A world is the container for all ECS data and supporting features.
Definition flecs.h:439
uint64_t ecs_id_t
IDs are the things that can be added to an entity.
Definition flecs.h:388
script_builder script(const char *name=nullptr) const
Build a script.
Definition mixin.inl:31
#define ECS_DECLARE(id)
Forward declare an entity, tag, prefab, or any other entity identifier.
Definition flecs_c.h:25
#define ECS_COMPONENT_DECLARE(id)
Forward declare a component.
Definition flecs_c.h:65
void(*) ecs_ctx_free_t(void *ctx)
Function to clean up context data.
Definition flecs.h:660
Async/await support for Flecs script.
Const component.
Definition script.h:211
Mut component.
Definition script.h:221
Script component.
Definition script.h:122
ecs_vec_t observers
Observers for referenced components.
Definition script.h:128
ecs_vec_t dyn_observers
Observers for refs resolved at runtime.
Definition script.h:129
ecs_script_template_t * template_
Only set for template scripts.
Definition script.h:127
char * error
Set if script evaluation had errors.
Definition script.h:125
char * code
Script source code.
Definition script.h:124
bool ir
Evaluate script with IR runtime.
Definition script.h:131
ecs_script_t * script
Parsed script object.
Definition script.h:126
char * filename
Script filename.
Definition script.h:123
bool skip_unknown
Skip unknown components when loading.
Definition script.h:130
Used with ecs_const_var_init().
Definition script.h:1141
ecs_entity_t parent
Variable parent (namespace).
Definition script.h:1146
const char * name
Variable name.
Definition script.h:1143
ecs_entity_t type
Variable type.
Definition script.h:1149
void * value
Pointer to value of variable.
Definition script.h:1153
Used with ecs_expr_run().
Definition script.h:1034
bool disable_folding
Disable constant folding (slower evaluation, faster parsing).
Definition script.h:1046
void * script_visitor
For internal usage.
Definition script.h:1059
ecs_entity_t type
Type of parsed value (optional).
Definition script.h:1038
const ecs_script_vars_t * vars
Variables accessible in expression.
Definition script.h:1037
ecs_script_runtime_t * runtime
Reusable runtime (optional).
Definition script.h:1057
bool allow_unresolved_identifiers
Allow for unresolved identifiers when parsing.
Definition script.h:1055
const char * name
Script name.
Definition script.h:1035
const char * expr
Full expression string.
Definition script.h:1036
bool disable_dynamic_variable_binding
This option instructs the expression runtime to lookup variables by stack pointer instead of by name,...
Definition script.h:1051
void * lookup_ctx
Context passed to lookup function.
Definition script.h:1043
Script function context.
Definition script.h:135
void * ctx
User context.
Definition script.h:139
ecs_entity_t function
The function entity.
Definition script.h:137
ecs_world_t * world
The world.
Definition script.h:136
ecs_entity_t entity
"this" entity (for methods and async functions).
Definition script.h:138
Used with ecs_function_init() and ecs_method_init().
Definition script.h:1396
ecs_entity_t return_type
Function return type.
Definition script.h:1408
const char * name
Function name.
Definition script.h:1398
ecs_script_parameter_t params[(16)]
Function parameters.
Definition script.h:1405
void * ctx
Context passed to function implementation.
Definition script.h:1463
ecs_function_callback_t callback
Function implementation.
Definition script.h:1411
ecs_vector_function_callback_t vector_callbacks[(18)]
Vector function implementations.
Definition script.h:1460
ecs_entity_t parent
Parent of function.
Definition script.h:1402
Iterator.
Definition flecs.h:1192
Used with ecs_mut_var_init().
Definition script.h:1234
void * value
Pointer to value of variable.
Definition script.h:1246
ecs_entity_t type
Variable type.
Definition script.h:1242
const char * name
Variable name.
Definition script.h:1236
ecs_entity_t parent
Variable parent (namespace).
Definition script.h:1239
Used with ecs_script_init().
Definition script.h:783
const char * code
Set to parse script from string.
Definition script.h:786
ecs_entity_t entity
Set to customize entity handle associated with script.
Definition script.h:784
bool skip_unknown
Skip unknown identifiers (see ecs_script_eval_desc_t::skip_unknown).
Definition script.h:787
bool ir
Evaluate script with IR runtime.
Definition script.h:788
const char * filename
Set to load script from file.
Definition script.h:785
Used with ecs_script_parse() and ecs_script_eval().
Definition script.h:164
bool ir
Evaluate script with the IR runtime instead of the AST interpreter.
Definition script.h:193
ecs_script_runtime_t * runtime
Reusable runtime (optional).
Definition script.h:165
bool skip_unknown
Skip unknown identifiers.
Definition script.h:190
Used to capture error output from script evaluation.
Definition script.h:197
char * error
Error message, or NULL if no error.
Definition script.h:198
int32_t line
Line number (1-based) of first error, or 0 if not available.
Definition script.h:199
int32_t column
Column number (1-based) of first error, or 0 if not available.
Definition script.h:200
Function argument type.
Definition script.h:158
const char * name
Parameter name.
Definition script.h:159
ecs_entity_t type
Parameter type.
Definition script.h:160
Source location of a script statement.
Definition script.h:462
int32_t line
Line of the first character (1 based).
Definition script.h:465
int32_t offset
Offset of the first character of the statement.
Definition script.h:463
bool has_scope
Whether the statement is followed by a { } scope.
Definition script.h:467
ecs_entity_t template_
Set when the statement is inside the body of a template statement.
Definition script.h:473
int32_t length
Number of bytes occupied by the statement.
Definition script.h:464
int32_t column
Column of the first character (1 based).
Definition script.h:466
Script object.
Definition script.h:110
const char * code
Script source code.
Definition script.h:113
const char * name
Script name.
Definition script.h:112
ecs_world_t * world
The world.
Definition script.h:111
Script variable.
Definition script.h:86
bool is_const
Whether the variable is constant.
Definition script.h:91
ecs_value_t value
Variable value.
Definition script.h:88
bool owned
Whether the scope owns the value storage.
Definition script.h:92
const char * name
Variable name.
Definition script.h:87
const ecs_type_info_t * type_info
Type information.
Definition script.h:89
int32_t sp
Stack pointer.
Definition script.h:90
Script variable scope.
Definition script.h:96
int32_t sp
Stack pointer for this scope.
Definition script.h:98
ecs_allocator_t * allocator
General purpose allocator.
Definition script.h:106
struct ecs_script_vars_t * parent
Parent variable scope.
Definition script.h:97
struct ecs_stack_t * stack
Stack allocator for variable storage.
Definition script.h:104
ecs_stack_cursor_t * cursor
Cursor into the stack allocator.
Definition script.h:105
ecs_hashmap_t var_index
Index for variable name lookups.
Definition script.h:100
const ecs_world_t * world
The world.
Definition script.h:103
ecs_vec_t vars
Vector of variables in this scope.
Definition script.h:101
Type that contains component information (passed to ctors/dtors/...).
Definition flecs.h:1052
Value of a dynamic type.
Definition flecs.h:1068
Vector function callbacks for different element types.
Definition script.h:1390
ecs_vector_function_callback_t i8
Callback for i8 element type.
Definition script.h:1391
ecs_vector_function_callback_t i32
Callback for i32 element type.
Definition script.h:1392