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

Configure Feed

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

Replace `Pattern::VarUsage` with `Pattern::BitArraySize`

+312 -166
+41 -16
compiler-core/src/ast.rs
··· 2015 2015 origin: VariableOrigin, 2016 2016 }, 2017 2017 2018 - /// A reference to a variable in a bit array. This is always a variable 2019 - /// being used rather than a new variable being assigned. 2020 - /// e.g. `assert <<y:size(somevar)>> = x` 2021 - VarUsage { 2022 - location: SrcSpan, 2023 - name: EcoString, 2024 - constructor: Option<ValueConstructor>, 2025 - type_: Type, 2026 - }, 2018 + /// The specified size of a bit array. This can either be a literal integer, 2019 + /// a reference to a variable, or a maths expression. 2020 + /// e.g. `let assert <<y:size(somevar)>> = x` 2021 + BitArraySize(BitArraySize<Type>), 2027 2022 2028 2023 /// A name given to a sub-pattern using the `as` keyword. 2029 2024 /// e.g. `assert #(1, [_, _] as the_list) = x` ··· 2089 2084 }, 2090 2085 } 2091 2086 2087 + pub type TypedBitArraySize = BitArraySize<Arc<Type>>; 2088 + 2089 + #[derive(Debug, Clone, PartialEq, Eq)] 2090 + pub enum BitArraySize<Type> { 2091 + Int { 2092 + location: SrcSpan, 2093 + value: EcoString, 2094 + int_value: BigInt, 2095 + }, 2096 + 2097 + Variable { 2098 + location: SrcSpan, 2099 + name: EcoString, 2100 + constructor: Option<ValueConstructor>, 2101 + type_: Type, 2102 + }, 2103 + } 2104 + 2105 + impl<T> BitArraySize<T> { 2106 + pub fn location(&self) -> SrcSpan { 2107 + match self { 2108 + BitArraySize::Int { location, .. } | BitArraySize::Variable { location, .. } => { 2109 + *location 2110 + } 2111 + } 2112 + } 2113 + } 2114 + 2092 2115 impl Default for Inferred<()> { 2093 2116 fn default() -> Self { 2094 2117 Self::Unknown ··· 2131 2154 } => SrcSpan::new(pattern.location().start, location.end), 2132 2155 Pattern::Int { location, .. } 2133 2156 | Pattern::Variable { location, .. } 2134 - | Pattern::VarUsage { location, .. } 2135 2157 | Pattern::List { location, .. } 2136 2158 | Pattern::Float { location, .. } 2137 2159 | Pattern::Discard { location, .. } ··· 2141 2163 | Pattern::StringPrefix { location, .. } 2142 2164 | Pattern::BitArray { location, .. } 2143 2165 | Pattern::Invalid { location, .. } => *location, 2166 + Pattern::BitArraySize(size) => size.location(), 2144 2167 } 2145 2168 } 2146 2169 ··· 2173 2196 | Pattern::Float { .. } 2174 2197 | Pattern::String { .. } 2175 2198 | Pattern::Variable { .. } 2176 - | Pattern::VarUsage { .. } 2199 + | Pattern::BitArraySize { .. } 2177 2200 | Pattern::Assign { .. } 2178 2201 | Pattern::Discard { .. } 2179 2202 | Pattern::List { .. } ··· 2192 2215 | Pattern::Float { .. } 2193 2216 | Pattern::String { .. } 2194 2217 | Pattern::Variable { .. } 2195 - | Pattern::VarUsage { .. } 2218 + | Pattern::BitArraySize { .. } 2196 2219 | Pattern::Assign { .. } 2197 2220 | Pattern::Discard { .. } 2198 2221 | Pattern::List { .. } ··· 2215 2238 2216 2239 Pattern::Variable { type_, .. } 2217 2240 | Pattern::List { type_, .. } 2218 - | Pattern::VarUsage { type_, .. } 2219 2241 | Pattern::Constructor { type_, .. } 2220 2242 | Pattern::Invalid { type_, .. } => type_.clone(), 2221 2243 2222 2244 Pattern::Assign { pattern, .. } => pattern.type_(), 2223 2245 2246 + // Bit array sizes should always be integers 2247 + Pattern::BitArraySize(_) => type_::int(), 2248 + 2224 2249 Pattern::Discard { type_, .. } => type_.clone(), 2225 2250 2226 2251 Pattern::Tuple { elements, .. } => { ··· 2246 2271 | Pattern::Float { .. } 2247 2272 | Pattern::String { .. } 2248 2273 | Pattern::Variable { .. } 2249 - | Pattern::VarUsage { .. } 2274 + | Pattern::BitArraySize { .. } 2250 2275 | Pattern::Assign { .. } 2251 2276 | Pattern::Discard { .. } 2252 2277 | Pattern::StringPrefix { .. } ··· 2329 2354 Pattern::Int { .. } 2330 2355 | Pattern::Float { .. } 2331 2356 | Pattern::String { .. } 2332 - | Pattern::VarUsage { .. } 2357 + | Pattern::BitArraySize { .. } 2333 2358 | Pattern::List { .. } 2334 2359 | Pattern::Constructor { .. } 2335 2360 | Pattern::BitArray { .. } ··· 2501 2526 | Pattern::Float { .. } 2502 2527 | Pattern::String { .. } 2503 2528 | Pattern::Variable { .. } 2504 - | Pattern::VarUsage { .. } 2529 + | Pattern::BitArraySize { .. } 2505 2530 | Pattern::Discard { .. } 2506 2531 | Pattern::List { .. } 2507 2532 | Pattern::Constructor { .. }
+42 -10
compiler-core/src/ast/visit.rs
··· 40 40 41 41 use crate::{ 42 42 analyse::Inferred, 43 + ast::{BitArraySize, TypedBitArraySize}, 43 44 exhaustiveness::CompiledCase, 44 45 type_::{ 45 46 ModuleValueConstructor, PatternConstructor, TypedCallArg, ValueConstructor, ··· 436 437 visit_typed_pattern_variable(self, location, name, type_, origin); 437 438 } 438 439 439 - fn visit_typed_pattern_var_usage( 440 + fn visit_typed_pattern_bit_array_size(&mut self, size: &'ast TypedBitArraySize) { 441 + visit_typed_pattern_bit_array_size(self, size); 442 + } 443 + 444 + fn visit_typed_bit_array_size_int(&mut self, location: &'ast SrcSpan, value: &'ast EcoString) { 445 + visit_typed_bit_array_size_int(self, location, value) 446 + } 447 + 448 + fn visit_typed_bit_array_size_variable( 440 449 &mut self, 441 450 location: &'ast SrcSpan, 442 451 name: &'ast EcoString, 443 452 constructor: &'ast Option<ValueConstructor>, 444 453 type_: &'ast Arc<Type>, 445 454 ) { 446 - visit_typed_pattern_var_usage(self, location, name, constructor, type_); 455 + visit_typed_bit_array_size_variable(self, location, name, constructor, type_) 447 456 } 448 457 449 458 fn visit_typed_pattern_assign( ··· 1499 1508 type_, 1500 1509 origin, 1501 1510 } => v.visit_typed_pattern_variable(location, name, type_, origin), 1502 - Pattern::VarUsage { 1503 - location, 1504 - name, 1505 - constructor, 1506 - type_, 1507 - } => v.visit_typed_pattern_var_usage(location, name, constructor, type_), 1511 + Pattern::BitArraySize(size) => v.visit_typed_pattern_bit_array_size(size), 1508 1512 Pattern::Assign { 1509 1513 location, 1510 1514 name, ··· 1592 1596 { 1593 1597 } 1594 1598 1595 - pub fn visit_typed_pattern_var_usage<'a, V>( 1599 + pub fn visit_typed_pattern_bit_array_size<'a, V>(v: &mut V, size: &'a TypedBitArraySize) 1600 + where 1601 + V: Visit<'a> + ?Sized, 1602 + { 1603 + match size { 1604 + BitArraySize::Int { 1605 + location, 1606 + value, 1607 + int_value: _, 1608 + } => v.visit_typed_bit_array_size_int(location, value), 1609 + BitArraySize::Variable { 1610 + location, 1611 + name, 1612 + constructor, 1613 + type_, 1614 + } => v.visit_typed_bit_array_size_variable(location, name, constructor, type_), 1615 + } 1616 + } 1617 + 1618 + pub fn visit_typed_bit_array_size_int<'a, V>( 1619 + _v: &mut V, 1620 + _location: &'a SrcSpan, 1621 + _value: &'a EcoString, 1622 + ) where 1623 + V: Visit<'a> + ?Sized, 1624 + { 1625 + } 1626 + 1627 + pub fn visit_typed_bit_array_size_variable<'a, V>( 1596 1628 _v: &mut V, 1597 1629 _location: &'a SrcSpan, 1598 1630 _name: &'a EcoString, 1599 1631 _constructor: &'a Option<ValueConstructor>, 1600 - _type: &'a Arc<Type>, 1632 + _type_: &'a Arc<Type>, 1601 1633 ) where 1602 1634 V: Visit<'a> + ?Sized, 1603 1635 {
+42 -13
compiler-core/src/ast_folder.rs
··· 5 5 use crate::{ 6 6 analyse::Inferred, 7 7 ast::{ 8 - Assert, AssignName, Assignment, BinOp, CallArg, Constant, Definition, FunctionLiteralKind, 9 - Pattern, RecordBeingUpdated, SrcSpan, Statement, TargetedDefinition, TodoKind, TypeAst, 10 - TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, UntypedArg, 11 - UntypedAssert, UntypedAssignment, UntypedClause, UntypedConstant, 8 + Assert, AssignName, Assignment, BinOp, BitArraySize, CallArg, Constant, Definition, 9 + FunctionLiteralKind, Pattern, RecordBeingUpdated, SrcSpan, Statement, TargetedDefinition, 10 + TodoKind, TypeAst, TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, 11 + UntypedArg, UntypedAssert, UntypedAssignment, UntypedClause, UntypedConstant, 12 12 UntypedConstantBitArraySegment, UntypedCustomType, UntypedDefinition, UntypedExpr, 13 13 UntypedExprBitArraySegment, UntypedFunction, UntypedImport, UntypedModule, 14 14 UntypedModuleConstant, UntypedPattern, UntypedPatternBitArraySegment, ··· 1203 1203 origin, 1204 1204 } => self.fold_pattern_var(location, name, origin), 1205 1205 1206 - Pattern::VarUsage { 1207 - location, 1208 - name, 1209 - constructor: _, 1210 - type_: (), 1211 - } => self.fold_pattern_var_usage(location, name), 1206 + Pattern::BitArraySize(size) => self.fold_pattern_bit_array_size(size), 1212 1207 1213 1208 Pattern::Assign { 1214 1209 name, ··· 1308 1303 } 1309 1304 } 1310 1305 1311 - fn fold_pattern_var_usage(&mut self, location: SrcSpan, name: EcoString) -> UntypedPattern { 1312 - Pattern::VarUsage { 1306 + fn fold_pattern_bit_array_size(&mut self, size: BitArraySize<()>) -> UntypedPattern { 1307 + Pattern::BitArraySize(self.fold_bit_array_size(size)) 1308 + } 1309 + 1310 + fn fold_bit_array_size(&mut self, size: BitArraySize<()>) -> BitArraySize<()> { 1311 + match size { 1312 + BitArraySize::Int { 1313 + location, 1314 + value, 1315 + int_value, 1316 + } => self.fold_bit_array_size_int(location, value, int_value), 1317 + BitArraySize::Variable { location, name, .. } => { 1318 + self.fold_bit_array_size_variable(location, name) 1319 + } 1320 + } 1321 + } 1322 + 1323 + fn fold_bit_array_size_int( 1324 + &mut self, 1325 + location: SrcSpan, 1326 + value: EcoString, 1327 + int_value: BigInt, 1328 + ) -> BitArraySize<()> { 1329 + BitArraySize::Int { 1330 + location, 1331 + value, 1332 + int_value, 1333 + } 1334 + } 1335 + 1336 + fn fold_bit_array_size_variable( 1337 + &mut self, 1338 + location: SrcSpan, 1339 + name: EcoString, 1340 + ) -> BitArraySize<()> { 1341 + BitArraySize::Variable { 1313 1342 location, 1314 1343 name, 1315 1344 constructor: None, ··· 1423 1452 | Pattern::Float { .. } 1424 1453 | Pattern::String { .. } 1425 1454 | Pattern::Discard { .. } 1426 - | Pattern::VarUsage { .. } 1455 + | Pattern::BitArraySize { .. } 1427 1456 | Pattern::StringPrefix { .. } 1428 1457 | Pattern::Invalid { .. } => pattern, 1429 1458
+6 -4
compiler-core/src/bit_array.rs
··· 344 344 345 345 impl GetLiteralValue for ast::TypedPattern { 346 346 fn as_int_literal(&self) -> Option<BigInt> { 347 - if let ast::Pattern::Int { int_value, .. } = self { 348 - Some(int_value.clone()) 349 - } else { 350 - None 347 + match self { 348 + ast::Pattern::Int { int_value, .. } 349 + | ast::Pattern::BitArraySize(ast::BitArraySize::Int { int_value, .. }) => { 350 + Some(int_value.clone()) 351 + } 352 + _ => None, 351 353 } 352 354 } 353 355 }
+12 -5
compiler-core/src/call_graph.rs
··· 7 7 use crate::{ 8 8 Result, 9 9 ast::{ 10 - AssignName, AssignmentKind, BitArrayOption, ClauseGuard, Constant, Pattern, SrcSpan, 11 - Statement, UntypedClauseGuard, UntypedExpr, UntypedFunction, UntypedModuleConstant, 12 - UntypedPattern, UntypedStatement, 10 + AssignName, AssignmentKind, BitArrayOption, BitArraySize, ClauseGuard, Constant, Pattern, 11 + SrcSpan, Statement, UntypedClauseGuard, UntypedExpr, UntypedFunction, 12 + UntypedModuleConstant, UntypedPattern, UntypedStatement, 13 13 }, 14 14 type_::Error, 15 15 }; ··· 359 359 } 360 360 } 361 361 362 - Pattern::VarUsage { name, .. } => { 363 - self.referenced(name); 362 + Pattern::BitArraySize(size) => { 363 + self.bit_array_size(size); 364 364 } 365 365 366 366 Pattern::Assign { name, pattern, .. } => { ··· 382 382 self.pattern(&segment.value); 383 383 } 384 384 } 385 + } 386 + } 387 + 388 + fn bit_array_size(&mut self, size: &'a BitArraySize<()>) { 389 + match size { 390 + BitArraySize::Int { .. } => {} 391 + BitArraySize::Variable { name, .. } => self.referenced(name), 385 392 } 386 393 } 387 394
+22 -14
compiler-core/src/erlang/pattern.rs
··· 37 37 38 38 Pattern::Discard { .. } => "_".to_doc(), 39 39 40 - Pattern::VarUsage { 41 - name, constructor, .. 42 - } => { 43 - let v = &constructor 44 - .as_ref() 45 - .expect("Constructor not found for variable usage") 46 - .variant; 47 - match v { 48 - ValueConstructorVariant::ModuleConstant { literal, .. } => { 49 - const_inline(literal, env) 50 - } 51 - _ => env.local_var_name(name), 52 - } 53 - } 40 + Pattern::BitArraySize(size) => bit_array_size(size, env), 54 41 55 42 Pattern::Variable { name, .. } => { 56 43 vars.push(name); ··· 139 126 } 140 127 141 128 Pattern::Invalid { .. } => panic!("invalid patterns should not reach code generation"), 129 + } 130 + } 131 + 132 + fn bit_array_size<'a>(size: &'a TypedBitArraySize, env: &mut Env<'a>) -> Document<'a> { 133 + match size { 134 + BitArraySize::Int { value, .. } => int(value), 135 + 136 + BitArraySize::Variable { 137 + name, constructor, .. 138 + } => { 139 + let v = &constructor 140 + .as_ref() 141 + .expect("Constructor not found for variable usage") 142 + .variant; 143 + match v { 144 + ValueConstructorVariant::ModuleConstant { literal, .. } => { 145 + const_inline(literal, env) 146 + } 147 + _ => env.local_var_name(name), 148 + } 149 + } 142 150 } 143 151 } 144 152
+30 -20
compiler-core/src/exhaustiveness.rs
··· 63 63 pub mod printer; 64 64 65 65 use crate::{ 66 - ast::{self, AssignName, Endianness, TypedClause, TypedPattern, TypedPatternBitArraySegment}, 66 + ast::{ 67 + self, AssignName, BitArraySize, Endianness, TypedBitArraySize, TypedClause, TypedPattern, 68 + TypedPatternBitArraySegment, 69 + }, 67 70 strings::{convert_string_escape_chars, length_utf16, length_utf32}, 68 71 type_::{ 69 72 Environment, Opaque, Type, TypeValueConstructor, TypeValueConstructorField, TypeVar, ··· 2784 2787 }) 2785 2788 } 2786 2789 2787 - TypedPattern::VarUsage { .. } => { 2788 - unreachable!("Cannot convert VarUsage to exhaustiveness pattern") 2790 + TypedPattern::BitArraySize { .. } => { 2791 + unreachable!("Cannot convert BitArraySize to exhaustiveness pattern") 2789 2792 } 2790 2793 } 2791 2794 } ··· 2957 2960 let pattern = pattern.unwrap_or(&segment.value); 2958 2961 2959 2962 match segment.size() { 2960 - // Size could either be a constant or a variable usage. In either case 2961 - // we need to take the segment's unit into account! 2962 - Some(ast::Pattern::Int { int_value, .. }) => { 2963 - ReadSize::ConstantBits(int_value * segment.unit()) 2964 - } 2965 - Some(ast::Pattern::VarUsage { name, .. }) => { 2966 - let variable = match pattern_variables.get(name) { 2967 - Some(read_action) => { 2968 - VariableUsage::PatternSegment(name.clone(), read_action.clone()) 2969 - } 2970 - None => VariableUsage::OutsideVariable(name.clone()), 2971 - }; 2972 - ReadSize::VariableBits { 2973 - variable: Box::new(variable), 2974 - unit: segment.unit(), 2975 - } 2976 - } 2963 + // The size of a segment must be a `BitArraySize` pattern. 2964 + Some(ast::Pattern::BitArraySize(size)) => bit_array_size(segment, pattern_variables, size), 2977 2965 Some(x) => panic!("invalid pattern size made it to code generation {x:?}"), 2978 2966 2979 2967 // If a segment has the `bits`/`bytes` option and has no size, that ··· 3010 2998 // In all other cases the segment is considered to be 64 bits. 3011 2999 _ => ReadSize::ConstantBits(64.into()), 3012 3000 }, 3001 + } 3002 + } 3003 + 3004 + fn bit_array_size( 3005 + segment: &TypedPatternBitArraySegment, 3006 + pattern_variables: &HashMap<EcoString, ReadAction>, 3007 + size: &TypedBitArraySize, 3008 + ) -> ReadSize { 3009 + match size { 3010 + BitArraySize::Int { int_value, .. } => ReadSize::ConstantBits(int_value * segment.unit()), 3011 + BitArraySize::Variable { name, .. } => { 3012 + let variable = match pattern_variables.get(name) { 3013 + Some(read_action) => { 3014 + VariableUsage::PatternSegment(name.clone(), read_action.clone()) 3015 + } 3016 + None => VariableUsage::OutsideVariable(name.clone()), 3017 + }; 3018 + ReadSize::VariableBits { 3019 + variable: Box::new(variable), 3020 + unit: segment.unit(), 3021 + } 3022 + } 3013 3023 } 3014 3024 } 3015 3025
+8 -1
compiler-core/src/format.rs
··· 2226 2226 2227 2227 Pattern::Variable { name, .. } => name.to_doc(), 2228 2228 2229 - Pattern::VarUsage { name, .. } => name.to_doc(), 2229 + Pattern::BitArraySize(size) => self.bit_array_size(size), 2230 2230 2231 2231 Pattern::Assign { name, pattern, .. } => { 2232 2232 self.pattern(pattern).append(" as ").append(name.as_str()) ··· 2288 2288 Pattern::Invalid { .. } => panic!("invalid patterns can not be in an untyped ast"), 2289 2289 }; 2290 2290 commented(doc, comments) 2291 + } 2292 + 2293 + fn bit_array_size<'a>(&mut self, size: &'a BitArraySize<()>) -> Document<'a> { 2294 + match size { 2295 + BitArraySize::Int { value, .. } => self.int(value), 2296 + BitArraySize::Variable { name, .. } => name.to_doc(), 2297 + } 2291 2298 } 2292 2299 2293 2300 fn list_pattern<'a>(
+4 -4
compiler-core/src/language_server/reference.rs
··· 6 6 use crate::{ 7 7 analyse, 8 8 ast::{ 9 - self, ArgNames, CustomType, Definition, Function, ModuleConstant, Pattern, 9 + self, ArgNames, BitArraySize, CustomType, Definition, Function, ModuleConstant, Pattern, 10 10 RecordConstructor, SrcSpan, TypedExpr, TypedModule, visit::Visit, 11 11 }, 12 12 build::Located, ··· 80 80 origin: Some(origin.clone()), 81 81 name: name.clone(), 82 82 }), 83 - Located::Pattern(Pattern::VarUsage { 83 + Located::Pattern(Pattern::BitArraySize(BitArraySize::Variable { 84 84 constructor, 85 85 location, 86 86 name, 87 87 .. 88 - }) => constructor 88 + })) => constructor 89 89 .as_ref() 90 90 .and_then(|constructor| match &constructor.variant { 91 91 ValueConstructorVariant::LocalVariable { ··· 477 477 } 478 478 } 479 479 480 - fn visit_typed_pattern_var_usage( 480 + fn visit_typed_bit_array_size_variable( 481 481 &mut self, 482 482 location: &'ast SrcSpan, 483 483 _name: &'ast EcoString,
+21 -24
compiler-core/src/parse.rs
··· 58 58 use crate::analyse::Inferred; 59 59 use crate::ast::{ 60 60 Arg, ArgNames, Assert, AssignName, Assignment, AssignmentKind, BinOp, BitArrayOption, 61 - BitArraySegment, CAPTURE_VARIABLE, CallArg, Clause, ClauseGuard, Constant, CustomType, 62 - Definition, Function, FunctionLiteralKind, HasLocation, Import, Module, ModuleConstant, 63 - Pattern, Publicity, RecordBeingUpdated, RecordConstructor, RecordConstructorArg, SrcSpan, 64 - Statement, TargetedDefinition, TodoKind, TypeAlias, TypeAst, TypeAstConstructor, TypeAstFn, 65 - TypeAstHole, TypeAstTuple, TypeAstVar, UnqualifiedImport, UntypedArg, UntypedClause, 66 - UntypedClauseGuard, UntypedConstant, UntypedDefinition, UntypedExpr, UntypedModule, 67 - UntypedPattern, UntypedRecordUpdateArg, UntypedStatement, UntypedUseAssignment, Use, 68 - UseAssignment, 61 + BitArraySegment, BitArraySize, CAPTURE_VARIABLE, CallArg, Clause, ClauseGuard, Constant, 62 + CustomType, Definition, Function, FunctionLiteralKind, HasLocation, Import, Module, 63 + ModuleConstant, Pattern, Publicity, RecordBeingUpdated, RecordConstructor, 64 + RecordConstructorArg, SrcSpan, Statement, TargetedDefinition, TodoKind, TypeAlias, TypeAst, 65 + TypeAstConstructor, TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, UnqualifiedImport, 66 + UntypedArg, UntypedClause, UntypedClauseGuard, UntypedConstant, UntypedDefinition, UntypedExpr, 67 + UntypedModule, UntypedPattern, UntypedRecordUpdateArg, UntypedStatement, UntypedUseAssignment, 68 + Use, UseAssignment, 69 69 }; 70 70 use crate::build::Target; 71 71 use crate::error::wrap; ··· 1406 1406 x => x, 1407 1407 }, 1408 1408 &Parser::expect_bit_array_pattern_segment_arg, 1409 - &bit_array_pattern_int, 1409 + &bit_array_size_int, 1410 1410 ) 1411 1411 }, 1412 1412 Some(&Token::Comma), ··· 3415 3415 } 3416 3416 3417 3417 fn expect_bit_array_pattern_segment_arg(&mut self) -> Result<UntypedPattern, ParseError> { 3418 - match self.next_tok() { 3419 - Some((start, Token::Name { name }, end)) => Ok(Pattern::VarUsage { 3418 + let size = match self.next_tok() { 3419 + Some((start, Token::Name { name }, end)) => BitArraySize::Variable { 3420 3420 location: SrcSpan { start, end }, 3421 3421 name, 3422 3422 constructor: None, 3423 3423 type_: (), 3424 - }), 3425 - Some((start, Token::Int { value, int_value }, end)) => Ok(Pattern::Int { 3424 + }, 3425 + Some((start, Token::Int { value, int_value }, end)) => BitArraySize::Int { 3426 3426 location: SrcSpan { start, end }, 3427 3427 value, 3428 3428 int_value, 3429 - }), 3430 - _ => self.next_tok_unexpected(vec!["A variable name or an integer".into()]), 3431 - } 3429 + }, 3430 + _ => return self.next_tok_unexpected(vec!["A variable name or an integer".into()]), 3431 + }; 3432 + 3433 + Ok(Pattern::BitArraySize(size)) 3432 3434 } 3433 3435 3434 3436 fn expect_const_int(&mut self) -> Result<UntypedConstant, ParseError> { ··· 4289 4291 // BitArrays in patterns, guards, and expressions have a very similar structure 4290 4292 // but need specific types. These are helpers for that. There is probably a 4291 4293 // rustier way to do this :) 4292 - fn bit_array_pattern_int( 4293 - value: EcoString, 4294 - int_value: BigInt, 4295 - start: u32, 4296 - end: u32, 4297 - ) -> UntypedPattern { 4298 - Pattern::Int { 4294 + fn bit_array_size_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedPattern { 4295 + Pattern::BitArraySize(BitArraySize::Int { 4299 4296 location: SrcSpan { start, end }, 4300 4297 value, 4301 4298 int_value, 4302 - } 4299 + }) 4303 4300 } 4304 4301 4305 4302 fn bit_array_expr_int(value: EcoString, int_value: BigInt, start: u32, end: u32) -> UntypedExpr {
+1 -1
compiler-core/src/type_/expression.rs
··· 4741 4741 pattern @ (Pattern::Int { .. } 4742 4742 | Pattern::Float { .. } 4743 4743 | Pattern::String { .. } 4744 - | Pattern::VarUsage { .. } 4744 + | Pattern::BitArraySize { .. } 4745 4745 | Pattern::Assign { .. } 4746 4746 | Pattern::List { .. } 4747 4747 | Pattern::Constructor { .. }
+83 -54
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, ImplicitCallArgOrigin, Layer, UntypedPatternBitArraySegment, 14 + AssignName, BitArrayOption, BitArraySize, ImplicitCallArgOrigin, Layer, 15 + UntypedPatternBitArraySegment, 15 16 }, 16 17 parse::PatternPosition, 17 18 reference::ReferenceKind, ··· 493 494 // Int segments that aren't a whole number of bytes 494 495 BitArrayOption::<TypedPattern>::Size { value, .. } if segment_type.is_int() => { 495 496 match &**value { 496 - Pattern::<_>::Int { 497 + Pattern::BitArraySize(BitArraySize::Int { 497 498 location, 498 499 int_value, 499 500 .. 500 - } if int_value % 8 != BigInt::ZERO => { 501 + }) if int_value % 8 != BigInt::ZERO => { 501 502 self.track_feature_usage( 502 503 FeatureKind::JavaScriptUnalignedBitArray, 503 504 *location, ··· 620 621 } 621 622 } 622 623 623 - Pattern::VarUsage { name, location, .. } => { 624 - let constructor = match self.variables.get_mut(&name) { 625 - // If we've bound a variable in the current bit array pattern, 626 - // we want to use that. 627 - Some(variable) if variable.in_scope() => { 628 - variable.usage = Usage::UsedInPattern; 629 - ValueConstructor::local_variable( 630 - variable.location, 631 - variable.origin.clone(), 632 - variable.type_.clone(), 633 - ) 634 - } 635 - // Otherwise, we check the local scope. 636 - Some(_) | None => match self.environment.get_variable(&name) { 637 - Some(constructor) => constructor.clone(), 638 - None => { 639 - self.error(Error::UnknownVariable { 640 - location, 641 - name: name.clone(), 642 - variables: self.environment.local_value_names(), 643 - discarded_location: self 644 - .environment 645 - .discarded_names 646 - .get(&eco_format!("_{name}")) 647 - .cloned(), 648 - type_with_name_in_scope: self 649 - .environment 650 - .module_types 651 - .keys() 652 - .any(|type_| type_ == &name), 653 - }); 654 - return Pattern::Invalid { location, type_ }; 655 - } 656 - }, 657 - }; 658 - 659 - self.environment.increment_usage(&name); 660 - let type_ = self.environment.instantiate( 661 - constructor.type_.clone(), 662 - &mut hashmap![], 663 - self.hydrator, 664 - ); 665 - self.unify_types(int(), type_.clone(), location); 666 - 667 - Pattern::VarUsage { 668 - name, 669 - location, 670 - constructor: Some(constructor), 671 - type_, 672 - } 673 - } 624 + Pattern::BitArraySize(size) => self.bit_array_size(size, type_), 674 625 675 626 Pattern::StringPrefix { 676 627 location, ··· 1235 1186 } 1236 1187 }) 1237 1188 .collect() 1189 + } 1190 + 1191 + fn bit_array_size(&mut self, size: BitArraySize<()>, type_: Arc<Type>) -> TypedPattern { 1192 + let typed_size = match size { 1193 + BitArraySize::Int { 1194 + location, 1195 + value, 1196 + int_value, 1197 + } => { 1198 + self.unify_types(type_, int(), location); 1199 + 1200 + if self.environment.target == Target::JavaScript 1201 + && !self.current_function.has_javascript_external 1202 + { 1203 + check_javascript_int_safety(&int_value, location, self.problems); 1204 + } 1205 + 1206 + BitArraySize::Int { 1207 + location, 1208 + value, 1209 + int_value, 1210 + } 1211 + } 1212 + 1213 + BitArraySize::Variable { name, location, .. } => { 1214 + let constructor = match self.variables.get_mut(&name) { 1215 + // If we've bound a variable in the current bit array pattern, 1216 + // we want to use that. 1217 + Some(variable) if variable.in_scope() => { 1218 + variable.usage = Usage::UsedInPattern; 1219 + ValueConstructor::local_variable( 1220 + variable.location, 1221 + variable.origin.clone(), 1222 + variable.type_.clone(), 1223 + ) 1224 + } 1225 + // Otherwise, we check the local scope. 1226 + Some(_) | None => match self.environment.get_variable(&name) { 1227 + Some(constructor) => constructor.clone(), 1228 + None => { 1229 + self.error(Error::UnknownVariable { 1230 + location, 1231 + name: name.clone(), 1232 + variables: self.environment.local_value_names(), 1233 + discarded_location: self 1234 + .environment 1235 + .discarded_names 1236 + .get(&eco_format!("_{name}")) 1237 + .cloned(), 1238 + type_with_name_in_scope: self 1239 + .environment 1240 + .module_types 1241 + .keys() 1242 + .any(|type_| type_ == &name), 1243 + }); 1244 + return Pattern::Invalid { location, type_ }; 1245 + } 1246 + }, 1247 + }; 1248 + 1249 + self.environment.increment_usage(&name); 1250 + let type_ = self.environment.instantiate( 1251 + constructor.type_.clone(), 1252 + &mut hashmap![], 1253 + self.hydrator, 1254 + ); 1255 + self.unify_types(int(), type_.clone(), location); 1256 + 1257 + BitArraySize::Variable { 1258 + name, 1259 + location, 1260 + constructor: Some(constructor), 1261 + type_, 1262 + } 1263 + } 1264 + }; 1265 + 1266 + Pattern::BitArraySize(typed_size) 1238 1267 } 1239 1268 1240 1269 fn check_name_case(&mut self, location: SrcSpan, name: &EcoString, kind: Named) {