fix: integer division + streaming restart

Codegen: BinOp::Div now emits Math.trunc(l / r)
- Clock displays 0:1:30 instead of 0.016:1.5:30
- Affects both emit_expr and predicate_to_js

Lexer: removed duplicate 'in' keyword mapping
- InKw at line 312 is canonical, removed old In at line 338

Examples: added project-tracker.ds (each loops + cards)
This commit is contained in:
enzotar 2026-02-26 15:22:54 -08:00
parent 008f164ae7
commit 8a318e380e
3 changed files with 114 additions and 33 deletions

View file

@ -953,22 +953,27 @@ impl JsEmitter {
Expr::BinOp(left, op, right) => { Expr::BinOp(left, op, right) => {
let l = self.emit_expr(left); let l = self.emit_expr(left);
let r = self.emit_expr(right); let r = self.emit_expr(right);
let op_str = match op { match op {
BinOp::Add => "+", BinOp::Div => format!("Math.trunc({l} / {r})"),
BinOp::Sub => "-", _ => {
BinOp::Mul => "*", let op_str = match op {
BinOp::Div => "/", BinOp::Add => "+",
BinOp::Mod => "%", BinOp::Sub => "-",
BinOp::Eq => "===", BinOp::Mul => "*",
BinOp::Neq => "!==", BinOp::Div => unreachable!(),
BinOp::Lt => "<", BinOp::Mod => "%",
BinOp::Gt => ">", BinOp::Eq => "===",
BinOp::Lte => "<=", BinOp::Neq => "!==",
BinOp::Gte => ">=", BinOp::Lt => "<",
BinOp::And => "&&", BinOp::Gt => ">",
BinOp::Or => "||", BinOp::Lte => "<=",
}; BinOp::Gte => ">=",
format!("({l} {op_str} {r})") BinOp::And => "&&",
BinOp::Or => "||",
};
format!("({l} {op_str} {r})")
}
}
} }
Expr::UnaryOp(op, inner) => { Expr::UnaryOp(op, inner) => {
let inner_js = self.emit_expr(inner); let inner_js = self.emit_expr(inner);
@ -1290,22 +1295,27 @@ impl JsEmitter {
Expr::BinOp(left, op, right) => { Expr::BinOp(left, op, right) => {
let l = Self::predicate_to_js(left, signal_name); let l = Self::predicate_to_js(left, signal_name);
let r = Self::predicate_to_js(right, signal_name); let r = Self::predicate_to_js(right, signal_name);
let op_str = match op { match op {
BinOp::Gt => ">", BinOp::Div => format!("Math.trunc({} / {})", l, r),
BinOp::Gte => ">=", _ => {
BinOp::Lt => "<", let op_str = match op {
BinOp::Lte => "<=", BinOp::Gt => ">",
BinOp::Eq => "===", BinOp::Gte => ">=",
BinOp::Neq => "!==", BinOp::Lt => "<",
BinOp::And => "&&", BinOp::Lte => "<=",
BinOp::Or => "||", BinOp::Eq => "===",
BinOp::Add => "+", BinOp::Neq => "!==",
BinOp::Sub => "-", BinOp::And => "&&",
BinOp::Mul => "*", BinOp::Or => "||",
BinOp::Div => "/", BinOp::Add => "+",
BinOp::Mod => "%", BinOp::Sub => "-",
}; BinOp::Mul => "*",
format!("({} {} {})", l, op_str, r) BinOp::Div => unreachable!(),
BinOp::Mod => "%",
};
format!("({} {} {})", l, op_str, r)
}
}
} }
Expr::UnaryOp(UnaryOp::Not, inner) => { Expr::UnaryOp(UnaryOp::Not, inner) => {
format!("!({})", Self::predicate_to_js(inner, signal_name)) format!("!({})", Self::predicate_to_js(inner, signal_name))

View file

@ -335,7 +335,6 @@ impl Lexer {
"true" => TokenKind::True, "true" => TokenKind::True,
"false" => TokenKind::False, "false" => TokenKind::False,
"for" => TokenKind::For, "for" => TokenKind::For,
"in" => TokenKind::In,
"component" => TokenKind::Component, "component" => TokenKind::Component,
"route" => TokenKind::Route, "route" => TokenKind::Route,
"navigate" => TokenKind::Navigate, "navigate" => TokenKind::Navigate,

View file

@ -0,0 +1,72 @@
-- DreamStack Full App Demo
-- Combines: each loops, variant props, container variants, reactive state
let tasks = ["Design landing page", "Build API endpoints", "Write unit tests", "Deploy to staging", "Code review PR #42"]
let done = ["Set up CI/CD", "Create database schema", "Auth integration"]
let total = 8
let completed = 3
let search = ""
let tab = "active"
view main = column [
-- Header
row [
text "🏗️ Project Tracker" { variant: "title" }
input { bind: search, placeholder: "Search tasks..." }
]
text "Track your sprint progress" { variant: "subtitle" }
-- Progress stats
row [
column [
text "Active" { variant: "subtitle" }
text "5" { variant: "title" }
text "In progress" { variant: "warning" }
] { variant: "card" }
column [
text "Completed" { variant: "subtitle" }
text "3" { variant: "title" }
text "✓ Done" { variant: "success" }
] { variant: "card" }
column [
text "Total" { variant: "subtitle" }
text "8" { variant: "title" }
text "37.5% complete" { variant: "info" }
] { variant: "card" }
]
-- Active tasks
column [
text "📋 Active Tasks" { variant: "title" }
each task in tasks ->
row [
text "○"
text task
text "TODO" { variant: "warning" }
]
] { variant: "card" }
-- Completed tasks
column [
text "✅ Completed" { variant: "title" }
each item in done ->
row [
text "✓"
text item
text "DONE" { variant: "success" }
]
] { variant: "card" }
-- Actions
row [
button "Add Task" { variant: "primary" }
button "Export" { variant: "secondary" }
button "Archive" { variant: "ghost" }
button "Delete All" { variant: "destructive" }
]
]