diff --git a/goal_src/engine/level/level-h.gc b/goal_src/engine/level/level-h.gc index 7c6392b6a..dd43072d3 100644 --- a/goal_src/engine/level/level-h.gc +++ b/goal_src/engine/level/level-h.gc @@ -207,8 +207,6 @@ ) (define-extern *level* level-group) -;; OpenGOAL doesn not yet support setting fields to arrays in statics. -#| (if (zero? *level*) (set! *level* (new 'static 'level-group @@ -225,28 +223,28 @@ :name #f :status 'inactive :foreground-sink-group - (new 'static 'inline-array 'dma-foreground-sink-group 3 + (new 'static 'inline-array dma-foreground-sink-group 3 (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 10) (new 'static 'generic-dma-foreground-sink :bucket 11 :foreground-output-bucket 1 ) - 0) + ) ) (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 49 :foreground-texture-page 1 ) - (new 'static 'generic-dma-foreground-sink : - bucket 50 :foreground-texture-page 1 + (new 'static 'generic-dma-foreground-sink + :bucket 50 :foreground-texture-page 1 :foreground-output-bucket 1) - 0) + ) ) (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 58 :foreground-texture-page 2 @@ -256,7 +254,7 @@ :foreground-texture-page 2 :foreground-output-bucket 1 ) - 0) + ) ) ) :inside-sphere? #f @@ -269,9 +267,9 @@ :index 1 :status 'inactive :foreground-sink-group - (new 'static 'inline-array 'dma-foreground-sink-group 3 + (new 'static 'inline-array dma-foreground-sink-group 3 (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 17 :foreground-texture-level 1 @@ -281,10 +279,10 @@ :foreground-texture-level 1 :foreground-output-bucket 1 ) - 0) + ) ) (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 52 :foreground-texture-page 1 @@ -296,11 +294,11 @@ :foreground-texture-level 1 :foreground-output-bucket 1 ) - 0 + ) ) (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 61 :foreground-texture-page 2 @@ -312,7 +310,7 @@ :foreground-texture-level 1 :foreground-output-bucket 1 ) - 0) + ) ) ) :inside-sphere? #f @@ -325,9 +323,9 @@ :index 2 :status 'reserved :foreground-sink-group - (new 'static 'inline-array 'dma-foreground-sink-group 3 + (new 'static 'inline-array dma-foreground-sink-group 3 (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 45 :foreground-texture-level 2 @@ -337,25 +335,25 @@ :foreground-texture-level 2 :foreground-output-bucket 1 ) - 0) - ) - (new 'static 'dma-foreground-sink-group : - sink (new 'static 'array 'dma-foreground-sink 3 - (new 'static 'dma-foreground-sink - :bucket 55 - :foreground-texture-page 1 - :foreground-texture-level 2 - ) - (new 'static 'generic-dma-foreground-sink - :bucket 56 - :foreground-texture-page 1 - :foreground-texture-level 2 - :foreground-output-bucket 1 - ) - 0) + ) ) (new 'static 'dma-foreground-sink-group - :sink (new 'static 'array 'dma-foreground-sink 3 + :sink (new 'static 'array dma-foreground-sink 3 + (new 'static 'dma-foreground-sink + :bucket 55 + :foreground-texture-page 1 + :foreground-texture-level 2 + ) + (new 'static 'generic-dma-foreground-sink + :bucket 56 + :foreground-texture-page 1 + :foreground-texture-level 2 + :foreground-output-bucket 1 + ) + ) + ) + (new 'static 'dma-foreground-sink-group + :sink (new 'static 'array dma-foreground-sink 3 (new 'static 'dma-foreground-sink :bucket 58 :foreground-texture-page 2 @@ -367,7 +365,7 @@ :foreground-texture-level 2 :foreground-output-bucket 1 ) - 0 + ) ) ) @@ -378,5 +376,4 @@ ) ) ) -|# diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index 18edc3dcf..ed09929be 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -165,6 +165,23 @@ class Compiler { bool boxed, Env* env); + StaticResult fill_static_inline_array(const goos::Object& form, + const goos::Object& rest, + Env* env); + + void fill_static_inline_array_inline(const goos::Object& form, + const TypeSpec& content_type, + const std::vector& args, + StaticStructure* structure, + int offset, + Env* env); + void fill_static_array_inline(const goos::Object& form, + const TypeSpec& content_type, + const std::vector& args, + StaticStructure* structure, + int offset, + Env* env); + TypeSystem m_ts; std::unique_ptr m_global_env = nullptr; std::unique_ptr m_none = nullptr; diff --git a/goalc/compiler/StaticObject.cpp b/goalc/compiler/StaticObject.cpp index ed37388df..e8158799d 100644 --- a/goalc/compiler/StaticObject.cpp +++ b/goalc/compiler/StaticObject.cpp @@ -90,7 +90,7 @@ StaticObject::LoadInfo StaticStructure::get_load_info() const { } int StaticStructure::get_addr_offset() const { - return 0; + return m_offset; } void StaticStructure::generate_structure(emitter::ObjectGenerator* gen) { diff --git a/goalc/compiler/StaticObject.h b/goalc/compiler/StaticObject.h index 4d30f952b..6cb0ead2f 100644 --- a/goalc/compiler/StaticObject.h +++ b/goalc/compiler/StaticObject.h @@ -48,6 +48,7 @@ class StaticStructure : public StaticObject { void generate_structure(emitter::ObjectGenerator* gen); void generate(emitter::ObjectGenerator* gen) override; int get_addr_offset() const override; + void set_offset(int offset) { m_offset = offset; } struct SymbolRecord { int offset = -1; @@ -67,6 +68,9 @@ class StaticStructure : public StaticObject { void add_symbol_record(std::string name, int offset); void add_pointer_record(int offset_in_this, StaticStructure* dest, int offset_in_dest); void add_type_record(std::string name, int offset); + + private: + int m_offset = 0; }; class StaticBasic : public StaticStructure { diff --git a/goalc/compiler/compilation/Static.cpp b/goalc/compiler/compilation/Static.cpp index 1e60c0287..50434d9ac 100644 --- a/goalc/compiler/compilation/Static.cpp +++ b/goalc/compiler/compilation/Static.cpp @@ -78,13 +78,82 @@ void Compiler::compile_static_structure_inline(const goos::Object& form, field_name_def = field_name_def.substr(1); auto field_info = m_ts.lookup_field_info(type_info->get_name(), field_name_def); - if (field_info.field.is_dynamic() || field_info.field.is_array()) { - throw_compiler_error(form, "Static objects not yet implemented for dynamic/inline/array"); + if (field_info.field.is_dynamic()) { + throw_compiler_error(form, "Dynamic fields are not supported for inline"); } auto field_offset = field_info.field.offset() + offset; - if (is_integer(field_info.type)) { + if (field_info.field.is_array()) { + bool is_inline = field_info.field.is_inline(); + + // for an array field, we only accept (new 'static 'array ...) + if (!field_value.is_list()) { + throw_compiler_error(field_value, "Array field was not properly specified"); + } + + goos::Object constructor_args; + auto new_form = get_list_as_vector(field_value, &constructor_args, 5); + if (new_form.size() != 5) { + throw_compiler_error( + field_value, + "Array field must be defined with (new 'static ['array, 'inline-array] type-name ...)"); + } + + if (!new_form.at(0).is_symbol() || new_form.at(0).as_symbol()->name != "new") { + throw_compiler_error( + field_value, + "Array field must be defined with (new 'static ['array, 'inline-array] type-name ...)"); + } + + if (!is_quoted_sym(new_form.at(1)) || unquote(new_form.at(1)).as_symbol()->name != "static") { + throw_compiler_error( + field_value, + "Array field must be defined with (new 'static ['array, 'inline-array] type-name ...)"); + } + + if (unquote(new_form.at(2)).print() != (is_inline ? "inline-array" : "array")) { + throw_compiler_error( + field_value, + "Array field must be defined with (new 'static ['array, 'inline-array] type-name ...)"); + } + + auto array_content_type = parse_typespec(new_form.at(3)); + + if (is_inline) { + if (field_info.field.type() != array_content_type) { + throw_compiler_error(field_value, "Inline array field must have the correct type"); + } + } else { + // allow more specific types. + m_ts.typecheck(field_info.field.type(), array_content_type, "Array content type"); + } + + s64 elt_array_len; + if (!try_getting_constant_integer(new_form.at(4), &elt_array_len, env)) { + throw_compiler_error(field_value, "Array field size is invalid, got {}", + new_form.at(4).print()); + } + + if (elt_array_len != field_info.field.array_size()) { + throw_compiler_error(field_value, "Array field had an expected size of {} but got {}", + field_info.field.array_size(), elt_array_len); + } + + auto arg_list = get_list_as_vector(field_value.as_pair()->cdr); + if (((int)arg_list.size() - 5) > elt_array_len) { + throw_compiler_error(field_value, "Array field definition has too many values in it."); + } + + if (is_inline) { + fill_static_inline_array_inline(field_value, field_info.field.type(), arg_list, structure, + field_offset, env); + } else { + fill_static_array_inline(field_value, field_info.field.type(), arg_list, structure, + field_offset, env); + } + + } else if (is_integer(field_info.type)) { assert(field_info.needs_deref); // for now... auto deref_info = m_ts.get_deref_info(m_ts.make_pointer_typespec(field_info.type)); auto field_size = deref_info.load_size; @@ -162,7 +231,7 @@ void Compiler::compile_static_structure_inline(const goos::Object& form, assert(field_offset + field_size <= int(structure->data.size())); auto sr = compile_static(field_value, env); if (sr.is_symbol()) { - if (sr.symbol_name() != "#f") { + if (sr.symbol_name() != "#f" && sr.symbol_name() != "_empty_") { typecheck(form, field_info.type, sr.typespec()); } structure->add_symbol_record(sr.symbol_name(), field_offset); @@ -437,6 +506,8 @@ StaticResult Compiler::compile_static(const goos::Object& form, Env* env) { return fill_static_array(form, rest, true, env); } else if (unquote(args.at(1)).as_symbol()->name == "array") { return fill_static_array(form, rest, false, env); + } else if (unquote(args.at(1)).as_symbol()->name == "inline-array") { + return fill_static_inline_array(form, rest, env); } else { auto ts = parse_typespec(unquote(args.at(1))); if (ts == TypeSpec("string")) { @@ -485,6 +556,46 @@ StaticResult Compiler::compile_static(const goos::Object& form, Env* env) { return {}; } +void Compiler::fill_static_array_inline(const goos::Object& form, + const TypeSpec& content_type, + const std::vector& args, + StaticStructure* structure, + int offset, + Env* env) { + auto pointer_type = m_ts.make_pointer_typespec(content_type); + auto deref_info = m_ts.get_deref_info(pointer_type); + assert(deref_info.can_deref); + assert(deref_info.mem_deref); + for (size_t i = 4; i < args.size(); i++) { + int arg_idx = i - 4; + int elt_offset = offset + arg_idx * deref_info.stride; + auto sr = compile_static(args.at(i), env); + if (is_integer(content_type)) { + typecheck(form, TypeSpec("integer"), sr.typespec()); + } else { + typecheck(form, content_type, sr.typespec()); + } + if (sr.is_symbol()) { + assert(deref_info.stride == 4); + structure->add_symbol_record(sr.symbol_name(), elt_offset); + u32 symbol_placeholder = 0xffffffff; + memcpy(structure->data.data() + elt_offset, &symbol_placeholder, 4); + } else if (sr.is_reference()) { + assert(deref_info.stride == 4); + structure->add_pointer_record(elt_offset, sr.reference(), sr.reference()->get_addr_offset()); + } else if (sr.is_constant_data()) { + if (!integer_fits(sr.constant_data(), deref_info.load_size, deref_info.sign_extend)) { + throw_compiler_error(form, "The integer {} doesn't fit in element {} of array of {}", + sr.constant_data(), arg_idx, content_type.print()); + } + u64 data = sr.constant_data(); + memcpy(structure->data.data() + elt_offset, &data, deref_info.load_size); + } else { + assert(false); + } + } +} + StaticResult Compiler::fill_static_array(const goos::Object& form, const goos::Object& rest, bool boxed, @@ -530,34 +641,8 @@ StaticResult Compiler::fill_static_array(const goos::Object& form, } // now add arguments: - for (size_t i = 4; i < args.size(); i++) { - int arg_idx = i - 4; - int elt_offset = array_header_size + arg_idx * deref_info.stride; - auto sr = compile_static(args.at(i), env); - if (is_integer(content_type)) { - typecheck(form, TypeSpec("integer"), sr.typespec()); - } else { - typecheck(form, content_type, sr.typespec()); - } - if (sr.is_symbol()) { - assert(deref_info.stride == 4); - obj->add_symbol_record(sr.symbol_name(), elt_offset); - u32 symbol_placeholder = 0xffffffff; - memcpy(obj->data.data() + elt_offset, &symbol_placeholder, 4); - } else if (sr.is_reference()) { - assert(deref_info.stride == 4); - obj->add_pointer_record(elt_offset, sr.reference(), sr.reference()->get_addr_offset()); - } else if (sr.is_constant_data()) { - if (!integer_fits(sr.constant_data(), deref_info.load_size, deref_info.sign_extend)) { - throw_compiler_error(form, "The integer {} doesn't fit in element {} of array of {}", - sr.constant_data(), arg_idx, content_type.print()); - } - u64 data = sr.constant_data(); - memcpy(obj->data.data() + elt_offset, &data, deref_info.load_size); - } else { - assert(false); - } - } + fill_static_array_inline(form, content_type, args, obj.get(), array_header_size, env); + TypeSpec result_type; if (boxed) { result_type = m_ts.make_array_typespec(content_type); @@ -569,6 +654,91 @@ StaticResult Compiler::fill_static_array(const goos::Object& form, return result; } +void Compiler::fill_static_inline_array_inline(const goos::Object& form, + const TypeSpec& content_type, + const std::vector& args, + StaticStructure* structure, + int offset, + Env* env) { + auto inline_array_type = m_ts.make_inline_array_typespec(content_type); + auto deref_info = m_ts.get_deref_info(inline_array_type); + assert(deref_info.can_deref); + assert(!deref_info.mem_deref); + + for (size_t i = 4; i < args.size(); i++) { + auto arg_idx = i - 4; + int elt_offset = arg_idx * deref_info.stride; + auto& elt_def = args.at(i); + if (!elt_def.is_list()) { + throw_compiler_error(form, "Element in static inline-array must be a {}. Got {}", + content_type.print(), elt_def.print()); + } + + goos::Object ctor_args; + auto new_form = get_list_as_vector(elt_def, &ctor_args, 3); + if (new_form.size() != 3) { + throw_compiler_error( + elt_def, "Inline array element must be defined with (new 'static 'type-name ...)"); + } + + if (!new_form.at(0).is_symbol() || new_form.at(0).as_symbol()->name != "new") { + throw_compiler_error( + elt_def, "Inline array element must be defined with (new 'static 'type-name ...)"); + } + + if (!is_quoted_sym(new_form.at(1)) || unquote(new_form.at(1)).as_symbol()->name != "static") { + throw_compiler_error( + elt_def, "Inline array element must be defined with (new 'static 'type-name ...)"); + } + + auto inlined_type = parse_typespec(unquote(new_form.at(2))); + if (inlined_type != content_type) { + throw_compiler_error(elt_def, "Cannot store a {} in an inline array of {}", + inlined_type.print(), content_type.print()); + } + compile_static_structure_inline(elt_def, content_type, ctor_args, structure, + elt_offset + offset, env); + if (is_basic(content_type)) { + structure->add_type_record(content_type.base_type(), elt_offset + offset); + } + } +} + +StaticResult Compiler::fill_static_inline_array(const goos::Object& form, + const goos::Object& rest, + Env* env) { + auto fie = get_parent_env_of_type(env); + // (new 'static 'inline-array ...) + // get all arguments now + auto args = get_list_as_vector(rest); + if (args.size() < 4) { + throw_compiler_error(form, "new static boxed array must have type and min-size arguments"); + } + auto content_type = parse_typespec(args.at(2)); + s64 min_size; + if (!try_getting_constant_integer(args.at(3), &min_size, env)) { + throw_compiler_error(form, "The length {} is not valid.", args.at(3).print()); + } + s32 length = std::max(min_size, s64(args.size() - 4)); + + auto inline_array_type = m_ts.make_inline_array_typespec(content_type); + auto deref_info = m_ts.get_deref_info(inline_array_type); + assert(deref_info.can_deref); + assert(!deref_info.mem_deref); + // todo + auto obj = std::make_unique(MAIN_SEGMENT); + obj->set_offset(is_basic(content_type) ? 4 : 0); + obj->data.resize(length * deref_info.stride); + + // now add elements: + fill_static_inline_array_inline(form, content_type, args, obj.get(), 0, env); + + TypeSpec result_type = m_ts.make_inline_array_typespec(content_type); + auto result = StaticResult::make_structure_reference(obj.get(), result_type); + fie->add_static(std::move(obj)); + return result; +} + Val* Compiler::compile_new_static_bitfield(const goos::Object& form, const TypeSpec& type, const goos::Object& _field_defs, diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index 1f263f82a..2be443742 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -766,7 +766,8 @@ Val* Compiler::compile_static_new(const goos::Object& form, Env* env) { auto unquoted = unquote(type); if (unquoted.is_symbol() && - (unquoted.as_symbol()->name == "boxed-array" || unquoted.as_symbol()->name == "array")) { + (unquoted.as_symbol()->name == "boxed-array" || unquoted.as_symbol()->name == "array" || + unquoted.as_symbol()->name == "inline-array")) { auto fe = get_parent_env_of_type(env); auto sr = compile_static(form, env); auto result = fe->alloc_val(sr.reference(), sr.typespec()); diff --git a/test/goalc/source_templates/with_game/test-static-array-field.gc b/test/goalc/source_templates/with_game/test-static-array-field.gc new file mode 100644 index 000000000..2703d9f83 --- /dev/null +++ b/test/goalc/source_templates/with_game/test-static-array-field.gc @@ -0,0 +1,17 @@ +(deftype test-basic-for-static-array-field (basic) + ((value uint32) + (name string) + (arr basic 12) + (lst pair) + ) + ) + +(let ((test (new 'static 'test-basic-for-static-array-field + :value 12 + :arr (new 'static 'array basic 12 + "asdf" + "ghjkl" + ) + ))) + (format #t "~A~%" (-> test arr 1)) + ) diff --git a/test/goalc/source_templates/with_game/test-static-field-inline-arrays.gc b/test/goalc/source_templates/with_game/test-static-field-inline-arrays.gc new file mode 100644 index 000000000..1e40ff383 --- /dev/null +++ b/test/goalc/source_templates/with_game/test-static-field-inline-arrays.gc @@ -0,0 +1,57 @@ +(deftype basic-elt (basic) + ((name string)) + ) + +(deftype struct-elt (structure) + ((thing symbol)) + ) + +(deftype test-basic-for-static-inline-array-field (basic) + ((value uint32) + (name string) + (arr basic-elt 12 :inline) + (arr2 struct-elt 3 :inline) + (lst pair) + ) + ) + +(let ((test (new 'static 'test-basic-for-static-inline-array-field + :value 12 + :arr (new 'static 'inline-array basic-elt 12 + (new 'static 'basic-elt :name "first") + (new 'static 'basic-elt :name "second") + ) + :arr2 (new 'static 'inline-array struct-elt 3 + (new 'static 'struct-elt :thing 'asdf) + (new 'static 'struct-elt :thing 'two) + ) + ))) + (format #t "~A ~A~%" (-> test arr 1 name) (-> test arr 0 name)) + (format #t "~A #x~X #x~X~%" (-> test arr 1 type) (logand 15 (the int (-> test arr))) (logand 15 (the int (-> test arr 1)))) + (format #t "~A~%" (-> test arr2 1 thing)) + ) + +(deftype test-struct-for-static-inline-array-field (structure) + ((value uint32) + (name string) + (arr basic-elt 12 :inline) + (arr2 struct-elt 3 :inline) + (lst pair) + ) + ) + +(let ((test (new 'static 'test-struct-for-static-inline-array-field + :value 12 + :arr (new 'static 'inline-array basic-elt 12 + (new 'static 'basic-elt :name "first") + (new 'static 'basic-elt :name "second") + ) + :arr2 (new 'static 'inline-array struct-elt 3 + (new 'static 'struct-elt :thing 'asdf) + (new 'static 'struct-elt :thing 'two) + ) + ))) + (format #t "~A ~A~%" (-> test arr 1 name) (-> test arr 0 name)) + (format #t "~A #x~X #x~X~%" (-> test arr 1 type) (logand 15 (the int (-> test arr))) (logand 15 (the int (-> test arr 1)))) + (format #t "~A~%" (-> test arr2 1 thing)) + ) diff --git a/test/goalc/source_templates/with_game/test-static-inline-array.gc b/test/goalc/source_templates/with_game/test-static-inline-array.gc new file mode 100644 index 000000000..aa6a0985b --- /dev/null +++ b/test/goalc/source_templates/with_game/test-static-inline-array.gc @@ -0,0 +1,47 @@ +(deftype test-basic-for-static-inline (basic) + ((value uint32) + (name string) + (thing symbol) + (lst pair) + ) + ) + +(let ((test-arr (new 'static 'inline-array test-basic-for-static-inline 3 + (new 'static 'test-basic-for-static-inline :value 12 :name "test-name" :thing 'beans :lst '("asdf" b ( c . d))) + (new 'static 'test-basic-for-static-inline :value 1235 :name "hello") + ) + ) + ) + (format #t "~A ~A #x~X #x~X ~A~%" + (-> test-arr 0 type) + (-> test-arr 1 type) + (logand 15 (the int (-> test-arr 1))) + (logand 15 (the int test-arr)) + (-> test-arr 1 name) + ) + + ) + +(deftype test-struct-for-static-inline (structure) + ((value uint32) + (name string) + (thing symbol) + (lst pair) + ) + ) + +(let ((test-arr (new 'static 'inline-array test-struct-for-static-inline 3 + (new 'static 'test-struct-for-static-inline :value 12 :name "test-name" :thing 'beans :lst '("asdf" b ( c . d))) + (new 'static 'test-struct-for-static-inline :value 1235 :name "hello") + ) + ) + ) + (format #t "#x~X #x~X ~A~%" + ;;(-> test-arr 0 type) + ;;(-> test-arr 1 type) + (logand 15 (the int (-> test-arr 1))) + (logand 15 (the int test-arr)) + (-> test-arr 1 name) + ) + + ) \ No newline at end of file diff --git a/test/goalc/test_with_game.cpp b/test/goalc/test_with_game.cpp index f0e4d8ede..418c0b3ba 100644 --- a/test/goalc/test_with_game.cpp +++ b/test/goalc/test_with_game.cpp @@ -493,6 +493,31 @@ TEST_F(WithGameTests, StaticArray) { "0\n"}); } +TEST_F(WithGameTests, StaticInlineArray) { + runner.run_static_test( + env, testCategory, "test-static-inline-array.gc", + {"test-basic-for-static-inline test-basic-for-static-inline #x4 #x4 \"hello\"\n" + "#x0 #x0 \"hello\"\n" + "0\n"}); +} + +TEST_F(WithGameTests, StaticArrayField) { + runner.run_static_test(env, testCategory, "test-static-array-field.gc", + {"\"ghjkl\"\n" + "0\n"}); +} + +TEST_F(WithGameTests, StaticFieldInlineArray) { + runner.run_static_test(env, testCategory, "test-static-field-inline-arrays.gc", + {"\"second\" \"first\"\n" + "basic-elt #x4 #x4\n" + "two\n" + "\"second\" \"first\"\n" + "basic-elt #x4 #x4\n" + "two\n" + "0\n"}); +} + TEST(TypeConsistency, TypeConsistency) { Compiler compiler; compiler.enable_throw_on_redefines();