Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

Implement parsing of binary operators in bit arrays size patterns

+485 -15
+29 -3
compiler-core/src/ast.rs
··· 2100 2100 constructor: Option<ValueConstructor>, 2101 2101 type_: Type, 2102 2102 }, 2103 + 2104 + BinaryOperator { 2105 + location: SrcSpan, 2106 + operator: IntegerOperator, 2107 + left: Box<Self>, 2108 + right: Box<Self>, 2109 + }, 2110 + } 2111 + 2112 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 2113 + pub enum IntegerOperator { 2114 + Add, 2115 + Subtract, 2116 + Multiply, 2117 + Divide, 2118 + Remainder, 2119 + } 2120 + 2121 + impl IntegerOperator { 2122 + pub fn precedence(&self) -> u8 { 2123 + match self { 2124 + Self::Add | Self::Subtract => 7, 2125 + 2126 + Self::Multiply | Self::Divide | Self::Remainder => 8, 2127 + } 2128 + } 2103 2129 } 2104 2130 2105 2131 impl<T> BitArraySize<T> { 2106 2132 pub fn location(&self) -> SrcSpan { 2107 2133 match self { 2108 - BitArraySize::Int { location, .. } | BitArraySize::Variable { location, .. } => { 2109 - *location 2110 - } 2134 + BitArraySize::Int { location, .. } 2135 + | BitArraySize::Variable { location, .. } 2136 + | BitArraySize::BinaryOperator { location, .. } => *location, 2111 2137 } 2112 2138 } 2113 2139 }
+4
compiler-core/src/ast/visit.rs
··· 1612 1612 constructor, 1613 1613 type_, 1614 1614 } => v.visit_typed_bit_array_size_variable(location, name, constructor, type_), 1615 + BitArraySize::BinaryOperator { left, right, .. } => { 1616 + v.visit_typed_pattern_bit_array_size(left); 1617 + v.visit_typed_pattern_bit_array_size(right); 1618 + } 1615 1619 } 1616 1620 } 1617 1621
+11
compiler-core/src/ast_folder.rs
··· 1317 1317 BitArraySize::Variable { location, name, .. } => { 1318 1318 self.fold_bit_array_size_variable(location, name) 1319 1319 } 1320 + BitArraySize::BinaryOperator { 1321 + location, 1322 + operator, 1323 + left, 1324 + right, 1325 + } => BitArraySize::BinaryOperator { 1326 + location, 1327 + operator, 1328 + left: Box::new(self.fold_bit_array_size(*left)), 1329 + right: Box::new(self.fold_bit_array_size(*right)), 1330 + }, 1320 1331 } 1321 1332 } 1322 1333
+4
compiler-core/src/call_graph.rs
··· 389 389 match size { 390 390 BitArraySize::Int { .. } => {} 391 391 BitArraySize::Variable { name, .. } => self.referenced(name), 392 + BitArraySize::BinaryOperator { left, right, .. } => { 393 + self.bit_array_size(left); 394 + self.bit_array_size(right); 395 + } 392 396 } 393 397 } 394 398
+22 -1
compiler-core/src/erlang/pattern.rs
··· 132 132 fn bit_array_size<'a>(size: &'a TypedBitArraySize, env: &mut Env<'a>) -> Document<'a> { 133 133 match size { 134 134 BitArraySize::Int { value, .. } => int(value), 135 - 136 135 BitArraySize::Variable { 137 136 name, constructor, .. 138 137 } => { ··· 146 145 } 147 146 _ => env.local_var_name(name), 148 147 } 148 + } 149 + 150 + BitArraySize::BinaryOperator { 151 + operator, 152 + left, 153 + right, 154 + .. 155 + } => { 156 + let operator = match operator { 157 + IntegerOperator::Add => " + ", 158 + IntegerOperator::Subtract => " - ", 159 + IntegerOperator::Multiply => " * ", 160 + // IntegerOperator::Divide => return int_div(left, right, "div", env), 161 + // IntegerOperator::Remainder => return int_div(left, right, "rem", env), 162 + _ => todo!(), 163 + }; 164 + 165 + docvec![ 166 + bit_array_size(left, env), 167 + operator, 168 + bit_array_size(right, env) 169 + ] 149 170 } 150 171 } 151 172 }
+1
compiler-core/src/exhaustiveness.rs
··· 3020 3020 unit: segment.unit(), 3021 3021 } 3022 3022 } 3023 + _ => todo!(), 3023 3024 } 3024 3025 } 3025 3026
+20
compiler-core/src/format.rs
··· 2294 2294 match size { 2295 2295 BitArraySize::Int { value, .. } => self.int(value), 2296 2296 BitArraySize::Variable { name, .. } => name.to_doc(), 2297 + BitArraySize::BinaryOperator { 2298 + left, 2299 + right, 2300 + operator, 2301 + .. 2302 + } => { 2303 + let operator = match operator { 2304 + IntegerOperator::Add => " + ", 2305 + IntegerOperator::Subtract => " - ", 2306 + IntegerOperator::Multiply => " * ", 2307 + IntegerOperator::Divide => " / ", 2308 + IntegerOperator::Remainder => " % ", 2309 + }; 2310 + 2311 + docvec![ 2312 + self.bit_array_size(left), 2313 + operator, 2314 + self.bit_array_size(right) 2315 + ] 2316 + } 2297 2317 } 2298 2318 } 2299 2319
+99 -4
compiler-core/src/parse.rs
··· 59 59 use crate::ast::{ 60 60 Arg, ArgNames, Assert, AssignName, Assignment, AssignmentKind, BinOp, BitArrayOption, 61 61 BitArraySegment, BitArraySize, CAPTURE_VARIABLE, CallArg, Clause, ClauseGuard, Constant, 62 - CustomType, Definition, Function, FunctionLiteralKind, HasLocation, Import, Module, 63 - ModuleConstant, Pattern, Publicity, RecordBeingUpdated, RecordConstructor, 62 + CustomType, Definition, Function, FunctionLiteralKind, HasLocation, Import, IntegerOperator, 63 + Module, ModuleConstant, Pattern, Publicity, RecordBeingUpdated, RecordConstructor, 64 64 RecordConstructorArg, SrcSpan, Statement, TargetedDefinition, TodoKind, TypeAlias, TypeAst, 65 65 TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, UnqualifiedImport, 66 66 UntypedArg, UntypedClause, UntypedClauseGuard, UntypedConstant, UntypedDefinition, UntypedExpr, ··· 3415 3415 } 3416 3416 3417 3417 fn expect_bit_array_pattern_segment_arg(&mut self) -> Result<UntypedPattern, ParseError> { 3418 - let size = match self.next_tok() { 3418 + Ok(Pattern::BitArraySize(self.expect_bit_array_size()?)) 3419 + } 3420 + 3421 + fn expect_bit_array_size(&mut self) -> Result<BitArraySize<()>, ParseError> { 3422 + let left = match self.next_tok() { 3419 3423 Some((start, Token::Name { name }, end)) => BitArraySize::Variable { 3420 3424 location: SrcSpan { start, end }, 3421 3425 name, ··· 3430 3434 _ => return self.next_tok_unexpected(vec!["A variable name or an integer".into()]), 3431 3435 }; 3432 3436 3433 - Ok(Pattern::BitArraySize(size)) 3437 + let Some((start, token, end)) = self.tok0.take() else { 3438 + return Ok(left); 3439 + }; 3440 + 3441 + match token { 3442 + Token::Plus => { 3443 + _ = self.next_tok(); 3444 + let right = self.expect_bit_array_size()?; 3445 + 3446 + Ok(self.bit_array_size_binary_operator(left, right, IntegerOperator::Add)) 3447 + } 3448 + Token::Minus => { 3449 + _ = self.next_tok(); 3450 + let right = self.expect_bit_array_size()?; 3451 + 3452 + Ok(self.bit_array_size_binary_operator(left, right, IntegerOperator::Subtract)) 3453 + } 3454 + Token::Star => { 3455 + _ = self.next_tok(); 3456 + let right = self.expect_bit_array_size()?; 3457 + 3458 + Ok(self.bit_array_size_high_precedence_operator( 3459 + left, 3460 + right, 3461 + IntegerOperator::Multiply, 3462 + )) 3463 + } 3464 + Token::Slash => { 3465 + _ = self.next_tok(); 3466 + let right = self.expect_bit_array_size()?; 3467 + 3468 + Ok(self.bit_array_size_high_precedence_operator( 3469 + left, 3470 + right, 3471 + IntegerOperator::Divide, 3472 + )) 3473 + } 3474 + Token::Percent => { 3475 + _ = self.next_tok(); 3476 + let right = self.expect_bit_array_size()?; 3477 + 3478 + Ok(self.bit_array_size_high_precedence_operator( 3479 + left, 3480 + right, 3481 + IntegerOperator::Remainder, 3482 + )) 3483 + } 3484 + _ => { 3485 + self.tok0 = Some((start, token, end)); 3486 + Ok(left) 3487 + } 3488 + } 3489 + } 3490 + 3491 + fn bit_array_size_binary_operator( 3492 + &self, 3493 + left: BitArraySize<()>, 3494 + right: BitArraySize<()>, 3495 + operator: IntegerOperator, 3496 + ) -> BitArraySize<()> { 3497 + let start = left.location().start; 3498 + let end = right.location().end; 3499 + 3500 + BitArraySize::BinaryOperator { 3501 + left: Box::new(left), 3502 + right: Box::new(right), 3503 + operator, 3504 + location: SrcSpan { start, end }, 3505 + } 3506 + } 3507 + 3508 + fn bit_array_size_high_precedence_operator( 3509 + &self, 3510 + left: BitArraySize<()>, 3511 + right: BitArraySize<()>, 3512 + operator: IntegerOperator, 3513 + ) -> BitArraySize<()> { 3514 + match right { 3515 + BitArraySize::Int { .. } | BitArraySize::Variable { .. } => { 3516 + self.bit_array_size_binary_operator(left, right, operator) 3517 + } 3518 + BitArraySize::BinaryOperator { 3519 + operator: o2, 3520 + left: right_left, 3521 + right, 3522 + .. 3523 + } => self.bit_array_size_binary_operator( 3524 + self.bit_array_size_binary_operator(left, *right_left, operator), 3525 + *right, 3526 + o2, 3527 + ), 3528 + } 3434 3529 } 3435 3530 3436 3531 fn expect_const_int(&mut self) -> Result<UntypedConstant, ParseError> {
+135
compiler-core/src/parse/snapshots/gleam_core__parse__tests__correct_precedence_in_pattern_size.snap
··· 1 + --- 2 + source: compiler-core/src/parse/tests.rs 3 + expression: "let assert <<size, payload:size(size + 2 * 8)>> = <<>>" 4 + --- 5 + [ 6 + Assignment( 7 + Assignment { 8 + location: SrcSpan { 9 + start: 0, 10 + end: 54, 11 + }, 12 + value: BitArray { 13 + location: SrcSpan { 14 + start: 50, 15 + end: 54, 16 + }, 17 + segments: [], 18 + }, 19 + pattern: BitArray { 20 + location: SrcSpan { 21 + start: 11, 22 + end: 47, 23 + }, 24 + segments: [ 25 + BitArraySegment { 26 + location: SrcSpan { 27 + start: 13, 28 + end: 17, 29 + }, 30 + value: Variable { 31 + location: SrcSpan { 32 + start: 13, 33 + end: 17, 34 + }, 35 + name: "size", 36 + type_: (), 37 + origin: VariableOrigin { 38 + syntax: Variable( 39 + "size", 40 + ), 41 + declaration: LetPattern, 42 + }, 43 + }, 44 + options: [], 45 + type_: (), 46 + }, 47 + BitArraySegment { 48 + location: SrcSpan { 49 + start: 19, 50 + end: 45, 51 + }, 52 + value: Variable { 53 + location: SrcSpan { 54 + start: 19, 55 + end: 26, 56 + }, 57 + name: "payload", 58 + type_: (), 59 + origin: VariableOrigin { 60 + syntax: Variable( 61 + "payload", 62 + ), 63 + declaration: LetPattern, 64 + }, 65 + }, 66 + options: [ 67 + Size { 68 + location: SrcSpan { 69 + start: 27, 70 + end: 45, 71 + }, 72 + value: BitArraySize( 73 + BinaryOperator { 74 + location: SrcSpan { 75 + start: 32, 76 + end: 44, 77 + }, 78 + operator: Add, 79 + left: Variable { 80 + location: SrcSpan { 81 + start: 32, 82 + end: 36, 83 + }, 84 + name: "size", 85 + constructor: None, 86 + type_: (), 87 + }, 88 + right: BinaryOperator { 89 + location: SrcSpan { 90 + start: 39, 91 + end: 44, 92 + }, 93 + operator: Multiply, 94 + left: Int { 95 + location: SrcSpan { 96 + start: 39, 97 + end: 40, 98 + }, 99 + value: "2", 100 + int_value: 2, 101 + }, 102 + right: Int { 103 + location: SrcSpan { 104 + start: 43, 105 + end: 44, 106 + }, 107 + value: "8", 108 + int_value: 8, 109 + }, 110 + }, 111 + }, 112 + ), 113 + short_form: false, 114 + }, 115 + ], 116 + type_: (), 117 + }, 118 + ], 119 + }, 120 + kind: Assert { 121 + location: SrcSpan { 122 + start: 0, 123 + end: 10, 124 + }, 125 + assert_keyword_start: 4, 126 + message: None, 127 + }, 128 + compiled_case: CompiledCase { 129 + tree: Fail, 130 + subject_variables: [], 131 + }, 132 + annotation: None, 133 + }, 134 + ), 135 + ]
+120
compiler-core/src/parse/snapshots/gleam_core__parse__tests__operator_in_pattern_size.snap
··· 1 + --- 2 + source: compiler-core/src/parse/tests.rs 3 + expression: "let assert <<size, payload:size(size - 1)>> = <<>>" 4 + --- 5 + [ 6 + Assignment( 7 + Assignment { 8 + location: SrcSpan { 9 + start: 0, 10 + end: 50, 11 + }, 12 + value: BitArray { 13 + location: SrcSpan { 14 + start: 46, 15 + end: 50, 16 + }, 17 + segments: [], 18 + }, 19 + pattern: BitArray { 20 + location: SrcSpan { 21 + start: 11, 22 + end: 43, 23 + }, 24 + segments: [ 25 + BitArraySegment { 26 + location: SrcSpan { 27 + start: 13, 28 + end: 17, 29 + }, 30 + value: Variable { 31 + location: SrcSpan { 32 + start: 13, 33 + end: 17, 34 + }, 35 + name: "size", 36 + type_: (), 37 + origin: VariableOrigin { 38 + syntax: Variable( 39 + "size", 40 + ), 41 + declaration: LetPattern, 42 + }, 43 + }, 44 + options: [], 45 + type_: (), 46 + }, 47 + BitArraySegment { 48 + location: SrcSpan { 49 + start: 19, 50 + end: 41, 51 + }, 52 + value: Variable { 53 + location: SrcSpan { 54 + start: 19, 55 + end: 26, 56 + }, 57 + name: "payload", 58 + type_: (), 59 + origin: VariableOrigin { 60 + syntax: Variable( 61 + "payload", 62 + ), 63 + declaration: LetPattern, 64 + }, 65 + }, 66 + options: [ 67 + Size { 68 + location: SrcSpan { 69 + start: 27, 70 + end: 41, 71 + }, 72 + value: BitArraySize( 73 + BinaryOperator { 74 + location: SrcSpan { 75 + start: 32, 76 + end: 40, 77 + }, 78 + operator: Subtract, 79 + left: Variable { 80 + location: SrcSpan { 81 + start: 32, 82 + end: 36, 83 + }, 84 + name: "size", 85 + constructor: None, 86 + type_: (), 87 + }, 88 + right: Int { 89 + location: SrcSpan { 90 + start: 39, 91 + end: 40, 92 + }, 93 + value: "1", 94 + int_value: 1, 95 + }, 96 + }, 97 + ), 98 + short_form: false, 99 + }, 100 + ], 101 + type_: (), 102 + }, 103 + ], 104 + }, 105 + kind: Assert { 106 + location: SrcSpan { 107 + start: 0, 108 + end: 10, 109 + }, 110 + assert_keyword_start: 4, 111 + message: None, 112 + }, 113 + compiled_case: CompiledCase { 114 + tree: Fail, 115 + subject_variables: [], 116 + }, 117 + annotation: None, 118 + }, 119 + ), 120 + ]
+10
compiler-core/src/parse/tests.rs
··· 1897 1897 fn doesnt_issue_special_error_for_pythonic_import_if_slash() { 1898 1898 assert_module_error!("import one/two.three"); 1899 1899 } 1900 + 1901 + #[test] 1902 + fn operator_in_pattern_size() { 1903 + assert_parse!("let assert <<size, payload:size(size - 1)>> = <<>>"); 1904 + } 1905 + 1906 + #[test] 1907 + fn correct_precedence_in_pattern_size() { 1908 + assert_parse!("let assert <<size, payload:size(size + 2 * 8)>> = <<>>"); 1909 + }
+30 -7
compiler-core/src/type_/pattern.rs
··· 11 11 use crate::{ 12 12 analyse::{self, Inferred, name::check_name_case}, 13 13 ast::{ 14 - AssignName, BitArrayOption, BitArraySize, ImplicitCallArgOrigin, Layer, 14 + AssignName, BitArrayOption, BitArraySize, ImplicitCallArgOrigin, Layer, TypedBitArraySize, 15 15 UntypedPatternBitArraySegment, 16 16 }, 17 17 parse::PatternPosition, ··· 621 621 } 622 622 } 623 623 624 - Pattern::BitArraySize(size) => self.bit_array_size(size, type_), 624 + Pattern::BitArraySize(size) => { 625 + let location = size.location(); 626 + match self.bit_array_size(size, type_.clone()) { 627 + Ok(size) => Pattern::BitArraySize(size), 628 + Err(error) => { 629 + self.error(error); 630 + Pattern::Invalid { location, type_ } 631 + } 632 + } 633 + } 625 634 626 635 Pattern::StringPrefix { 627 636 location, ··· 1188 1197 .collect() 1189 1198 } 1190 1199 1191 - fn bit_array_size(&mut self, size: BitArraySize<()>, type_: Arc<Type>) -> TypedPattern { 1200 + fn bit_array_size( 1201 + &mut self, 1202 + size: BitArraySize<()>, 1203 + type_: Arc<Type>, 1204 + ) -> Result<TypedBitArraySize, Error> { 1192 1205 let typed_size = match size { 1193 1206 BitArraySize::Int { 1194 1207 location, ··· 1209 1222 int_value, 1210 1223 } 1211 1224 } 1212 - 1213 1225 BitArraySize::Variable { name, location, .. } => { 1214 1226 let constructor = match self.variables.get_mut(&name) { 1215 1227 // If we've bound a variable in the current bit array pattern, ··· 1226 1238 Some(_) | None => match self.environment.get_variable(&name) { 1227 1239 Some(constructor) => constructor.clone(), 1228 1240 None => { 1229 - self.error(Error::UnknownVariable { 1241 + return Err(Error::UnknownVariable { 1230 1242 location, 1231 1243 name: name.clone(), 1232 1244 variables: self.environment.local_value_names(), ··· 1241 1253 .keys() 1242 1254 .any(|type_| type_ == &name), 1243 1255 }); 1244 - return Pattern::Invalid { location, type_ }; 1245 1256 } 1246 1257 }, 1247 1258 }; ··· 1261 1272 type_, 1262 1273 } 1263 1274 } 1275 + 1276 + BitArraySize::BinaryOperator { 1277 + location, 1278 + operator, 1279 + left, 1280 + right, 1281 + } => BitArraySize::BinaryOperator { 1282 + location, 1283 + operator, 1284 + left: Box::new(self.bit_array_size(*left, type_.clone())?), 1285 + right: Box::new(self.bit_array_size(*right, type_)?), 1286 + }, 1264 1287 }; 1265 1288 1266 - Pattern::BitArraySize(typed_size) 1289 + Ok(typed_size) 1267 1290 } 1268 1291 1269 1292 fn check_name_case(&mut self, location: SrcSpan, name: &EcoString, kind: Named) {