Switch statement
This commit is contained in:
parent
bb57af7642
commit
fa4ec4c156
168
src/compiler.bbb
168
src/compiler.bbb
@ -2738,9 +2738,27 @@ StatementWhile = struct
|
|||||||
block: &Block,
|
block: &Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StatementSwitchDiscriminantId = enum
|
||||||
|
{
|
||||||
|
single,
|
||||||
|
range,
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementSwitchDiscriminantContent = union
|
||||||
|
{
|
||||||
|
single: &Value,
|
||||||
|
range: [2]&Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
StatementSwitchDiscriminant = struct
|
||||||
|
{
|
||||||
|
content: StatementSwitchDiscriminantContent,
|
||||||
|
id: StatementSwitchDiscriminantId,
|
||||||
|
}
|
||||||
|
|
||||||
StatementSwitchClause = struct
|
StatementSwitchClause = struct
|
||||||
{
|
{
|
||||||
values: []&Value,
|
values: []StatementSwitchDiscriminant,
|
||||||
block: &Block,
|
block: &Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6014,7 +6032,148 @@ parse_statement = fn (module: &Module, scope: &Scope) &Statement
|
|||||||
},
|
},
|
||||||
.switch =>
|
.switch =>
|
||||||
{
|
{
|
||||||
#trap();
|
skip_space(module);
|
||||||
|
expect_character(module, left_parenthesis);
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
>discriminant = parse_value(module, scope, zero);
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
expect_character(module, right_parenthesis);
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
expect_character(module, left_brace);
|
||||||
|
|
||||||
|
>clause_buffer: [64]StatementSwitchClause = undefined;
|
||||||
|
>clause_count: u64 = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
>is_else: u1 = 0;
|
||||||
|
if (is_identifier_start(module.content[module.offset]))
|
||||||
|
{
|
||||||
|
>else_checkpoint = get_checkpoint(module);
|
||||||
|
>i = parse_identifier(module);
|
||||||
|
is_else = string_equal(i, "else");
|
||||||
|
|
||||||
|
if (!is_else)
|
||||||
|
{
|
||||||
|
set_checkpoint(module, else_checkpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>clause_values: []StatementSwitchDiscriminant = zero;
|
||||||
|
|
||||||
|
if (is_else)
|
||||||
|
{
|
||||||
|
skip_space(module);
|
||||||
|
expect_character(module, '=');
|
||||||
|
expect_character(module, '>');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
>case_buffer: [64]StatementSwitchDiscriminant = undefined;
|
||||||
|
>case_count: u64 = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
>first_case_value = parse_value(module, scope, zero);
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
>checkpoint = get_checkpoint(module);
|
||||||
|
>token = tokenize(module);
|
||||||
|
|
||||||
|
>clause_discriminant: StatementSwitchDiscriminant = undefined;
|
||||||
|
|
||||||
|
switch (token.id)
|
||||||
|
{
|
||||||
|
.triple_dot =>
|
||||||
|
{
|
||||||
|
>last_case_value = parse_value(module, scope, zero);
|
||||||
|
clause_discriminant = {
|
||||||
|
.content = {
|
||||||
|
.range = [ first_case_value, last_case_value ],
|
||||||
|
},
|
||||||
|
.id = .range,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
else =>
|
||||||
|
{
|
||||||
|
if (token.id != .comma)
|
||||||
|
{
|
||||||
|
set_checkpoint(module, checkpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
clause_discriminant = {
|
||||||
|
.content = {
|
||||||
|
.single = first_case_value,
|
||||||
|
},
|
||||||
|
.id = .single,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (clause_discriminant.id)
|
||||||
|
{
|
||||||
|
.single => { assert(clause_discriminant.content.single != zero); },
|
||||||
|
.range =>
|
||||||
|
{
|
||||||
|
assert(clause_discriminant.content.range[0] != zero);
|
||||||
|
assert(clause_discriminant.content.range[1] != zero);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
case_buffer[case_count] = clause_discriminant;
|
||||||
|
case_count += 1;
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
if (consume_character_if_match(module, '='))
|
||||||
|
{
|
||||||
|
expect_character(module, '>');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clause_values = arena_allocate_slice[StatementSwitchDiscriminant](module.arena, case_count);
|
||||||
|
memcpy(#pointer_cast(clause_values.pointer), #pointer_cast(&case_buffer), case_count * #byte_size(StatementSwitchDiscriminant));
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
>clause_block = parse_block(module, scope);
|
||||||
|
|
||||||
|
clause_buffer[clause_count] = {
|
||||||
|
.values = clause_values,
|
||||||
|
.block = clause_block,
|
||||||
|
};
|
||||||
|
clause_count += 1;
|
||||||
|
|
||||||
|
consume_character_if_match(module, ',');
|
||||||
|
|
||||||
|
skip_space(module);
|
||||||
|
|
||||||
|
if (consume_character_if_match(module, right_brace))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>clauses = arena_allocate_slice[StatementSwitchClause](module.arena, clause_count);
|
||||||
|
memcpy(#pointer_cast(clauses.pointer), #pointer_cast(&clause_buffer), clause_count * #byte_size(StatementSwitchClause));
|
||||||
|
|
||||||
|
require_semicolon = 0;
|
||||||
|
|
||||||
|
statement.content = {
|
||||||
|
.switch = {
|
||||||
|
.discriminant = discriminant,
|
||||||
|
.clauses = clauses,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
statement.id = .switch;
|
||||||
},
|
},
|
||||||
.break =>
|
.break =>
|
||||||
{
|
{
|
||||||
@ -13013,6 +13172,10 @@ analyze_statement = fn (module: &Module, scope: &Scope, statement: &Statement) v
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.switch =>
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
},
|
||||||
else =>
|
else =>
|
||||||
{
|
{
|
||||||
#trap();
|
#trap();
|
||||||
@ -14457,6 +14620,7 @@ names: [_][]u8 =
|
|||||||
"string_to_enum",
|
"string_to_enum",
|
||||||
"empty_if",
|
"empty_if",
|
||||||
"else_if",
|
"else_if",
|
||||||
|
"else_if_complicated",
|
||||||
];
|
];
|
||||||
|
|
||||||
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32
|
[export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32
|
||||||
|
Loading…
x
Reference in New Issue
Block a user