1use std::collections::HashMap;
4use std::fmt;
5
6use crate::ast::*;
7use crate::output::{BufferedOutput, OutputHandler};
8
9#[derive(Debug, Clone)]
12pub enum Value {
13 Integer(i64),
14 Float(f64),
15 String(String),
16 Boolean(bool),
17 List(Vec<Value>),
18 Dict(Vec<(Value, Value)>),
19 Tuple(Vec<Value>),
20 Function(FuncValue),
21 BuiltinFn(String),
22 None,
23}
24
25#[derive(Debug, Clone)]
26pub struct FuncValue {
27 pub name: Option<String>,
28 pub params: Vec<Param>,
29 pub body: Expr,
30 pub closure: Environment,
31}
32
33impl fmt::Display for Value {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 Value::Integer(n) => write!(f, "{}", n),
37 Value::Float(n) => write!(f, "{}", n),
38 Value::String(s) => write!(f, "{}", s),
39 Value::Boolean(b) => write!(f, "{}", if *b { "True" } else { "False" }),
40 Value::List(items) => {
41 write!(f, "[")?;
42 for (i, item) in items.iter().enumerate() {
43 if i > 0 {
44 write!(f, ", ")?;
45 }
46 write!(f, "{}", item)?;
47 }
48 write!(f, "]")
49 }
50 Value::Dict(entries) => {
51 write!(f, "{{")?;
52 for (i, (k, v)) in entries.iter().enumerate() {
53 if i > 0 {
54 write!(f, ", ")?;
55 }
56 write!(f, "{}: {}", k, v)?;
57 }
58 write!(f, "}}")
59 }
60 Value::Tuple(items) => {
61 write!(f, "(")?;
62 for (i, item) in items.iter().enumerate() {
63 if i > 0 {
64 write!(f, ", ")?;
65 }
66 write!(f, "{}", item)?;
67 }
68 write!(f, ")")
69 }
70 Value::Function(_) => write!(f, "<function>"),
71 Value::BuiltinFn(name) => write!(f, "<builtin:{}>", name),
72 Value::None => write!(f, "None"),
73 }
74 }
75}
76
77impl PartialEq for Value {
78 fn eq(&self, other: &Self) -> bool {
79 match (self, other) {
80 (Value::Integer(a), Value::Integer(b)) => a == b,
81 (Value::Float(a), Value::Float(b)) => a == b,
82 (Value::Integer(a), Value::Float(b)) => (*a as f64) == *b,
83 (Value::Float(a), Value::Integer(b)) => *a == (*b as f64),
84 (Value::String(a), Value::String(b)) => a == b,
85 (Value::Boolean(a), Value::Boolean(b)) => a == b,
86 (Value::None, Value::None) => true,
87 (Value::List(a), Value::List(b)) => a == b,
88 _ => false,
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
96pub struct Environment {
97 pub scopes: Vec<HashMap<String, Value>>,
98}
99
100impl Default for Environment {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106impl Environment {
107 pub fn new() -> Self {
108 let mut global = HashMap::new();
109 for name in [
111 "print", "println", "len", "range", "str", "int", "float", "type", "map", "filter",
112 "sum", "append",
113 ] {
114 global.insert(name.to_string(), Value::BuiltinFn(name.to_string()));
115 }
116 let mut env = Self {
117 scopes: vec![global],
118 };
119 crate::stdlib::register_modules(&mut env);
121 env
122 }
123
124 pub fn push_scope(&mut self) {
125 self.scopes.push(HashMap::new());
126 }
127
128 pub fn pop_scope(&mut self) {
129 self.scopes.pop();
130 }
131
132 pub fn get(&self, name: &str) -> Option<&Value> {
133 for scope in self.scopes.iter().rev() {
134 if let Some(val) = scope.get(name) {
135 return Some(val);
136 }
137 }
138 None
139 }
140
141 pub fn set(&mut self, name: String, value: Value) {
142 for scope in self.scopes.iter_mut().rev() {
144 if let std::collections::hash_map::Entry::Occupied(mut e) = scope.entry(name.clone()) {
145 e.insert(value);
146 return;
147 }
148 }
149 if let Some(scope) = self.scopes.last_mut() {
151 scope.insert(name, value);
152 }
153 }
154
155 pub fn define(&mut self, name: String, value: Value) {
156 if let Some(scope) = self.scopes.last_mut() {
157 scope.insert(name, value);
158 }
159 }
160}
161
162#[derive(Debug, Clone)]
165pub struct RuntimeError(pub String);
166
167impl fmt::Display for RuntimeError {
168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169 write!(f, "Runtime error: {}", self.0)
170 }
171}
172
173impl std::error::Error for RuntimeError {}
174
175#[derive(Debug, Clone)]
177pub enum Signal {
178 Value(Value),
179 Return(Value),
180}
181
182pub struct Interpreter {
185 pub env: Environment,
186 pub output: Box<dyn OutputHandler>,
187}
188
189impl Default for Interpreter {
190 fn default() -> Self {
191 Self::new()
192 }
193}
194
195impl Interpreter {
196 pub fn new() -> Self {
198 Self {
199 env: Environment::new(),
200 output: Box::new(BufferedOutput::new()),
201 }
202 }
203
204 pub fn with_output(handler: Box<dyn OutputHandler>) -> Self {
210 Self {
211 env: Environment::new(),
212 output: handler,
213 }
214 }
215
216 pub fn output_lines(&self) -> &[String] {
218 self.output.lines()
219 }
220
221 pub fn run(&mut self, program: &Node) -> Result<Value, RuntimeError> {
222 match program {
223 Node::Module(items) => {
224 let mut last = Value::None;
225 for item in items {
226 match self.exec_node(item)? {
227 Signal::Return(v) => return Ok(v),
228 Signal::Value(v) => last = v,
229 }
230 }
231 Ok(last)
232 }
233 _ => match self.exec_node(program)? {
234 Signal::Return(v) | Signal::Value(v) => Ok(v),
235 },
236 }
237 }
238
239 fn exec_node(&mut self, node: &Node) -> Result<Signal, RuntimeError> {
240 match node {
241 Node::Module(items) => {
242 let mut last = Value::None;
243 for item in items {
244 match self.exec_node(item)? {
245 Signal::Return(v) => return Ok(Signal::Return(v)),
246 Signal::Value(v) => last = v,
247 }
248 }
249 Ok(Signal::Value(last))
250 }
251 Node::Import(_) => {
252 Ok(Signal::Value(Value::None))
254 }
255 Node::VariableDeclaration(name, _, expr) => {
256 let val = self.eval(expr)?;
257 self.env.define(name.clone(), val);
258 Ok(Signal::Value(Value::None))
259 }
260 Node::FunctionDeclaration(decl) => {
261 let func = Value::Function(FuncValue {
262 name: Some(decl.name.clone()),
263 params: decl.params.clone(),
264 body: *decl.body.clone(),
265 closure: self.env.clone(),
266 });
267 self.env.define(decl.name.clone(), func);
268 Ok(Signal::Value(Value::None))
269 }
270 Node::Expression(expr) => {
271 let val = self.eval(expr)?;
272 Ok(Signal::Value(val))
273 }
274 Node::Return(expr) => {
275 let val = match expr {
276 Some(e) => self.eval(e)?,
277 None => Value::None,
278 };
279 Ok(Signal::Return(val))
280 }
281 Node::TypeDefinition(_, _)
282 | Node::DataDefinition(_, _)
283 | Node::TraitDefinition(_, _)
284 | Node::InstanceDefinition(_, _, _) => {
285 Ok(Signal::Value(Value::None))
287 }
288 }
289 }
290
291 pub fn eval(&mut self, expr: &Expr) -> Result<Value, RuntimeError> {
292 match expr {
293 Expr::Integer(n) => Ok(Value::Integer(*n)),
294 Expr::Float(n) => Ok(Value::Float(*n)),
295 Expr::StringLit(s) => Ok(Value::String(s.clone())),
296 Expr::Boolean(b) => Ok(Value::Boolean(*b)),
297 Expr::Identifier(name) => self
298 .env
299 .get(name)
300 .cloned()
301 .ok_or_else(|| RuntimeError(format!("undefined variable: {}", name))),
302
303 Expr::List(items) => {
304 let vals: Vec<Value> = items
305 .iter()
306 .map(|e| self.eval(e))
307 .collect::<Result<_, _>>()?;
308 Ok(Value::List(vals))
309 }
310 Expr::Dict(entries) => {
311 let vals: Vec<(Value, Value)> = entries
312 .iter()
313 .map(|(k, v)| Ok((self.eval(k)?, self.eval(v)?)))
314 .collect::<Result<_, RuntimeError>>()?;
315 Ok(Value::Dict(vals))
316 }
317 Expr::Tuple(items) => {
318 let vals: Vec<Value> = items
319 .iter()
320 .map(|e| self.eval(e))
321 .collect::<Result<_, _>>()?;
322 Ok(Value::Tuple(vals))
323 }
324
325 Expr::BinaryOp(op, left, right) => {
326 let lv = self.eval(left)?;
327 let rv = self.eval(right)?;
328 self.eval_binop(op, &lv, &rv)
329 }
330
331 Expr::UnaryOp(op, expr) => {
332 let val = self.eval(expr)?;
333 match op {
334 UnaryOp::Neg => match val {
335 Value::Integer(n) => Ok(Value::Integer(-n)),
336 Value::Float(n) => Ok(Value::Float(-n)),
337 _ => Err(RuntimeError("cannot negate non-numeric value".into())),
338 },
339 UnaryOp::Pos => Ok(val),
340 UnaryOp::Not => match val {
341 Value::Boolean(b) => Ok(Value::Boolean(!b)),
342 _ => Err(RuntimeError(
343 "cannot apply 'not' to non-boolean value".into(),
344 )),
345 },
346 }
347 }
348
349 Expr::Pipe(left, right) => {
350 let lv = self.eval(left)?;
351 let func = self.eval(right)?;
353 self.call_value(&func, &[lv])
354 }
355
356 Expr::FunctionCall(callee, args) => {
357 let func = self.eval(callee)?;
358 let arg_vals: Vec<Value> = args
359 .iter()
360 .map(|a| self.eval(a))
361 .collect::<Result<_, _>>()?;
362 self.call_value(&func, &arg_vals)
363 }
364
365 Expr::Index(expr, idx) => {
366 let container = self.eval(expr)?;
367 let index = self.eval(idx)?;
368 match (&container, &index) {
369 (Value::List(items), Value::Integer(i)) => {
370 let i = if *i < 0 { items.len() as i64 + i } else { *i } as usize;
371 items
372 .get(i)
373 .cloned()
374 .ok_or_else(|| RuntimeError(format!("index {} out of bounds", i)))
375 }
376 (Value::String(s), Value::Integer(i)) => {
377 let i = if *i < 0 { s.len() as i64 + i } else { *i } as usize;
378 s.chars()
379 .nth(i)
380 .map(|c| Value::String(c.to_string()))
381 .ok_or_else(|| RuntimeError(format!("index {} out of bounds", i)))
382 }
383 (Value::Dict(entries), key) => {
384 for (k, v) in entries {
385 if k == key {
386 return Ok(v.clone());
387 }
388 }
389 Err(RuntimeError(format!("key not found: {}", key)))
390 }
391 _ => Err(RuntimeError("cannot index this value".into())),
392 }
393 }
394
395 Expr::MemberAccess(expr, member) => {
396 let val = self.eval(expr)?;
397 match &val {
398 Value::Dict(entries) => {
399 for (k, v) in entries {
400 if let Value::String(s) = k {
401 if s == member {
402 return Ok(v.clone());
403 }
404 }
405 }
406 Err(RuntimeError(format!("no member '{}' found", member)))
407 }
408 _ => Err(RuntimeError(format!(
409 "member access on unsupported type: {}",
410 val
411 ))),
412 }
413 }
414
415 Expr::If(cond, then_body, elif_branches, else_body) => {
416 let cond_val = self.eval(cond)?;
417 if is_truthy(&cond_val) {
418 self.eval(then_body)
419 } else {
420 for (elif_cond, elif_body) in elif_branches {
421 let elif_val = self.eval(elif_cond)?;
422 if is_truthy(&elif_val) {
423 return self.eval(elif_body);
424 }
425 }
426 if let Some(else_body) = else_body {
427 self.eval(else_body)
428 } else {
429 Ok(Value::None)
430 }
431 }
432 }
433
434 Expr::For(var, iterable, body) => {
435 let iter_val = self.eval(iterable)?;
436 let items = match iter_val {
437 Value::List(items) => items,
438 _ => return Err(RuntimeError("for loop requires iterable (list)".into())),
439 };
440 self.env.push_scope();
441 let mut last = Value::None;
442 for item in items {
443 self.env.define(var.clone(), item);
444 last = self.eval(body)?;
445 }
446 self.env.pop_scope();
447 Ok(last)
448 }
449
450 Expr::While(cond, body) => {
451 let mut last = Value::None;
452 loop {
453 let cond_val = self.eval(cond)?;
454 if !is_truthy(&cond_val) {
455 break;
456 }
457 last = self.eval(body)?;
458 }
459 Ok(last)
460 }
461
462 Expr::Match(subject, arms) => {
463 let val = self.eval(subject)?;
464 for arm in arms {
465 if let Some(bindings) = match_pattern(&arm.pattern, &val) {
466 self.env.push_scope();
467 for (name, bound_val) in &bindings {
468 self.env.define(name.clone(), bound_val.clone());
469 }
470 if let Some(guard) = &arm.guard {
472 let guard_val = self.eval(guard)?;
473 if !is_truthy(&guard_val) {
474 self.env.pop_scope();
475 continue;
476 }
477 }
478 let result = self.eval(&arm.body)?;
479 self.env.pop_scope();
480 return Ok(result);
481 }
482 }
483 Err(RuntimeError(
484 "no matching pattern in match expression".into(),
485 ))
486 }
487
488 Expr::Lambda(params, body) => Ok(Value::Function(FuncValue {
489 name: None,
490 params: params.clone(),
491 body: *body.clone(),
492 closure: self.env.clone(),
493 })),
494
495 Expr::ListComprehension(expr, var, iterable, filter) => {
496 let iter_val = self.eval(iterable)?;
497 let items = match iter_val {
498 Value::List(items) => items,
499 _ => return Err(RuntimeError("list comprehension requires iterable".into())),
500 };
501 let mut result = Vec::new();
502 self.env.push_scope();
503 for item in items {
504 self.env.define(var.clone(), item);
505 if let Some(filter_expr) = filter {
506 let fv = self.eval(filter_expr)?;
507 if !is_truthy(&fv) {
508 continue;
509 }
510 }
511 result.push(self.eval(expr)?);
512 }
513 self.env.pop_scope();
514 Ok(Value::List(result))
515 }
516
517 Expr::Block(stmts) => {
518 self.env.push_scope();
519 let mut last = Value::None;
520 for stmt in stmts {
521 match self.exec_node(stmt)? {
522 Signal::Return(v) => {
523 self.env.pop_scope();
524 return Ok(v); }
526 Signal::Value(v) => last = v,
527 }
528 }
529 self.env.pop_scope();
530 Ok(last)
531 }
532
533 Expr::Assign(target, value) => {
534 let val = self.eval(value)?;
535 match target.as_ref() {
536 Expr::Identifier(name) => {
537 self.env.set(name.clone(), val);
538 Ok(Value::None)
539 }
540 _ => Err(RuntimeError("invalid assignment target".into())),
541 }
542 }
543
544 Expr::CompoundAssign(op, target, value) => {
545 let current = self.eval(target)?;
546 let rhs = self.eval(value)?;
547 let result = self.eval_binop(op, ¤t, &rhs)?;
548 match target.as_ref() {
549 Expr::Identifier(name) => {
550 self.env.set(name.clone(), result);
551 Ok(Value::None)
552 }
553 _ => Err(RuntimeError("invalid compound assignment target".into())),
554 }
555 }
556 }
557 }
558
559 fn eval_binop(&self, op: &BinOp, left: &Value, right: &Value) -> Result<Value, RuntimeError> {
560 match op {
561 BinOp::Add => match (left, right) {
562 (Value::Integer(a), Value::Integer(b)) => Ok(Value::Integer(a + b)),
563 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a + b)),
564 (Value::Integer(a), Value::Float(b)) => Ok(Value::Float(*a as f64 + b)),
565 (Value::Float(a), Value::Integer(b)) => Ok(Value::Float(a + *b as f64)),
566 (Value::String(a), Value::String(b)) => Ok(Value::String(format!("{}{}", a, b))),
567 (Value::List(a), Value::List(b)) => {
568 let mut result = a.clone();
569 result.extend(b.clone());
570 Ok(Value::List(result))
571 }
572 _ => Err(RuntimeError(format!("cannot add {} and {}", left, right))),
573 },
574 BinOp::Sub => numeric_op(left, right, |a, b| a - b, |a, b| a - b),
575 BinOp::Mul => match (left, right) {
576 (Value::String(s), Value::Integer(n)) | (Value::Integer(n), Value::String(s)) => {
577 Ok(Value::String(s.repeat(*n as usize)))
578 }
579 _ => numeric_op(left, right, |a, b| a * b, |a, b| a * b),
580 },
581 BinOp::Div => match (left, right) {
582 (Value::Integer(_), Value::Integer(0)) | (Value::Float(_), Value::Integer(0)) => {
583 Err(RuntimeError("division by zero".into()))
584 }
585 _ => numeric_op_float(left, right, |a, b| a / b),
586 },
587 BinOp::IntDiv => match (left, right) {
588 (Value::Integer(a), Value::Integer(b)) => {
589 if *b == 0 {
590 Err(RuntimeError("division by zero".into()))
591 } else {
592 Ok(Value::Integer(a / b))
593 }
594 }
595 _ => Err(RuntimeError("integer division requires integers".into())),
596 },
597 BinOp::Mod => match (left, right) {
598 (Value::Integer(a), Value::Integer(b)) => {
599 if *b == 0 {
600 Err(RuntimeError("modulo by zero".into()))
601 } else {
602 Ok(Value::Integer(a % b))
603 }
604 }
605 _ => Err(RuntimeError("modulo requires integers".into())),
606 },
607 BinOp::Pow => match (left, right) {
608 (Value::Integer(a), Value::Integer(b)) => Ok(Value::Integer(a.pow(*b as u32))),
609 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a.powf(*b))),
610 (Value::Integer(a), Value::Float(b)) => Ok(Value::Float((*a as f64).powf(*b))),
611 (Value::Float(a), Value::Integer(b)) => Ok(Value::Float(a.powf(*b as f64))),
612 _ => Err(RuntimeError("power requires numeric operands".into())),
613 },
614 BinOp::Eq => Ok(Value::Boolean(left == right)),
615 BinOp::Neq => Ok(Value::Boolean(left != right)),
616 BinOp::Lt => compare_op(left, right, |ord| ord == std::cmp::Ordering::Less),
617 BinOp::Lte => compare_op(left, right, |ord| {
618 ord == std::cmp::Ordering::Less || ord == std::cmp::Ordering::Equal
619 }),
620 BinOp::Gt => compare_op(left, right, |ord| ord == std::cmp::Ordering::Greater),
621 BinOp::Gte => compare_op(left, right, |ord| {
622 ord == std::cmp::Ordering::Greater || ord == std::cmp::Ordering::Equal
623 }),
624 BinOp::And => Ok(Value::Boolean(is_truthy(left) && is_truthy(right))),
625 BinOp::Or => Ok(Value::Boolean(is_truthy(left) || is_truthy(right))),
626 }
627 }
628
629 fn call_value(&mut self, func: &Value, args: &[Value]) -> Result<Value, RuntimeError> {
630 match func {
631 Value::Function(fv) => {
632 let mut call_env = fv.closure.clone();
633 call_env.push_scope();
634 if let Some(ref name) = fv.name {
636 call_env.define(name.clone(), func.clone());
637 }
638 for (i, param) in fv.params.iter().enumerate() {
639 let val = args.get(i).cloned().unwrap_or(Value::None);
640 call_env.define(param.name.clone(), val);
641 }
642 let prev_env = std::mem::replace(&mut self.env, call_env);
643 let result = self.eval(&fv.body);
644 self.env = prev_env;
645 result
646 }
647 Value::BuiltinFn(name) => self.call_builtin(name, args),
648 _ => Err(RuntimeError(format!("cannot call non-function: {}", func))),
649 }
650 }
651
652 fn call_builtin(&mut self, name: &str, args: &[Value]) -> Result<Value, RuntimeError> {
653 match name {
654 "print" => {
655 let text: Vec<String> = args.iter().map(|a| format!("{}", a)).collect();
656 let line = text.join(" ");
657 self.output.emit(&line);
658 Ok(Value::None)
659 }
660 "println" => {
661 let text: Vec<String> = args.iter().map(|a| format!("{}", a)).collect();
662 let line = text.join(" ");
663 self.output.emit(&line);
664 Ok(Value::None)
665 }
666 "len" => match args.first() {
667 Some(Value::List(items)) => Ok(Value::Integer(items.len() as i64)),
668 Some(Value::String(s)) => Ok(Value::Integer(s.len() as i64)),
669 Some(Value::Dict(entries)) => Ok(Value::Integer(entries.len() as i64)),
670 _ => Err(RuntimeError(
671 "len() requires a list, string, or dict".into(),
672 )),
673 },
674 "range" => {
675 let (start, end, step) = match args.len() {
676 1 => match &args[0] {
677 Value::Integer(n) => (0, *n, 1),
678 _ => return Err(RuntimeError("range() requires integer arguments".into())),
679 },
680 2 => match (&args[0], &args[1]) {
681 (Value::Integer(a), Value::Integer(b)) => (*a, *b, 1),
682 _ => return Err(RuntimeError("range() requires integer arguments".into())),
683 },
684 3 => match (&args[0], &args[1], &args[2]) {
685 (Value::Integer(a), Value::Integer(b), Value::Integer(c)) => (*a, *b, *c),
686 _ => return Err(RuntimeError("range() requires integer arguments".into())),
687 },
688 _ => return Err(RuntimeError("range() takes 1-3 arguments".into())),
689 };
690 if step == 0 {
691 return Err(RuntimeError("range() step cannot be zero".into()));
692 }
693 let mut items = Vec::new();
694 let mut i = start;
695 if step > 0 {
696 while i < end {
697 items.push(Value::Integer(i));
698 i += step;
699 }
700 } else {
701 while i > end {
702 items.push(Value::Integer(i));
703 i += step;
704 }
705 }
706 Ok(Value::List(items))
707 }
708 "str" => match args.first() {
709 Some(val) => Ok(Value::String(format!("{}", val))),
710 None => Ok(Value::String(String::new())),
711 },
712 "int" => match args.first() {
713 Some(Value::Integer(n)) => Ok(Value::Integer(*n)),
714 Some(Value::Float(n)) => Ok(Value::Integer(*n as i64)),
715 Some(Value::String(s)) => s
716 .parse::<i64>()
717 .map(Value::Integer)
718 .map_err(|_| RuntimeError(format!("cannot convert '{}' to int", s))),
719 Some(Value::Boolean(b)) => Ok(Value::Integer(if *b { 1 } else { 0 })),
720 _ => Err(RuntimeError(
721 "int() requires a numeric or string argument".into(),
722 )),
723 },
724 "float" => match args.first() {
725 Some(Value::Integer(n)) => Ok(Value::Float(*n as f64)),
726 Some(Value::Float(n)) => Ok(Value::Float(*n)),
727 Some(Value::String(s)) => s
728 .parse::<f64>()
729 .map(Value::Float)
730 .map_err(|_| RuntimeError(format!("cannot convert '{}' to float", s))),
731 _ => Err(RuntimeError(
732 "float() requires a numeric or string argument".into(),
733 )),
734 },
735 "type" => {
736 let type_name = match args.first() {
737 Some(Value::Integer(_)) => "Int",
738 Some(Value::Float(_)) => "Float",
739 Some(Value::String(_)) => "String",
740 Some(Value::Boolean(_)) => "Bool",
741 Some(Value::List(_)) => "List",
742 Some(Value::Dict(_)) => "Dict",
743 Some(Value::Tuple(_)) => "Tuple",
744 Some(Value::Function(_)) => "Function",
745 Some(Value::BuiltinFn(_)) => "BuiltinFn",
746 Some(Value::None) | None => "None",
747 };
748 Ok(Value::String(type_name.to_string()))
749 }
750 "map" => {
751 if args.len() != 2 {
752 return Err(RuntimeError(
753 "map() takes 2 arguments (function, list)".into(),
754 ));
755 }
756 let func = &args[0];
757 let items = match &args[1] {
758 Value::List(items) => items.clone(),
759 _ => return Err(RuntimeError("map() second argument must be a list".into())),
760 };
761 let mut result = Vec::new();
762 for item in &items {
763 result.push(self.call_value(func, std::slice::from_ref(item))?);
764 }
765 Ok(Value::List(result))
766 }
767 "filter" => {
768 if args.len() != 2 {
769 return Err(RuntimeError(
770 "filter() takes 2 arguments (function, list)".into(),
771 ));
772 }
773 let func = &args[0];
774 let items = match &args[1] {
775 Value::List(items) => items.clone(),
776 _ => {
777 return Err(RuntimeError(
778 "filter() second argument must be a list".into(),
779 ))
780 }
781 };
782 let mut result = Vec::new();
783 for item in &items {
784 let v = self.call_value(func, std::slice::from_ref(item))?;
785 if is_truthy(&v) {
786 result.push(item.clone());
787 }
788 }
789 Ok(Value::List(result))
790 }
791 "sum" => match args.first() {
792 Some(Value::List(items)) => {
793 let mut total = Value::Integer(0);
794 for item in items {
795 total = self.eval_binop(&BinOp::Add, &total, item)?;
796 }
797 Ok(total)
798 }
799 _ => Err(RuntimeError("sum() requires a list argument".into())),
800 },
801 "append" => {
802 if args.len() != 2 {
803 return Err(RuntimeError(
804 "append() takes 2 arguments (list, item)".into(),
805 ));
806 }
807 match &args[0] {
808 Value::List(items) => {
809 let mut new_items = items.clone();
810 new_items.push(args[1].clone());
811 Ok(Value::List(new_items))
812 }
813 _ => Err(RuntimeError(
814 "append() first argument must be a list".into(),
815 )),
816 }
817 }
818 _ => {
819 if let Some(result) = crate::stdlib::call(name, args, &mut *self.output) {
822 return result;
823 }
824 Err(RuntimeError(format!("unknown builtin: {}", name)))
825 }
826 }
827 }
828}
829
830fn is_truthy(val: &Value) -> bool {
833 match val {
834 Value::Boolean(b) => *b,
835 Value::Integer(n) => *n != 0,
836 Value::Float(n) => *n != 0.0,
837 Value::String(s) => !s.is_empty(),
838 Value::List(items) => !items.is_empty(),
839 Value::None => false,
840 _ => true,
841 }
842}
843
844fn numeric_op(
845 left: &Value,
846 right: &Value,
847 int_op: fn(i64, i64) -> i64,
848 float_op: fn(f64, f64) -> f64,
849) -> Result<Value, RuntimeError> {
850 match (left, right) {
851 (Value::Integer(a), Value::Integer(b)) => Ok(Value::Integer(int_op(*a, *b))),
852 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(float_op(*a, *b))),
853 (Value::Integer(a), Value::Float(b)) => Ok(Value::Float(float_op(*a as f64, *b))),
854 (Value::Float(a), Value::Integer(b)) => Ok(Value::Float(float_op(*a, *b as f64))),
855 _ => Err(RuntimeError(format!(
856 "arithmetic requires numeric operands, got {} and {}",
857 left, right
858 ))),
859 }
860}
861
862fn numeric_op_float(
863 left: &Value,
864 right: &Value,
865 op: fn(f64, f64) -> f64,
866) -> Result<Value, RuntimeError> {
867 match (left, right) {
868 (Value::Integer(a), Value::Integer(b)) => Ok(Value::Float(op(*a as f64, *b as f64))),
869 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(op(*a, *b))),
870 (Value::Integer(a), Value::Float(b)) => Ok(Value::Float(op(*a as f64, *b))),
871 (Value::Float(a), Value::Integer(b)) => Ok(Value::Float(op(*a, *b as f64))),
872 _ => Err(RuntimeError(format!(
873 "arithmetic requires numeric operands, got {} and {}",
874 left, right
875 ))),
876 }
877}
878
879fn compare_op(
880 left: &Value,
881 right: &Value,
882 pred: fn(std::cmp::Ordering) -> bool,
883) -> Result<Value, RuntimeError> {
884 let ord = match (left, right) {
885 (Value::Integer(a), Value::Integer(b)) => a.cmp(b),
886 (Value::Float(a), Value::Float(b)) => a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal),
887 (Value::Integer(a), Value::Float(b)) => (*a as f64)
888 .partial_cmp(b)
889 .unwrap_or(std::cmp::Ordering::Equal),
890 (Value::Float(a), Value::Integer(b)) => a
891 .partial_cmp(&(*b as f64))
892 .unwrap_or(std::cmp::Ordering::Equal),
893 (Value::String(a), Value::String(b)) => a.cmp(b),
894 _ => {
895 return Err(RuntimeError(format!(
896 "cannot compare {} and {}",
897 left, right
898 )))
899 }
900 };
901 Ok(Value::Boolean(pred(ord)))
902}
903
904fn match_pattern(pattern: &Pattern, value: &Value) -> Option<Vec<(String, Value)>> {
905 match pattern {
906 Pattern::Wildcard => Some(vec![]),
907 Pattern::Literal(lit_expr) => {
908 let lit_val = match lit_expr {
909 Expr::Integer(n) => Value::Integer(*n),
910 Expr::Float(n) => Value::Float(*n),
911 Expr::StringLit(s) => Value::String(s.clone()),
912 Expr::Boolean(b) => Value::Boolean(*b),
913 _ => return None,
914 };
915 if &lit_val == value {
916 Some(vec![])
917 } else {
918 None
919 }
920 }
921 Pattern::Identifier(name) => Some(vec![(name.clone(), value.clone())]),
922 Pattern::Tuple(patterns) => match value {
923 Value::Tuple(items) if items.len() == patterns.len() => {
924 let mut bindings = Vec::new();
925 for (pat, val) in patterns.iter().zip(items.iter()) {
926 match match_pattern(pat, val) {
927 Some(b) => bindings.extend(b),
928 None => return None,
929 }
930 }
931 Some(bindings)
932 }
933 _ => None,
934 },
935 Pattern::List(patterns, rest) => match value {
936 Value::List(items) => {
937 if rest.is_some() {
938 if items.len() < patterns.len() {
939 return None;
940 }
941 } else if items.len() != patterns.len() {
942 return None;
943 }
944 let mut bindings = Vec::new();
945 for (pat, val) in patterns.iter().zip(items.iter()) {
946 match match_pattern(pat, val) {
947 Some(b) => bindings.extend(b),
948 None => return None,
949 }
950 }
951 if let Some(rest_name) = rest {
952 let rest_items = items[patterns.len()..].to_vec();
953 bindings.push((rest_name.clone(), Value::List(rest_items)));
954 }
955 Some(bindings)
956 }
957 _ => None,
958 },
959 Pattern::Constructor(_name, _patterns) => {
960 None
962 }
963 }
964}
965
966#[cfg(test)]
967mod tests {
968 use super::*;
969 use crate::parser;
970
971 fn eval_str(source: &str) -> Result<Value, String> {
972 let ast = parser::parse(source).map_err(|e| e.to_string())?;
973 let mut interp = Interpreter::new();
974 interp.run(&ast).map_err(|e| e.to_string())
975 }
976
977 fn eval_with_output(source: &str) -> (Result<Value, String>, Vec<String>) {
978 let ast = match parser::parse(source) {
979 Ok(a) => a,
980 Err(e) => return (Err(e.to_string()), vec![]),
981 };
982 let mut interp = Interpreter::new();
983 let result = interp.run(&ast).map_err(|e| e.to_string());
984 (result, interp.output_lines().to_vec())
985 }
986
987 #[test]
988 fn test_integer_literal() {
989 assert_eq!(eval_str("42").unwrap(), Value::Integer(42));
990 }
991
992 #[test]
993 fn test_float_literal() {
994 match eval_str("3.14").unwrap() {
995 Value::Float(f) => assert!((f - 3.14).abs() < f64::EPSILON),
996 other => panic!("expected float, got {:?}", other),
997 }
998 }
999
1000 #[test]
1001 fn test_var_float_bug() {
1002 let source = "var y = 13.1\ny";
1004 match eval_str(source).unwrap() {
1005 Value::Float(f) => assert!((f - 13.1).abs() < f64::EPSILON),
1006 other => panic!("expected float 13.1, got {:?}", other),
1007 }
1008 }
1009
1010 #[test]
1011 fn test_string_literal() {
1012 assert_eq!(
1013 eval_str("\"hello\"").unwrap(),
1014 Value::String("hello".to_string())
1015 );
1016 }
1017
1018 #[test]
1019 fn test_boolean() {
1020 assert_eq!(eval_str("True").unwrap(), Value::Boolean(true));
1021 assert_eq!(eval_str("False").unwrap(), Value::Boolean(false));
1022 }
1023
1024 #[test]
1025 fn test_arithmetic() {
1026 assert_eq!(eval_str("2 + 3").unwrap(), Value::Integer(5));
1027 assert_eq!(eval_str("10 - 4").unwrap(), Value::Integer(6));
1028 assert_eq!(eval_str("3 * 7").unwrap(), Value::Integer(21));
1029 assert_eq!(eval_str("10 % 3").unwrap(), Value::Integer(1));
1030 }
1031
1032 #[test]
1033 fn test_operator_precedence() {
1034 assert_eq!(eval_str("2 + 3 * 4").unwrap(), Value::Integer(14));
1035 assert_eq!(eval_str("2 * 3 + 4").unwrap(), Value::Integer(10));
1036 }
1037
1038 #[test]
1039 fn test_variable() {
1040 let source = "var x = 42\nx";
1041 assert_eq!(eval_str(source).unwrap(), Value::Integer(42));
1042 }
1043
1044 #[test]
1045 fn test_comparison() {
1046 assert_eq!(eval_str("3 < 5").unwrap(), Value::Boolean(true));
1047 assert_eq!(eval_str("5 < 3").unwrap(), Value::Boolean(false));
1048 assert_eq!(eval_str("3 == 3").unwrap(), Value::Boolean(true));
1049 assert_eq!(eval_str("3 != 4").unwrap(), Value::Boolean(true));
1050 }
1051
1052 #[test]
1053 fn test_print() {
1054 let (result, output) = eval_with_output("println(\"Hello, ArchScript!\")");
1055 assert!(result.is_ok());
1056 assert_eq!(output, vec!["Hello, ArchScript!"]);
1057 }
1058
1059 #[test]
1060 fn test_len() {
1061 let source = "len(\"hello\")";
1062 assert_eq!(eval_str(source).unwrap(), Value::Integer(5));
1063 }
1064
1065 #[test]
1066 fn test_range() {
1067 let source = "range(5)";
1068 assert_eq!(
1069 eval_str(source).unwrap(),
1070 Value::List(vec![
1071 Value::Integer(0),
1072 Value::Integer(1),
1073 Value::Integer(2),
1074 Value::Integer(3),
1075 Value::Integer(4),
1076 ])
1077 );
1078 }
1079}