bitwise operations
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user