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