Pass an important chunk of tests #36
@ -51,3 +51,6 @@ target_link_libraries(bb PUBLIC llvm_bindings)
|
|||||||
add_compile_options(-Wall -Wextra -pedantic -Wpedantic -Werror -Wno-c99-extensions -Wno-unused-function -Wno-missing-designated-field-initializers -fno-signed-char -fwrapv -fno-strict-aliasing)
|
add_compile_options(-Wall -Wextra -pedantic -Wpedantic -Werror -Wno-c99-extensions -Wno-unused-function -Wno-missing-designated-field-initializers -fno-signed-char -fwrapv -fno-strict-aliasing)
|
||||||
add_compile_definitions(CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}")
|
add_compile_definitions(CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}")
|
||||||
add_compile_definitions(BB_CI=${BB_CI})
|
add_compile_definitions(BB_CI=${BB_CI})
|
||||||
|
|
||||||
|
# add_compile_options(-fsanitize=address)
|
||||||
|
# add_link_options(-fsanitize=address)
|
||||||
|
2177
src/compiler.bbb
2177
src/compiler.bbb
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@ fn LLVMValueRef llvm_module_create_function(Arena* arena, LLVMModuleRef module,
|
|||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn LLVMValueRef llvm_module_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMThreadLocalMode thread_local_mode, bool externally_initialized, u32 alignment, LLVMUnnamedAddr unnamed_address)
|
fn LLVMValueRef llvm_create_global_variable(LLVMModuleRef module, LLVMTypeRef type, bool is_constant, LLVMLinkage linkage_type, LLVMValueRef initial_value, String name, LLVMThreadLocalMode thread_local_mode, bool externally_initialized, u32 alignment, LLVMUnnamedAddr unnamed_address)
|
||||||
{
|
{
|
||||||
assert(name.pointer[name.length] == 0);
|
assert(name.pointer[name.length] == 0);
|
||||||
auto global = LLVMAddGlobal(module, type, (char*)name.pointer);
|
auto global = LLVMAddGlobal(module, type, (char*)name.pointer);
|
||||||
@ -609,21 +609,19 @@ fn bool contains_no_user_data(Type* type, u64 start, u64 end)
|
|||||||
{
|
{
|
||||||
case TypeId::structure:
|
case TypeId::structure:
|
||||||
{
|
{
|
||||||
u64 offset = 0;
|
|
||||||
|
|
||||||
for (auto& field: type->structure.fields)
|
for (auto& field: type->structure.fields)
|
||||||
{
|
{
|
||||||
if (offset >= end)
|
auto field_offset = field.offset;
|
||||||
|
if (field_offset >= end)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto field_start = offset < start ? start - offset : 0;
|
auto field_start = field_offset < start ? start - field_offset : 0;
|
||||||
if (!contains_no_user_data(field.type, field_start, end - offset))
|
if (!contains_no_user_data(field.type, field_start, end - field_offset))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
offset += get_byte_size(field.type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -855,7 +853,7 @@ fn AbiSystemVClassifyResult abi_system_v_classify_type(Type* type, AbiSystemVCla
|
|||||||
|
|
||||||
u64 vector_size = 16;
|
u64 vector_size = 16;
|
||||||
|
|
||||||
if (byte_size > 16 && (byte_size != get_byte_size(element_type) || byte_size > vector_size))
|
if (byte_size > 16 && (byte_size != element_size || byte_size > vector_size))
|
||||||
{
|
{
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
@ -2541,7 +2539,6 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
|
|||||||
auto u64_type = uint64(module);
|
auto u64_type = uint64(module);
|
||||||
resolve_type_in_place(module, u8_type);
|
resolve_type_in_place(module, u8_type);
|
||||||
resolve_type_in_place(module, u64_type);
|
resolve_type_in_place(module, u64_type);
|
||||||
LLVMValueRef name_before = 0;
|
|
||||||
LLVMValueRef name_constant_buffer[64];
|
LLVMValueRef name_constant_buffer[64];
|
||||||
|
|
||||||
for (u32 i = 0; i < fields.length; i += 1)
|
for (u32 i = 0; i < fields.length; i += 1)
|
||||||
@ -2555,11 +2552,9 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
|
|||||||
string_literal("."),
|
string_literal("."),
|
||||||
field.name,
|
field.name,
|
||||||
};
|
};
|
||||||
unsigned address_space = 0;
|
|
||||||
auto initial_value = LLVMConstStringInContext2(module->llvm.context, (char*)field.name.pointer, field.name.length, false);
|
auto initial_value = LLVMConstStringInContext2(module->llvm.context, (char*)field.name.pointer, field.name.length, false);
|
||||||
u32 alignment = 1;
|
u32 alignment = 1;
|
||||||
auto name_global = llvm_module_create_global_variable(module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, initial_value, arena_join_string(module->arena, array_to_slice(name_parts)), LLVMNotThreadLocal, false, alignment, LLVMGlobalUnnamedAddr);
|
auto name_global = llvm_create_global_variable(module->llvm.module, LLVMArrayType2(u8_type->llvm.abi, field.name.length + null_terminate), is_constant, LLVMInternalLinkage, initial_value, arena_join_string(module->arena, array_to_slice(name_parts)), LLVMNotThreadLocal, false, alignment, LLVMGlobalUnnamedAddr);
|
||||||
name_before = name_global;
|
|
||||||
LLVMValueRef constants[] = {
|
LLVMValueRef constants[] = {
|
||||||
name_global,
|
name_global,
|
||||||
LLVMConstInt(u64_type->llvm.abi, field.name.length, false),
|
LLVMConstInt(u64_type->llvm.abi, field.name.length, false),
|
||||||
@ -2573,8 +2568,7 @@ fn Global* get_enum_name_array_global(Module* module, Type* enum_type)
|
|||||||
auto name_array = LLVMConstArray2(slice_type->llvm.abi, name_constant_buffer, array_element_count);
|
auto name_array = LLVMConstArray2(slice_type->llvm.abi, name_constant_buffer, array_element_count);
|
||||||
auto name_array_type = LLVMArrayType2(slice_type->llvm.abi, array_element_count);
|
auto name_array_type = LLVMArrayType2(slice_type->llvm.abi, array_element_count);
|
||||||
auto is_constant = true;
|
auto is_constant = true;
|
||||||
unsigned address_space = 0;
|
auto name_array_variable = llvm_create_global_variable(module->llvm.module, name_array_type, is_constant, LLVMInternalLinkage, name_array, string_literal("name.array.enum"), LLVMNotThreadLocal, false, get_byte_alignment(slice_type), LLVMGlobalUnnamedAddr);
|
||||||
auto name_array_variable = llvm_module_create_global_variable(module->llvm.module, name_array_type, is_constant, LLVMInternalLinkage, name_array, string_literal("name.array.enum"), LLVMNotThreadLocal, false, get_byte_alignment(slice_type), LLVMGlobalUnnamedAddr);
|
|
||||||
|
|
||||||
auto global_type = get_array_type(module, slice_type, array_element_count);
|
auto global_type = get_array_type(module, slice_type, array_element_count);
|
||||||
resolve_type_in_place(module, global_type);
|
resolve_type_in_place(module, global_type);
|
||||||
@ -4283,9 +4277,8 @@ fn void analyze_type(Module* module, Value* value, Type* expected_type, TypeAnal
|
|||||||
auto value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count);
|
auto value_array_variable_type = LLVMArrayType2(enum_value_type, array_element_count);
|
||||||
auto is_constant = true;
|
auto is_constant = true;
|
||||||
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
||||||
unsigned address_space = 0;
|
|
||||||
auto externally_initialized = false;
|
auto externally_initialized = false;
|
||||||
auto value_array_variable = llvm_module_create_global_variable(module->llvm.module, value_array_variable_type, is_constant, LLVMInternalLinkage, value_array, string_literal("value.array.enum"), thread_local_mode, externally_initialized, enum_alignment, LLVMGlobalUnnamedAddr);
|
auto value_array_variable = llvm_create_global_variable(module->llvm.module, value_array_variable_type, is_constant, LLVMInternalLinkage, value_array, string_literal("value.array.enum"), thread_local_mode, externally_initialized, enum_alignment, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry");
|
auto* entry_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "entry");
|
||||||
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
|
auto* return_block = LLVMAppendBasicBlockInContext(module->llvm.context, llvm_function, "return_block");
|
||||||
@ -5179,7 +5172,7 @@ fn SliceEmitResult emit_string_literal(Module* module, Value* value)
|
|||||||
LLVMThreadLocalMode tlm = LLVMNotThreadLocal;
|
LLVMThreadLocalMode tlm = LLVMNotThreadLocal;
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
u32 alignment = 1;
|
u32 alignment = 1;
|
||||||
auto global = llvm_module_create_global_variable(module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), tlm, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
auto global = llvm_create_global_variable(module->llvm.module, string_type, is_constant, LLVMInternalLinkage, constant_string, string_literal("conststring"), tlm, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
return { global, LLVMConstInt(uint64(module)->llvm.abi, length, false) };
|
return { global, LLVMConstInt(uint64(module)->llvm.abi, length, false) };
|
||||||
} break;
|
} break;
|
||||||
@ -5216,6 +5209,22 @@ fn void invalidate_analysis(Module* module, Value* value)
|
|||||||
{
|
{
|
||||||
invalidate_analysis(module, value->unary.value);
|
invalidate_analysis(module, value->unary.value);
|
||||||
} break;
|
} break;
|
||||||
|
case ValueId::slice_expression:
|
||||||
|
{
|
||||||
|
invalidate_analysis(module, value->slice_expression.array_like);
|
||||||
|
auto start = value->slice_expression.start;
|
||||||
|
auto end = value->slice_expression.end;
|
||||||
|
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
invalidate_analysis(module, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end)
|
||||||
|
{
|
||||||
|
invalidate_analysis(module, end);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default: trap();
|
default: trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5552,11 +5561,10 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
bool is_constant = true;
|
bool is_constant = true;
|
||||||
LLVMLinkage linkage_type = LLVMInternalLinkage;
|
LLVMLinkage linkage_type = LLVMInternalLinkage;
|
||||||
LLVMThreadLocalMode thread_local_mode = {};
|
LLVMThreadLocalMode thread_local_mode = {};
|
||||||
u32 address_space = 0;
|
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
auto alignment = get_byte_alignment(semantic_argument_type);
|
auto alignment = get_byte_alignment(semantic_argument_type);
|
||||||
|
|
||||||
auto global = llvm_module_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("conststruct"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
auto global = llvm_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("const.struct"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
for (u32 i = 0; i < coerce_fields.length; i += 1)
|
for (u32 i = 0; i < coerce_fields.length; i += 1)
|
||||||
{
|
{
|
||||||
@ -5707,7 +5715,7 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
auto alignment = get_byte_alignment(semantic_argument_type);
|
auto alignment = get_byte_alignment(semantic_argument_type);
|
||||||
|
|
||||||
auto global = llvm_module_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("indirect.const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
auto global = llvm_create_global_variable(module->llvm.module, semantic_argument_type->llvm.memory, is_constant, linkage_type, semantic_call_argument_value->llvm, string_literal("indirect.const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
llvm_abi_argument_value_buffer[abi_argument_count] = global;
|
llvm_abi_argument_value_buffer[abi_argument_count] = global;
|
||||||
abi_argument_count += 1;
|
abi_argument_count += 1;
|
||||||
@ -5840,7 +5848,6 @@ fn LLVMValueRef emit_call(Module* module, Value* value, LLVMValueRef left_llvm,
|
|||||||
|
|
||||||
auto destination_type = return_abi.semantic_type;
|
auto destination_type = return_abi.semantic_type;
|
||||||
|
|
||||||
|
|
||||||
auto source_value = llvm_call;
|
auto source_value = llvm_call;
|
||||||
auto source_type = raw_function_type->function.abi.abi_return_type;
|
auto source_type = raw_function_type->function.abi.abi_return_type;
|
||||||
auto destination_size = get_byte_size(destination_type);
|
auto destination_size = get_byte_size(destination_type);
|
||||||
@ -6449,11 +6456,10 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
|
|||||||
bool is_constant = true;
|
bool is_constant = true;
|
||||||
LLVMLinkage linkage_type = LLVMInternalLinkage;
|
LLVMLinkage linkage_type = LLVMInternalLinkage;
|
||||||
LLVMThreadLocalMode thread_local_mode = {};
|
LLVMThreadLocalMode thread_local_mode = {};
|
||||||
u32 address_space = 0;
|
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
auto alignment = get_byte_alignment(resolved_value_type);
|
auto alignment = get_byte_alignment(resolved_value_type);
|
||||||
|
|
||||||
auto global = llvm_module_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("array.init"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
auto global = llvm_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("array.init"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
||||||
|
|
||||||
u64 memcpy_size = get_byte_size(resolved_value_type);
|
u64 memcpy_size = get_byte_size(resolved_value_type);
|
||||||
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, LLVMConstInt(uint64_type->llvm.abi, memcpy_size, false));
|
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, LLVMConstInt(uint64_type->llvm.abi, memcpy_size, false));
|
||||||
@ -6526,7 +6532,7 @@ fn void emit_assignment(Module* module, LLVMValueRef left_llvm, Type* left_type,
|
|||||||
LLVMLinkage linkage_type = LLVMInternalLinkage;
|
LLVMLinkage linkage_type = LLVMInternalLinkage;
|
||||||
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
LLVMThreadLocalMode thread_local_mode = LLVMNotThreadLocal;
|
||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
auto global = llvm_module_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
auto global = llvm_create_global_variable(module->llvm.module, value_type->llvm.memory, is_constant, linkage_type, right->llvm, string_literal("const.aggregate"), thread_local_mode, externally_initialized, alignment, LLVMGlobalUnnamedAddr);
|
||||||
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, byte_size_value);
|
LLVMBuildMemCpy(module->llvm.builder, left_llvm, alignment, global, alignment, byte_size_value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -7068,7 +7074,8 @@ fn void analyze_block(Module* module, Block* block)
|
|||||||
|
|
||||||
fn LLVMValueRef emit_constant_array(Module* module, Slice<Value*> elements, Type* element_type)
|
fn LLVMValueRef emit_constant_array(Module* module, Slice<Value*> elements, Type* element_type)
|
||||||
{
|
{
|
||||||
LLVMValueRef value_buffer[64];
|
LLVMValueRef value_buffer[128];
|
||||||
|
assert(elements.length <= array_length(value_buffer));
|
||||||
|
|
||||||
resolve_type_in_place(module, element_type);
|
resolve_type_in_place(module, element_type);
|
||||||
|
|
||||||
@ -7329,7 +7336,7 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect
|
|||||||
assert(array_type->id == TypeId::array);
|
assert(array_type->id == TypeId::array);
|
||||||
resolve_type_in_place(module, array_type);
|
resolve_type_in_place(module, array_type);
|
||||||
auto alignment = get_byte_alignment(resolved_value_type);
|
auto alignment = get_byte_alignment(resolved_value_type);
|
||||||
auto value_array_variable = llvm_module_create_global_variable(module->llvm.module, array_type->llvm.memory, is_constant, LLVMInternalLinkage, array_value, string_literal("enum.values"), LLVMNotThreadLocal, 0, alignment, LLVMGlobalUnnamedAddr);
|
auto value_array_variable = llvm_create_global_variable(module->llvm.module, array_type->llvm.memory, is_constant, LLVMInternalLinkage, array_value, string_literal("enum.values"), LLVMNotThreadLocal, 0, alignment, LLVMGlobalUnnamedAddr);
|
||||||
llvm_value = value_array_variable;
|
llvm_value = value_array_variable;
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@ -8615,6 +8622,10 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
if (else_clause_index == invalid_clause_index)
|
if (else_clause_index == invalid_clause_index)
|
||||||
{
|
{
|
||||||
LLVMPositionBuilderAtEnd(module->llvm.builder, else_block);
|
LLVMPositionBuilderAtEnd(module->llvm.builder, else_block);
|
||||||
|
if (module->has_debug_info && !build_mode_is_optimized(module->build_mode))
|
||||||
|
{
|
||||||
|
emit_intrinsic_call(module, IntrinsicIndex::trap, {}, {});
|
||||||
|
}
|
||||||
LLVMBuildUnreachable(module->llvm.builder);
|
LLVMBuildUnreachable(module->llvm.builder);
|
||||||
LLVMClearInsertionPosition(module->llvm.builder);
|
LLVMClearInsertionPosition(module->llvm.builder);
|
||||||
}
|
}
|
||||||
@ -8678,6 +8689,16 @@ fn void analyze_statement(Module* module, Scope* scope, Statement* statement, u3
|
|||||||
|
|
||||||
Type* aggregate_type = 0;
|
Type* aggregate_type = 0;
|
||||||
|
|
||||||
|
if (right->kind == ValueKind::left && right->type->id != TypeId::pointer)
|
||||||
|
{
|
||||||
|
if (!type_is_slice(right->type))
|
||||||
|
{
|
||||||
|
report_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
right->kind = ValueKind::right;
|
||||||
|
}
|
||||||
|
|
||||||
switch (right->kind)
|
switch (right->kind)
|
||||||
{
|
{
|
||||||
case ValueKind::right:
|
case ValueKind::right:
|
||||||
@ -9504,7 +9525,7 @@ void emit(Module* module)
|
|||||||
bool externally_initialized = false;
|
bool externally_initialized = false;
|
||||||
|
|
||||||
auto alignment = get_byte_alignment(global_type);
|
auto alignment = get_byte_alignment(global_type);
|
||||||
auto global_llvm = llvm_module_create_global_variable(module->llvm.module, global_type->llvm.memory, is_constant, linkage, global->variable.initial_value->llvm, global->variable.name, thread_local_mode, externally_initialized, alignment, LLVMNoUnnamedAddr);
|
auto global_llvm = llvm_create_global_variable(module->llvm.module, global_type->llvm.memory, is_constant, linkage, global->variable.initial_value->llvm, global->variable.name, thread_local_mode, externally_initialized, alignment, LLVMNoUnnamedAddr);
|
||||||
global->variable.storage->llvm = global_llvm;
|
global->variable.storage->llvm = global_llvm;
|
||||||
global->variable.storage->type = get_pointer_type(module, global_type);
|
global->variable.storage->type = get_pointer_type(module, global_type);
|
||||||
|
|
||||||
|
@ -1937,7 +1937,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
|||||||
case TokenId::left_bracket:
|
case TokenId::left_bracket:
|
||||||
{
|
{
|
||||||
u64 element_count = 0;
|
u64 element_count = 0;
|
||||||
Value* value_buffer[64];
|
Value* value_buffer[128];
|
||||||
|
|
||||||
skip_space(module);
|
skip_space(module);
|
||||||
|
|
||||||
@ -1976,6 +1976,7 @@ fn Value* parse_left(Module* module, Scope* scope, ValueBuilder builder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto value = parse_value(module, scope, {});
|
auto value = parse_value(module, scope, {});
|
||||||
|
assert(element_count < array_length(value_buffer));
|
||||||
value_buffer[element_count] = value;
|
value_buffer[element_count] = value;
|
||||||
element_count += 1;
|
element_count += 1;
|
||||||
|
|
||||||
@ -2822,7 +2823,7 @@ fn Statement* parse_statement(Module* module, Scope* scope)
|
|||||||
Value* right_value_buffer[64];
|
Value* right_value_buffer[64];
|
||||||
u64 right_value_count = 0;
|
u64 right_value_count = 0;
|
||||||
|
|
||||||
right_value_buffer[right_value_count] = parse_value(module, scope, { .kind = ValueKind::left });
|
right_value_buffer[right_value_count] = parse_value(module, scope, {});
|
||||||
right_value_count += 1;
|
right_value_count += 1;
|
||||||
|
|
||||||
skip_space(module);
|
skip_space(module);
|
||||||
@ -2839,15 +2840,17 @@ fn Statement* parse_statement(Module* module, Scope* scope)
|
|||||||
report_error();
|
report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
right_value_buffer[0]->kind = ValueKind::right;
|
|
||||||
|
|
||||||
right_value_buffer[right_value_count] = parse_value(module, scope, {});
|
right_value_buffer[right_value_count] = parse_value(module, scope, {});
|
||||||
right_value_count += 1;
|
right_value_count += 1;
|
||||||
|
|
||||||
expect_character(module, right_parenthesis);
|
expect_character(module, right_parenthesis);
|
||||||
kind = ForEachKind::range;
|
kind = ForEachKind::range;
|
||||||
} break;
|
} break;
|
||||||
case TokenId::right_parenthesis: kind = ForEachKind::slice; break;
|
case TokenId::right_parenthesis:
|
||||||
|
{
|
||||||
|
right_value_buffer[0]->kind = ValueKind::left;
|
||||||
|
kind = ForEachKind::slice;
|
||||||
|
} break;
|
||||||
default: report_error();
|
default: report_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user