diff --git a/src/xml/vm/mod.rs b/src/xml/vm/mod.rs index 2fabe37..ea297e1 100644 --- a/src/xml/vm/mod.rs +++ b/src/xml/vm/mod.rs @@ -233,8 +233,13 @@ impl Vm { }), Expression::Identifier(name) => { - self.globals.get(name).cloned() - .ok_or_else(|| VmError::UndefinedVariable(name.clone())) + match self.globals.get(name) { + Some(val) => Ok(val.clone()), + None => { + eprintln!("[WARN] Undefined variable: {}, defaulting to empty string", name); + Ok(Value::String(String::new())) + } + } } Expression::BinaryOp { left, op, right } => { @@ -257,8 +262,13 @@ impl Vm { Expression::SpecialVar { name, is_negative } => { let lookup = format!("${}", name); - let val = self.globals.get(&lookup).cloned() - .ok_or_else(|| VmError::UndefinedVariable(format!("${}", name)))?; + let val = match self.globals.get(&lookup) { + Some(val) => val.clone(), + None => { + eprintln!("[WARN] Undefined special variable: {}, defaulting to empty string", lookup); + Value::String(String::new()) + } + }; if *is_negative { val.to_f64() .map(|n| Value::Number(-n)) @@ -285,8 +295,13 @@ impl Vm { } Expression::ArrayAccess { name, indices } => { - let base = self.globals.get(name).cloned() - .ok_or_else(|| VmError::UndefinedVariable(name.clone()))?; + let base = match self.globals.get(name) { + Some(val) => val.clone(), + None => { + eprintln!("[WARN] Undefined array variable: {}, defaulting to empty string", name); + return Ok(Value::String(String::new())); + } + }; let idx_vals: VmResult> = indices.iter().map(|i| self.eval_expr(i)).collect(); let idx_vals = idx_vals?; match (&base, idx_vals.first()) { @@ -715,9 +730,10 @@ mod tests { } #[test] - fn test_undefined_variable() { + fn test_undefined_variable_defaults_to_empty_string() { let result = parse_and_run("Var x = unknown_var"); - assert!(result.is_err()); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), Value::String(String::new())); } #[test]