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

Configure Feed

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

✨ Include parsed value for float literals

+183 -38
+2 -1
compiler-core/src/ast.rs
··· 15 15 use crate::bit_array; 16 16 use crate::build::{ExpressionPosition, Located, Target, module_erlang_name}; 17 17 use crate::exhaustiveness::CompiledCase; 18 - use crate::parse::SpannedString; 18 + use crate::parse::{LiteralFloatValue, SpannedString}; 19 19 use crate::type_::error::VariableOrigin; 20 20 use crate::type_::expression::{Implementations, Purity}; 21 21 use crate::type_::printer::Names; ··· 2356 2356 Float { 2357 2357 location: SrcSpan, 2358 2358 value: EcoString, 2359 + float_value: LiteralFloatValue, 2359 2360 }, 2360 2361 2361 2362 String {
+1
compiler-core/src/ast/constant.rs
··· 16 16 Float { 17 17 location: SrcSpan, 18 18 value: EcoString, 19 + float_value: LiteralFloatValue, 19 20 }, 20 21 21 22 String {
+2
compiler-core/src/ast/typed.rs
··· 6 6 use crate::{ 7 7 build::ExpressionPosition, 8 8 exhaustiveness::CompiledCase, 9 + parse::LiteralFloatValue, 9 10 type_::{HasType, Type, ValueConstructorVariant, bool}, 10 11 }; 11 12 ··· 22 23 location: SrcSpan, 23 24 type_: Arc<Type>, 24 25 value: EcoString, 26 + float_value: LiteralFloatValue, 25 27 }, 26 28 27 29 String {
+3
compiler-core/src/ast/untyped.rs
··· 1 1 use vec1::Vec1; 2 2 3 + use crate::parse::LiteralFloatValue; 4 + 3 5 use super::*; 4 6 5 7 #[derive(Debug, Clone, PartialEq, Eq)] ··· 13 15 Float { 14 16 location: SrcSpan, 15 17 value: EcoString, 18 + float_value: LiteralFloatValue, 16 19 }, 17 20 18 21 String {
+6 -1
compiler-core/src/ast/visit.rs
··· 774 774 location, 775 775 type_, 776 776 value, 777 + float_value: _, 777 778 } => v.visit_typed_expr_float(location, type_, value), 778 779 TypedExpr::String { 779 780 location, ··· 1568 1569 value, 1569 1570 int_value: _, 1570 1571 } => v.visit_typed_pattern_int(location, value), 1571 - Pattern::Float { location, value } => v.visit_typed_pattern_float(location, value), 1572 + Pattern::Float { 1573 + location, 1574 + value, 1575 + float_value: _, 1576 + } => v.visit_typed_pattern_float(location, value), 1572 1577 Pattern::String { location, value } => v.visit_typed_pattern_string(location, value), 1573 1578 Pattern::Variable { 1574 1579 location,
+49 -9
compiler-core/src/ast_folder.rs
··· 17 17 UntypedUseAssignment, Use, UseAssignment, 18 18 }, 19 19 build::Target, 20 + parse::LiteralFloatValue, 20 21 type_::error::VariableOrigin, 21 22 }; 22 23 ··· 258 259 value, 259 260 int_value, 260 261 } => self.fold_int(location, value, int_value), 261 - UntypedExpr::Float { location, value } => self.fold_float(location, value), 262 + UntypedExpr::Float { 263 + location, 264 + value, 265 + float_value, 266 + } => self.fold_float(location, value, float_value), 262 267 UntypedExpr::String { location, value } => self.fold_string(location, value), 263 268 264 269 UntypedExpr::Block { ··· 714 719 } 715 720 } 716 721 717 - fn fold_float(&mut self, location: SrcSpan, value: EcoString) -> UntypedExpr { 718 - UntypedExpr::Float { location, value } 722 + fn fold_float( 723 + &mut self, 724 + location: SrcSpan, 725 + value: EcoString, 726 + float_value: LiteralFloatValue, 727 + ) -> UntypedExpr { 728 + UntypedExpr::Float { 729 + location, 730 + value, 731 + float_value, 732 + } 719 733 } 720 734 721 735 fn fold_string(&mut self, location: SrcSpan, value: EcoString) -> UntypedExpr { ··· 937 951 int_value, 938 952 } => self.fold_constant_int(location, value, int_value), 939 953 940 - Constant::Float { location, value } => self.fold_constant_float(location, value), 954 + Constant::Float { 955 + location, 956 + value, 957 + float_value, 958 + } => self.fold_constant_float(location, value, float_value), 941 959 942 960 Constant::String { location, value } => self.fold_constant_string(location, value), 943 961 ··· 998 1016 } 999 1017 } 1000 1018 1001 - fn fold_constant_float(&mut self, location: SrcSpan, value: EcoString) -> UntypedConstant { 1002 - Constant::Float { location, value } 1019 + fn fold_constant_float( 1020 + &mut self, 1021 + location: SrcSpan, 1022 + value: EcoString, 1023 + float_value: LiteralFloatValue, 1024 + ) -> UntypedConstant { 1025 + Constant::Float { 1026 + location, 1027 + value, 1028 + float_value, 1029 + } 1003 1030 } 1004 1031 1005 1032 fn fold_constant_string(&mut self, location: SrcSpan, value: EcoString) -> UntypedConstant { ··· 1188 1215 int_value, 1189 1216 } => self.fold_pattern_int(location, value, int_value), 1190 1217 1191 - Pattern::Float { location, value } => self.fold_pattern_float(location, value), 1218 + Pattern::Float { 1219 + location, 1220 + value, 1221 + float_value, 1222 + } => self.fold_pattern_float(location, value, float_value), 1192 1223 1193 1224 Pattern::String { location, value } => self.fold_pattern_string(location, value), 1194 1225 ··· 1277 1308 } 1278 1309 } 1279 1310 1280 - fn fold_pattern_float(&mut self, location: SrcSpan, value: EcoString) -> UntypedPattern { 1281 - Pattern::Float { location, value } 1311 + fn fold_pattern_float( 1312 + &mut self, 1313 + location: SrcSpan, 1314 + value: EcoString, 1315 + float_value: LiteralFloatValue, 1316 + ) -> UntypedPattern { 1317 + Pattern::Float { 1318 + location, 1319 + value, 1320 + float_value, 1321 + } 1282 1322 } 1283 1323 1284 1324 fn fold_pattern_string(&mut self, location: SrcSpan, value: EcoString) -> UntypedPattern {
+3
compiler-core/src/metadata/module_decoder.rs
··· 12 12 }, 13 13 build::Origin, 14 14 line_numbers::{Character, LineNumbers}, 15 + parse::LiteralFloatValue, 15 16 reference::{Reference, ReferenceKind, ReferenceMap}, 16 17 schema_capnp::{self as schema, *}, 17 18 type_::{ ··· 396 397 Constant::Float { 397 398 location: Default::default(), 398 399 value: value.into(), 400 + float_value: LiteralFloatValue::parse(value) 401 + .expect("float value to parse as non-NaN f64"), 399 402 } 400 403 } 401 404
+5
compiler-core/src/metadata/tests.rs
··· 10 10 }, 11 11 build::Origin, 12 12 line_numbers::LineNumbers, 13 + parse::LiteralFloatValue, 13 14 reference::{Reference, ReferenceKind}, 14 15 type_::{ 15 16 self, Deprecation, ModuleInterface, Opaque, References, Type, TypeAliasConstructor, ··· 1056 1057 let module = constant_module(Constant::Float { 1057 1058 location: Default::default(), 1058 1059 value: "1.0".into(), 1060 + float_value: LiteralFloatValue::ONE, 1059 1061 }); 1060 1062 1061 1063 assert_eq!(roundtrip(&module), module); ··· 1084 1086 Constant::Float { 1085 1087 location: Default::default(), 1086 1088 value: "1.0".into(), 1089 + float_value: LiteralFloatValue::ONE, 1087 1090 }, 1088 1091 Constant::Tuple { 1089 1092 location: Default::default(), ··· 1096 1099 Constant::Float { 1097 1100 location: Default::default(), 1098 1101 value: "1.0".into(), 1102 + float_value: LiteralFloatValue::ONE, 1099 1103 }, 1100 1104 ], 1101 1105 }, ··· 1146 1150 value: Constant::Float { 1147 1151 location: Default::default(), 1148 1152 value: "0.0".into(), 1153 + float_value: LiteralFloatValue::ZERO, 1149 1154 }, 1150 1155 }, 1151 1156 CallArg {
+37 -3
compiler-core/src/parse.rs
··· 517 517 } 518 518 } 519 519 520 - Some((start, Token::Float { value }, end)) => { 520 + Some((start, Token::Float { value, float_value }, end)) => { 521 521 self.advance(); 522 522 UntypedExpr::Float { 523 523 location: SrcSpan { start, end }, 524 524 value, 525 + float_value, 525 526 } 526 527 } 527 528 ··· 1401 1402 int_value, 1402 1403 } 1403 1404 } 1404 - Some((start, Token::Float { value }, end)) => { 1405 + Some((start, Token::Float { value, float_value }, end)) => { 1405 1406 self.advance(); 1406 1407 Pattern::Float { 1407 1408 location: SrcSpan { start, end }, 1408 1409 value, 1410 + float_value, 1409 1411 } 1410 1412 } 1411 1413 Some((start, Token::Hash, _)) => { ··· 3117 3119 })) 3118 3120 } 3119 3121 3120 - Some((start, Token::Float { value }, end)) => { 3122 + Some((start, Token::Float { value, float_value }, end)) => { 3121 3123 self.advance(); 3122 3124 Ok(Some(Constant::Float { 3123 3125 value, 3124 3126 location: SrcSpan { start, end }, 3127 + float_value, 3125 3128 })) 3126 3129 } 3127 3130 ··· 4717 4720 } 4718 4721 } 4719 4722 } 4723 + 4724 + /// A thin f64 wrapper that does not permit NaN. 4725 + /// This allows us to implement `Eq`, which require reflexivity. 4726 + /// 4727 + /// Used for gleam float literals, which cannot be NaN. 4728 + /// While there is no syntax for "infinity", float literals 4729 + /// may overflow into (possibly negative) infinity on the JS target. 4730 + #[derive(Clone, Copy, Debug, PartialEq)] 4731 + pub struct LiteralFloatValue(f64); 4732 + 4733 + impl LiteralFloatValue { 4734 + pub const ONE: Self = LiteralFloatValue(1.0); 4735 + pub const ZERO: Self = LiteralFloatValue(0.0); 4736 + 4737 + /// Parse from a string, returning `None` if the string 4738 + /// is not a valid f64 or the float is `NaN`` 4739 + pub fn parse(value: &str) -> Option<Self> { 4740 + value 4741 + .replace("_", "") 4742 + .parse::<f64>() 4743 + .ok() 4744 + .filter(|f| !f.is_nan()) 4745 + .map(LiteralFloatValue) 4746 + } 4747 + 4748 + pub fn value(&self) -> f64 { 4749 + self.0 4750 + } 4751 + } 4752 + 4753 + impl Eq for LiteralFloatValue {}
+4
compiler-core/src/parse/lexer.rs
··· 1 1 use ecow::EcoString; 2 2 3 3 use crate::ast::SrcSpan; 4 + use crate::parse::LiteralFloatValue; 4 5 use crate::parse::error::{LexicalError, LexicalErrorType}; 5 6 use crate::parse::token::Token; 6 7 use std::char; ··· 621 622 value.push_str(&exponent_run); 622 623 } 623 624 let end_pos = self.get_pos(); 625 + let float_value = 626 + LiteralFloatValue::parse(&value).expect("float value to parse as non-NaN f64"); 624 627 Ok(( 625 628 start_pos, 626 629 Token::Float { 627 630 value: value.into(), 631 + float_value, 628 632 }, 629 633 end_pos, 630 634 ))
+6
compiler-core/src/parse/snapshots/gleam_core__parse__tests__nested_block.snap
··· 34 34 end: 9, 35 35 }, 36 36 value: "1.0", 37 + float_value: LiteralFloatValue( 38 + 1.0, 39 + ), 37 40 }, 38 41 ), 39 42 Expression( ··· 43 46 end: 13, 44 47 }, 45 48 value: "2.0", 49 + float_value: LiteralFloatValue( 50 + 2.0, 51 + ), 46 52 }, 47 53 ), 48 54 ],
+29 -8
compiler-core/src/parse/token.rs
··· 3 3 4 4 use ecow::EcoString; 5 5 6 + use crate::parse::LiteralFloatValue; 7 + 6 8 #[derive(Clone, Debug, PartialEq, Eq)] 7 9 pub enum Token { 8 - Name { name: EcoString }, 9 - UpName { name: EcoString }, 10 - DiscardName { name: EcoString }, 11 - Int { value: EcoString, int_value: BigInt }, 12 - Float { value: EcoString }, 13 - String { value: EcoString }, 14 - CommentDoc { content: EcoString }, 10 + Name { 11 + name: EcoString, 12 + }, 13 + UpName { 14 + name: EcoString, 15 + }, 16 + DiscardName { 17 + name: EcoString, 18 + }, 19 + Int { 20 + value: EcoString, 21 + int_value: BigInt, 22 + }, 23 + Float { 24 + value: EcoString, 25 + float_value: LiteralFloatValue, 26 + }, 27 + String { 28 + value: EcoString, 29 + }, 30 + CommentDoc { 31 + content: EcoString, 32 + }, 15 33 // Groupings 16 34 LeftParen, // ( 17 35 RightParen, // ) ··· 207 225 value, 208 226 int_value: _, 209 227 } 210 - | Token::Float { value } 228 + | Token::Float { 229 + value, 230 + float_value: _, 231 + } 211 232 | Token::String { value } => value.as_str(), 212 233 Token::AmperAmper => "&&", 213 234 Token::As => "as",
+3 -5
compiler-core/src/type_/error.rs
··· 6 6 ast::{BinOp, BitArraySegmentTruncation, Layer, SrcSpan, TodoKind}, 7 7 build::Target, 8 8 exhaustiveness::ImpossibleBitArraySegmentPattern, 9 + parse::LiteralFloatValue, 9 10 type_::{Type, expression::ComparisonOutcome}, 10 11 }; 11 12 ··· 1978 1979 /// Erlang's floating point numbers 1979 1980 /// 1980 1981 pub fn check_erlang_float_safety( 1981 - string_value: &EcoString, 1982 + value: LiteralFloatValue, 1982 1983 location: SrcSpan, 1983 1984 problems: &mut Problems, 1984 1985 ) { 1985 1986 let erl_min_float = -1.7976931348623157e308f64; 1986 1987 let erl_max_float = 1.7976931348623157e308f64; 1987 1988 1988 - let float_value: f64 = string_value 1989 - .replace("_", "") 1990 - .parse() 1991 - .expect("Unable to parse string to floating point value"); 1989 + let float_value = value.value(); 1992 1990 1993 1991 if float_value < erl_min_float || float_value > erl_max_float { 1994 1992 problems.error(Error::ErlangFloatUnsafe { location });
+22 -8
compiler-core/src/type_/expression.rs
··· 16 16 }, 17 17 build::Target, 18 18 exhaustiveness::{self, CompileCaseResult, CompiledCase, Reachability}, 19 - parse::PatternPosition, 19 + parse::{LiteralFloatValue, PatternPosition}, 20 20 reference::ReferenceKind, 21 21 }; 22 22 use ecow::eco_format; ··· 454 454 } => Ok(self.infer_tuple(elements, location)), 455 455 456 456 UntypedExpr::Float { 457 - location, value, .. 457 + location, 458 + value, 459 + float_value, 458 460 } => { 459 461 if self.environment.target == Target::Erlang 460 462 && !self.current_function_definition.has_erlang_external 461 463 { 462 - check_erlang_float_safety(&value, location, self.problems) 464 + check_erlang_float_safety(float_value, location, self.problems) 463 465 } 464 466 465 - Ok(self.infer_float(value, location)) 467 + Ok(self.infer_float(value, float_value, location)) 466 468 } 467 469 468 470 UntypedExpr::String { ··· 665 667 } 666 668 } 667 669 668 - fn infer_float(&mut self, value: EcoString, location: SrcSpan) -> TypedExpr { 670 + fn infer_float( 671 + &mut self, 672 + value: EcoString, 673 + float_value: LiteralFloatValue, 674 + location: SrcSpan, 675 + ) -> TypedExpr { 669 676 TypedExpr::Float { 670 677 location, 671 678 value, 679 + float_value, 672 680 type_: float(), 673 681 } 674 682 } ··· 3773 3781 } 3774 3782 3775 3783 Constant::Float { 3776 - location, value, .. 3784 + location, 3785 + value, 3786 + float_value, 3777 3787 } => { 3778 3788 if self.environment.target == Target::Erlang { 3779 - check_erlang_float_safety(&value, location, self.problems) 3789 + check_erlang_float_safety(float_value, location, self.problems) 3780 3790 } 3781 3791 3782 - Ok(Constant::Float { location, value }) 3792 + Ok(Constant::Float { 3793 + location, 3794 + value, 3795 + float_value, 3796 + }) 3783 3797 } 3784 3798 3785 3799 Constant::String {
+11 -3
compiler-core/src/type_/pattern.rs
··· 735 735 } 736 736 } 737 737 738 - Pattern::Float { location, value } => { 738 + Pattern::Float { 739 + location, 740 + value, 741 + float_value, 742 + } => { 739 743 self.unify_types(type_, float(), location); 740 744 741 745 if self.environment.target == Target::Erlang 742 746 && !self.implementations.uses_erlang_externals 743 747 { 744 - check_erlang_float_safety(&value, location, self.problems) 748 + check_erlang_float_safety(float_value, location, self.problems) 745 749 } 746 750 747 - Pattern::Float { location, value } 751 + Pattern::Float { 752 + location, 753 + value, 754 + float_value, 755 + } 748 756 } 749 757 750 758 Pattern::String { location, value } => {