diff --git a/src/compiler.bbb b/src/compiler.bbb index 531c6c5..52970a4 100644 --- a/src/compiler.bbb +++ b/src/compiler.bbb @@ -1487,6 +1487,8 @@ ValueId = enum function, constant_integer, global, + unary, + binary, } ValueConstantInteger = struct @@ -1510,10 +1512,37 @@ ValueFunction = struct attributes: FunctionAttributes, } +UnaryId = enum +{ + minus, + plus, + ampersand, + exclamation, + tilde, + enum_name, + extend, + truncate, + pointer_cast, + int_from_enum, + int_from_pointer, + va_end, + bitwise_not, + dereference, + pointer_from_int, + enum_from_int, +} + +ValueUnary = struct +{ + value: &Value, + id: UnaryId, +} + ValueContent = union { constant_integer: ValueConstantInteger, function: ValueFunction, + unary: ValueUnary, } ValueKind = enum @@ -2819,7 +2848,7 @@ tokenize = fn (module: &Module) Token >start_character = module.content[start_index]; - >token: Token = undefined; + >token: Token = zero; switch (start_character) { @@ -2940,7 +2969,45 @@ tokenize = fn (module: &Module) Token '!', => { - #trap(); + >next_ch = module.content[start_index + 1]; + >id: TokenId = undefined; + + if (next_ch == '=') + { + switch (start_character) + { + '+' => { id = .assign_plus; }, + '-' => { id = .assign_dash; }, + '*' => { id = .assign_asterisk; }, + '/' => { id = .assign_forward_slash; }, + '%' => { id = .assign_percentage; }, + '&' => { id = .assign_ampersand; }, + '|' => { id = .assign_bar; }, + '^' => { id = .assign_caret; }, + '!' => { id = .compare_not_equal; }, + else => { unreachable; } + } + } + else + { + switch (start_character) + { + '+' => { id = .plus; }, + '-' => { id = .dash; }, + '*' => { id = .asterisk; }, + '/' => { id = .forward_slash; }, + '%' => { id = .percentage; }, + '&' => { id = .ampersand; }, + '|' => { id = .bar; }, + '^' => { id = .caret; }, + '!' => { id = .exclamation; }, + else => { unreachable; } + } + } + + token.id = id; + + module.offset += #extend(next_ch == '=') + 1; }, else => { @@ -2984,6 +3051,8 @@ ValueBuilder = struct allow_assignment_operators: u1, } +parse_precedence = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value; + parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value { >token = builder.token; @@ -3007,6 +3076,72 @@ parse_left = fn (module: &Module, scope: &Scope, builder: ValueBuilder) &Value zero, }; }, + .dash, .ampersand, .exclamation, .tilde => + { + assert(!builder.left); + >id: UnaryId = undefined; + + switch (token.id) + { + .dash => { id = .minus; }, + .ampersand => { id = .ampersand; }, + .exclamation => { id = .exclamation; }, + .tilde => { id = .bitwise_not; }, + else => { unreachable; }, + } + + >unary_builder = builder; + unary_builder.precedence = .prefix; + unary_builder.token = zero; + unary_builder.kind = #select(token.id == .ampersand, .left, builder.kind); + + >unary_value = parse_precedence(module, scope, builder); + + result = new_value(module); + result.& = { + .content = { + .unary = { + .value = unary_value, + .id = id, + }, + }, + .id = .unary, + .kind = .right, + zero, + }; + }, + .identifier => + { + #trap(); + }, + .value_intrinsic => + { + #trap(); + }, + .left_bracket => + { + #trap(); + }, + .dot => + { + #trap(); + }, + .left_parenthesis => + { + #trap(); + }, + .string_literal => + { + #trap(); + }, + .left_brace => + { + #trap(); + }, + .value_keyword => + { + #trap(); + }, else => { report_error(); @@ -5738,6 +5873,18 @@ compile_file = fn (arena: &Arena, compile_options: CompileFile) []u8 names: [_][]u8 = [ "minimal", + "comments", + "constant_add", + "constant_and", + "constant_div", + "constant_mul", + "constant_rem", + "constant_or", + "constant_sub", + "constant_xor", + "constant_shift_left", + "constant_shift_right", + ]; [export] main = fn [cc(c)] (argument_count: u32, argv: &&u8, envp: &&u8) s32 diff --git a/src/emitter.cpp b/src/emitter.cpp index 6c4a60b..92c2cb6 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -5983,6 +5983,7 @@ fn LLVMValueRef emit_field_access(Module* module, Value* value, LLVMValueRef lef auto load = create_load(module, { .type = field_access.type, .pointer = gep, + .kind = type_kind, }); return load; } break; @@ -7704,6 +7705,7 @@ fn void emit_value(Module* module, Value* value, TypeKind type_kind, bool expect auto condition = value->select.condition; auto true_value = value->select.true_value; auto false_value = value->select.false_value; + emit_value(module, condition, TypeKind::abi, must_be_constant); LLVMValueRef llvm_condition = condition->llvm; auto condition_type = condition->type;