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

Configure Feed

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

change how guards are generate to accomodate binary representation

author
Giacomo Cavalieri
committer
Louis Pilfold
date (Jul 22, 2026, 8:34 AM +0100) commit f83d1798 parent 0faebb04 change-id xvrwtvpm
+70 -8
+2
compiler-core/src/erlang.rs
··· 2201 2201 2202 2202 let clause_guards = builder.end_clause_pattern(clause_pattern); 2203 2203 if let Some(guard) = clause.guard.as_ref() { 2204 + let guard_ender = builder.start_clause_guard(); 2204 2205 self.clause_guard(builder, guard, &variables_to_add_later); 2206 + builder.end_clause_guard(guard_ender); 2205 2207 } 2206 2208 2207 2209 // Finally we can generate the clause body. If the clause is
+68 -8
erlang-generation/src/lib.rs
··· 111 111 /// Represents a set of clause guards that has yet to be closed. 112 112 type ClauseGuards; 113 113 114 + /// Represents a single clause guard that has yet to be closed. 115 + type Guard; 116 + 114 117 /// Represents an open clause body that has yet to be closed. 115 118 type ClauseBody; 116 119 ··· 936 939 /// that function without generating anything inbetween. 937 940 fn end_clause_pattern(&mut self, clause_pattern: Self::ClausePattern) -> Self::ClauseGuards; 938 941 942 + /// You must call this before generating the guard of a case clause. 943 + /// For example: 944 + /// 945 + /// ```ignore 946 + /// let case = builder.start_case(); 947 + /// builder.variable("wibble"); 948 + /// let case = builder.end_case_subject(); 949 + /// 950 + /// let clause = builder.start_case_clause(); 951 + /// builder.discard_pattern(); 952 + /// let clause = builder.end_clause_pattern(); 953 + /// let guard = builder.start_clause_guard(); 954 + /// builder.atom("true"); 955 + /// builder.builder.end_clause_guard(guard); 956 + /// let clause = builder.end_clause_guards(); 957 + /// builder.int(1.into()); 958 + /// builder.end_clause_body(); 959 + /// 960 + /// builder.end_case(case); 961 + /// ``` 962 + /// 963 + /// A clause might have multiple guards but, the way Gleam is compiled, you 964 + /// should always call this function just once. A gleam guard is always 965 + /// compiled as a single erlang guard with a single expression. 966 + /// 967 + fn start_clause_guard(&mut self) -> Self::Guard; 968 + 969 + /// This ends an open clause guards. Anything that is generated after 970 + /// this is going to be a new guard among the guards of a case's guards. 971 + fn end_clause_guard(&mut self, clause_guard: Self::Guard); 972 + 939 973 /// This ends the case clause's guards. Anything that is generated after 940 974 /// this is going to be a statement inside the current case clause until 941 975 /// `end_clause_body` is called. ··· 1491 1525 /// in two steps: first we generate the name, second we generate the type of 1492 1526 /// the field. 1493 1527 RecordField { expected: ExpectedRecordFieldItem }, 1528 + /// We're generating a guard in a possible series of guards in a clause. 1529 + ClauseGuard, 1494 1530 } 1495 1531 1496 1532 #[derive(Debug, Eq, PartialEq)] ··· 1714 1750 type CalledExpression = (); 1715 1751 type Call = (); 1716 1752 type Case = (); 1753 + type Guard = (); 1717 1754 type CaseSubject = (); 1718 1755 type ClauseBody = (); 1719 1756 type ClauseGuards = (); ··· 2302 2339 }); 2303 2340 } 2304 2341 2342 + fn start_clause_guard(&mut self) -> Self::Guard { 2343 + self.new_clause_guard(); 2344 + self.position.push(ErlangSourceBuilderPosition::ClauseGuard); 2345 + } 2346 + 2347 + fn end_clause_guard(&mut self, _clause_guard: Self::Guard) { 2348 + self.close_currently_open_item(); 2349 + } 2350 + 2305 2351 fn end_clause_guards(&mut self, _clause_guards: Self::ClauseGuards) -> Self::ClauseBody { 2306 2352 self.close_currently_open_item(); 2307 2353 self.indentation += INDENT; ··· 2666 2712 } 2667 2713 } 2668 2714 2669 - ErlangSourceBuilderPosition::CaseClause { 2670 - expected: 2671 - ExpectedCaseClauseItem::Guards { 2672 - first: first @ true, 2673 - }, 2674 - } => { 2675 - *first = false; 2715 + ErlangSourceBuilderPosition::ClauseGuard => { 2676 2716 self.code.push_str(" when "); 2677 2717 } 2678 2718 ··· 2731 2771 | ErlangSourceBuilderPosition::Map { .. } 2732 2772 | ErlangSourceBuilderPosition::RecordAttribute { .. } 2733 2773 | ErlangSourceBuilderPosition::CaseClause { 2734 - expected: ExpectedCaseClauseItem::Guards { first: false }, 2774 + expected: ExpectedCaseClauseItem::Guards { .. }, 2735 2775 } 2736 2776 | ErlangSourceBuilderPosition::BitArraySegment { 2737 2777 expected: BitArraySegmentExpectedItem::Specifiers, ··· 2818 2858 | ErlangSourceBuilderPosition::AnonymousFunctionStatement { .. } 2819 2859 | ErlangSourceBuilderPosition::UnaryOperator 2820 2860 | ErlangSourceBuilderPosition::Case { .. } 2861 + | ErlangSourceBuilderPosition::ClauseGuard 2821 2862 | ErlangSourceBuilderPosition::BinaryOperator { .. } 2822 2863 | ErlangSourceBuilderPosition::CaseClause { .. } 2823 2864 | ErlangSourceBuilderPosition::Map { .. } ··· 2941 2982 | ErlangSourceBuilderPosition::UnaryOperator 2942 2983 | ErlangSourceBuilderPosition::BinaryOperator { .. } 2943 2984 | ErlangSourceBuilderPosition::Case { .. } 2985 + | ErlangSourceBuilderPosition::ClauseGuard 2944 2986 | ErlangSourceBuilderPosition::Map { .. } 2945 2987 | ErlangSourceBuilderPosition::MapField { .. } 2946 2988 | ErlangSourceBuilderPosition::MatchOperator { ··· 3088 3130 self.code.push_str("end"); 3089 3131 } 3090 3132 3133 + ErlangSourceBuilderPosition::ClauseGuard => (), 3091 3134 ErlangSourceBuilderPosition::CaseClause { expected } => match expected { 3092 3135 ExpectedCaseClauseItem::Pattern => (), 3093 3136 // When the guards of a case clause are over we need to add the ··· 3191 3234 | ErlangSourceBuilderPosition::BinaryOperator { .. } 3192 3235 | ErlangSourceBuilderPosition::Case { .. } 3193 3236 | ErlangSourceBuilderPosition::CaseClause { .. } 3237 + | ErlangSourceBuilderPosition::ClauseGuard 3194 3238 | ErlangSourceBuilderPosition::Map { .. } 3195 3239 | ErlangSourceBuilderPosition::MapField { .. } 3196 3240 | ErlangSourceBuilderPosition::MatchPattern { .. } ··· 3273 3317 self.code.push_str(&" ".repeat(self.indentation)) 3274 3318 } 3275 3319 3320 + fn new_clause_guard(&mut self) { 3321 + self.pop_leftover_items(); 3322 + let Some(ErlangSourceBuilderPosition::CaseClause { 3323 + expected: 3324 + ExpectedCaseClauseItem::Guards { 3325 + first: first @ true, 3326 + }, 3327 + }) = self.position.last_mut() 3328 + else { 3329 + invalid_code_for_position!(self, "new clause guard"); 3330 + }; 3331 + 3332 + *first = false; 3333 + } 3334 + 3276 3335 /// You can call this before generating any expression (before the 3277 3336 /// `new_expression` call) if we can skip wrapping it in parentheses when it 3278 3337 /// appears as a bitstring segment value. ··· 3464 3523 | ErlangSourceBuilderPosition::BitArray { .. } 3465 3524 | ErlangSourceBuilderPosition::Map { .. } 3466 3525 | ErlangSourceBuilderPosition::Block { .. } 3526 + | ErlangSourceBuilderPosition::ClauseGuard 3467 3527 | ErlangSourceBuilderPosition::UnaryOperator 3468 3528 | ErlangSourceBuilderPosition::FunctionType { 3469 3529 expected: