bitwise operations

This commit is contained in:
2026-07-19 00:36:31 +02:00
parent f9448363e4
commit c7e3162ecb
21 changed files with 219439 additions and 140077 deletions
+38 -3
View File
@@ -26,6 +26,9 @@ Parser :: struct {
// struct literal. Nested `(`/`[`/call-arg contexts (delimiter_depth > 0) still
// allow struct literals.
no_struct_literal: bool,
// At the top level of if/for headers, `|` begins captures. Bitwise OR in
// those headers remains available inside parentheses.
capture_pipe: bool,
hidden_names: [dynamic]symbol.Id,
}
@@ -1105,10 +1108,14 @@ infix_binding_power :: proc(kind: token.Kind) -> (left, right: int, ok: bool) {
return 6, 7, true
case .Equal_Equal, .Bang_Equal, .Less, .Less_Equal, .Greater, .Greater_Equal:
return 8, 9, true
case .Plus, .Minus:
case .Ampersand, .Keyword_Xor, .Pipe:
return 10, 11, true
case .Star, .Slash:
case .Less_Less, .Greater_Greater, .Less_Less_Pipe:
return 12, 13, true
case .Plus, .Minus:
return 14, 15, true
case .Star, .Slash:
return 16, 17, true
}
return 0, 0, false
}
@@ -1126,6 +1133,12 @@ infix_expr_kind :: proc(kind: token.Kind) -> ast.Expr_Kind {
case .Less_Equal: return .Le
case .Greater: return .Gt
case .Greater_Equal: return .Ge
case .Ampersand: return .Bit_And
case .Pipe: return .Bit_Or
case .Keyword_Xor: return .Bit_Xor
case .Less_Less: return .Shift_Left
case .Greater_Greater: return .Shift_Right
case .Less_Less_Pipe: return .Shift_Left_Saturating
case .Plus: return .Add
case .Minus: return .Sub
case .Star: return .Mul
@@ -1140,6 +1153,12 @@ compound_assignment_op :: proc(kind: token.Kind) -> (ast.Assignment_Op, bool) {
case .Minus_Equal: return .Sub, true
case .Star_Equal: return .Mul, true
case .Slash_Equal: return .Div, true
case .Ampersand_Equal: return .Bit_And, true
case .Pipe_Equal: return .Bit_Or, true
case .Xor_Equal: return .Bit_Xor, true
case .Less_Less_Equal: return .Shift_Left, true
case .Greater_Greater_Equal: return .Shift_Right, true
case .Less_Less_Pipe_Equal: return .Shift_Left_Saturating, true
}
return .Set, false
}
@@ -1158,7 +1177,7 @@ is_simple_range_bound :: proc(expr: ast.Expr) -> bool {
prefix_binding_power :: proc(kind: token.Kind) -> (right: int, ok: bool) {
#partial switch kind {
case .Minus, .Ampersand, .Bang, .Dollar, .Keyword_Try:
case .Minus, .Ampersand, .Bang, .Tilde, .Dollar, .Keyword_Try:
return 20, true
}
return 0, false
@@ -1196,6 +1215,7 @@ parse_expression_bp :: proc(parser: ^Parser, minimum_binding_power, nesting: int
#partial switch operator.kind {
case .Ampersand: prefix_kind = .Address
case .Bang: prefix_kind = .Not
case .Tilde: prefix_kind = .Bit_Not
case .Dollar: prefix_kind = .Comptime
case .Keyword_Try: prefix_kind = .Try
}
@@ -1352,6 +1372,9 @@ parse_expression_bp :: proc(parser: ^Parser, minimum_binding_power, nesting: int
})
continue
}
if parser.capture_pipe && parser.delimiter_depth == 0 && current(parser).kind == .Pipe {
break
}
left_power, right_power, ok := infix_binding_power(current(parser).kind)
if ok && (current(parser).kind == .Range || current(parser).kind == .Range_Inclusive) &&
parser.range_disabled > 0 {
@@ -2031,7 +2054,10 @@ parse_if :: proc(parser: ^Parser) -> ast.Stmt_Id {
skip_newlines(parser)
saved := parser.no_struct_literal
parser.no_struct_literal = true
saved_capture_pipe := parser.capture_pipe
parser.capture_pipe = true
condition := parse_expression(parser)
parser.capture_pipe = saved_capture_pipe
parser.no_struct_literal = saved
captures: [dynamic]symbol.Id
captures.allocator = parser.module.allocator
@@ -2060,7 +2086,10 @@ parse_if :: proc(parser: ^Parser) -> ast.Stmt_Id {
} else {
saved = parser.no_struct_literal
parser.no_struct_literal = true
saved_capture_pipe = parser.capture_pipe
parser.capture_pipe = true
guard = parse_expression(parser)
parser.capture_pipe = saved_capture_pipe
parser.no_struct_literal = saved
}
}
@@ -2166,6 +2195,8 @@ parse_match_arm :: proc(parser: ^Parser) -> ast.Stmt_Id {
} else if _, is_else := allow(parser, .Keyword_Else); !is_else {
saved := parser.no_struct_literal
parser.no_struct_literal = true
saved_capture_pipe := parser.capture_pipe
parser.capture_pipe = true
append(&patterns, parse_expression(parser))
for {
if _, ok := allow(parser, .Comma); !ok {
@@ -2174,6 +2205,7 @@ parse_match_arm :: proc(parser: ^Parser) -> ast.Stmt_Id {
skip_newlines(parser)
append(&patterns, parse_expression(parser))
}
parser.capture_pipe = saved_capture_pipe
parser.no_struct_literal = saved
if _, ok := allow(parser, .Pipe); ok {
if _, at_ok := allow(parser, .At); at_ok {
@@ -2324,7 +2356,10 @@ parse_for :: proc(parser: ^Parser) -> ast.Stmt_Id {
skip_newlines(parser)
saved := parser.no_struct_literal
parser.no_struct_literal = true
saved_capture_pipe := parser.capture_pipe
parser.capture_pipe = true
iterable := parse_expression(parser)
parser.capture_pipe = saved_capture_pipe
parser.no_struct_literal = saved
skip_newlines(parser)