diff --git a/compiler/ds-codegen/src/js_emitter.rs b/compiler/ds-codegen/src/js_emitter.rs index 4b4eb74..35f39eb 100644 --- a/compiler/ds-codegen/src/js_emitter.rs +++ b/compiler/ds-codegen/src/js_emitter.rs @@ -953,22 +953,27 @@ impl JsEmitter { Expr::BinOp(left, op, right) => { let l = self.emit_expr(left); let r = self.emit_expr(right); - let op_str = match op { - BinOp::Add => "+", - BinOp::Sub => "-", - BinOp::Mul => "*", - BinOp::Div => "/", - BinOp::Mod => "%", - BinOp::Eq => "===", - BinOp::Neq => "!==", - BinOp::Lt => "<", - BinOp::Gt => ">", - BinOp::Lte => "<=", - BinOp::Gte => ">=", - BinOp::And => "&&", - BinOp::Or => "||", - }; - format!("({l} {op_str} {r})") + match op { + BinOp::Div => format!("Math.trunc({l} / {r})"), + _ => { + let op_str = match op { + BinOp::Add => "+", + BinOp::Sub => "-", + BinOp::Mul => "*", + BinOp::Div => unreachable!(), + BinOp::Mod => "%", + BinOp::Eq => "===", + BinOp::Neq => "!==", + BinOp::Lt => "<", + BinOp::Gt => ">", + BinOp::Lte => "<=", + BinOp::Gte => ">=", + BinOp::And => "&&", + BinOp::Or => "||", + }; + format!("({l} {op_str} {r})") + } + } } Expr::UnaryOp(op, inner) => { let inner_js = self.emit_expr(inner); @@ -1290,22 +1295,27 @@ impl JsEmitter { Expr::BinOp(left, op, right) => { let l = Self::predicate_to_js(left, signal_name); let r = Self::predicate_to_js(right, signal_name); - let op_str = match op { - BinOp::Gt => ">", - BinOp::Gte => ">=", - BinOp::Lt => "<", - BinOp::Lte => "<=", - BinOp::Eq => "===", - BinOp::Neq => "!==", - BinOp::And => "&&", - BinOp::Or => "||", - BinOp::Add => "+", - BinOp::Sub => "-", - BinOp::Mul => "*", - BinOp::Div => "/", - BinOp::Mod => "%", - }; - format!("({} {} {})", l, op_str, r) + match op { + BinOp::Div => format!("Math.trunc({} / {})", l, r), + _ => { + let op_str = match op { + BinOp::Gt => ">", + BinOp::Gte => ">=", + BinOp::Lt => "<", + BinOp::Lte => "<=", + BinOp::Eq => "===", + BinOp::Neq => "!==", + BinOp::And => "&&", + BinOp::Or => "||", + BinOp::Add => "+", + BinOp::Sub => "-", + BinOp::Mul => "*", + BinOp::Div => unreachable!(), + BinOp::Mod => "%", + }; + format!("({} {} {})", l, op_str, r) + } + } } Expr::UnaryOp(UnaryOp::Not, inner) => { format!("!({})", Self::predicate_to_js(inner, signal_name)) diff --git a/compiler/ds-parser/src/lexer.rs b/compiler/ds-parser/src/lexer.rs index 0a1ee70..a21443d 100644 --- a/compiler/ds-parser/src/lexer.rs +++ b/compiler/ds-parser/src/lexer.rs @@ -335,7 +335,6 @@ impl Lexer { "true" => TokenKind::True, "false" => TokenKind::False, "for" => TokenKind::For, - "in" => TokenKind::In, "component" => TokenKind::Component, "route" => TokenKind::Route, "navigate" => TokenKind::Navigate, diff --git a/examples/project-tracker.ds b/examples/project-tracker.ds new file mode 100644 index 0000000..b8feb62 --- /dev/null +++ b/examples/project-tracker.ds @@ -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" } + ] +]