@@ -715,25 +715,24 @@ impl Evaluator {
715715
716716 // --- @data (load JSON file into variables) ---
717717
718− // @data file.json top-level keys become variables
719718 // @data $name file.json values as $name.key
720719 // @data $name dir/*.json each file as $name.STEM.key; $name
721720 // lists the stems, $name._count counts them
722721 // @data $name env:NAME [DEFAULT] an environment variable
723722 if let Some(rest) = content.strip_prefix("@data ") {
724723 let rest = rest.trim();
725− let (prefix, filename) = match rest.strip_prefix('$') {
726− Some(named) => match named.split_once(char::is_whitespace) {
727− Some((name, source)) => (name.to_string(), source.trim().to_string()),
728− None => {
729− return Err(ParseError {
730− line: line_num,
731− message: "@data requires: @data $name SOURCE or @data file.json"
732− .to_string(),
733− });
734− }
735− },
736− None => (String::new(), rest.to_string()),
724+ let Some((prefix, filename)) = rest
725+ .strip_prefix('$')
726+ .and_then(|named| named.split_once(char::is_whitespace))
727+ .map(|(name, source)| (name.to_string(), source.trim().to_string()))
728+ else {
729+ return Err(ParseError {
730+ line: line_num,
731+ message: format!(
732+ "@data needs a name: write `@data $name {}` and use `$name.key`",
733+ rest.trim_start_matches('$')
734+ ),
735+ });
737736 };
738737
739738 if let Some(env) = filename.strip_prefix("env:") {
@@ -741,12 +740,6 @@ impl Evaluator {
741740 Some((var, default)) => (var, Some(default.trim())),
742741 None => (env, None),
743742 };
744− if prefix.is_empty() {
745− return Err(ParseError {
746− line: line_num,
747− message: format!("@data env:{} needs a name: @data $name env:{}", var, var),
748− });
749− }
750743 let value = std::env::var(var)
751744 .ok()
752745 .or_else(|| default.map(|d| substitute_vars(d, &ctx.variables)));
@@ -768,12 +761,6 @@ impl Evaluator {
768761
769762 let filename = substitute_vars(&filename, &ctx.variables);
770763 if filename.contains('*') {
771− if prefix.is_empty() {
772− return Err(ParseError {
773− line: line_num,
774− message: format!("@data {} needs a name: @data $name {}", filename, filename),
775− });
776− }
777764 self.load_data_glob(&prefix, &filename, line_num, &content, ctx);
778765 return Ok(None);
779766 }
@@ -800,32 +787,10 @@ impl Evaluator {
800787
801788 match parse_json_with_error(&json_text) {
802789 Ok(json) => {
803− if prefix.is_empty() {
804− // No prefix: top-level object keys become variables directly
805− if let JsonValue::Object(pairs) = &json {
806− for (key, val) in pairs {
807− let mut sub = HashMap::new();
808− flatten_json(key, val, &mut sub);
809− for (k, v) in sub {
810− ctx.variables.insert(k, v);
811− }
812− }
813− } else {
814− ctx.diagnostics.push(Diagnostic {
815− line: line_num,
816− column: None,
817− message: "@data without prefix requires a JSON object at top level"
818− .to_string(),
819− severity: Severity::Error,
820− source_line: Some(content.clone()),
821− });
822− }
823− } else {
824− let mut sub = HashMap::new();
825− flatten_json(&prefix, &json, &mut sub);
826− for (k, v) in sub {
827− ctx.variables.insert(k, v);
828− }
790+ let mut sub = HashMap::new();
791+ flatten_json(&prefix, &json, &mut sub);
792+ for (k, v) in sub {
793+ ctx.variables.insert(k, v);
829794 }
830795 }
831796 Err(detail) => {