diff --git a/compiler/ds-parser/src/parser.rs b/compiler/ds-parser/src/parser.rs index 29f1363..95e70e9 100644 --- a/compiler/ds-parser/src/parser.rs +++ b/compiler/ds-parser/src/parser.rs @@ -1373,7 +1373,34 @@ impl Parser { } else { first }; - props.push((key, val)); + // Merge duplicate keys: `click: a` then `click: b` → Block([a, b]) + if let Some(existing) = props.iter_mut().find(|(k, _)| *k == key) { + // Merge with existing value + match &existing.1 { + Expr::Block(exprs) => { + let mut merged = exprs.clone(); + match val { + Expr::Block(new_exprs) => merged.extend(new_exprs), + other => merged.push(other), + } + existing.1 = Expr::Block(merged); + } + _ => { + let prev = existing.1.clone(); + match val { + Expr::Block(mut new_exprs) => { + new_exprs.insert(0, prev); + existing.1 = Expr::Block(new_exprs); + } + other => { + existing.1 = Expr::Block(vec![prev, other]); + } + } + } + } + } else { + props.push((key, val)); + } self.skip_newlines(); if self.check(&TokenKind::Comma) { self.advance(); diff --git a/examples/streaming-mood.ds b/examples/streaming-mood.ds index d1d027a..3f23835 100644 --- a/examples/streaming-mood.ds +++ b/examples/streaming-mood.ds @@ -3,7 +3,7 @@ -- Only mood, energy, color are exposed (clicks is internal). -- -- Run with: --- dreamstack stream examples/streaming-mood.ds --port 3004 --relay ws://localhost:9100/source/mood +-- dreamstack stream examples/streaming-mood.ds --port 3004 let mood = "neutral" let energy = 50 @@ -22,29 +22,12 @@ view mood_tracker = text "Energy: {energy}%" text "Color: {color}" row [ - button "😄 Happy" { - click: mood = "happy" - click: color = "green" - click: energy = energy + 10 - } - button "😐 Neutral" { - click: mood = "neutral" - click: color = "gray" - } - button "😤 Angry" { - click: mood = "angry" - click: color = "red" - click: energy = energy - 10 - } + button "😄 Happy" { click: mood = "happy"; color = "green"; energy += 10 } + button "😐 Neutral" { click: mood = "neutral"; color = "gray" } + button "😤 Angry" { click: mood = "angry"; color = "red"; energy -= 10 } ] row [ - button "☕ Caffeine" { - click: energy = energy + 25 - click: clicks += 1 - } - button "😴 Rest" { - click: energy = energy - 15 - click: clicks += 1 - } + button "☕ Caffeine" { click: energy += 25; clicks += 1 } + button "😴 Rest" { click: energy -= 15; clicks += 1 } ] ] diff --git a/examples/streaming-stats.ds b/examples/streaming-stats.ds index ba5ab58..2b140c2 100644 --- a/examples/streaming-stats.ds +++ b/examples/streaming-stats.ds @@ -22,23 +22,9 @@ view stats = text "Average: {average}" text "Max: {max}" row [ - button "+5" { - click: total += 1 - click: sum += 5 - } - button "+10" { - click: total += 1 - click: sum += 10 - } - button "+25" { - click: total += 1 - click: sum += 25 - click: max = 25 - } - button "+50" { - click: total += 1 - click: sum += 50 - click: max = 50 - } + button "+5" { click: total += 1; sum += 5 } + button "+10" { click: total += 1; sum += 10 } + button "+25" { click: total += 1; sum += 25; max = 25 } + button "+50" { click: total += 1; sum += 50; max = 50 } ] ]