REFACTOR: No longer require PositionedItem for Val::Tuples.

This commit is contained in:
Jeremy Wall 2019-02-19 16:36:19 -06:00
parent 535d201edc
commit ceaed5c543
10 changed files with 70 additions and 98 deletions

View File

@ -18,7 +18,8 @@ pub enum Val {
Float(f64), Float(f64),
Str(String), Str(String),
List(Vec<Rc<Val>>), List(Vec<Rc<Val>>),
Tuple(Vec<(PositionedItem<String>, Rc<Val>)>), // TODO(jwall): Remove the need for PositionedItem here
Tuple(Vec<(String, Rc<Val>)>),
Env(Vec<(String, String)>), Env(Vec<(String, String)>),
Func(FuncDef), Func(FuncDef),
Module(ModuleDef), Module(ModuleDef),
@ -86,12 +87,12 @@ impl Val {
} else { } else {
for (i, lv) in ldef.iter().enumerate() { for (i, lv) in ldef.iter().enumerate() {
let field_target = &rdef[i]; let field_target = &rdef[i];
if lv.0.val != field_target.0.val { if lv.0 != field_target.0 {
// field name equality // field name equality
return Ok(false); return Ok(false);
} else { } else {
// field value equality. // field value equality.
if !lv.1.equal(field_target.1.as_ref(), lv.0.pos.clone())? { if !lv.1.equal(field_target.1.as_ref(), pos.clone())? {
return Ok(false); return Ok(false);
} }
} }
@ -99,6 +100,7 @@ impl Val {
Ok(true) Ok(true)
} }
} }
// FIXME(jwall): Maybe we don't require positions here?
(&Val::Func(_), &Val::Func(_)) => Err(error::BuildError::new( (&Val::Func(_), &Val::Func(_)) => Err(error::BuildError::new(
"Func are not comparable", "Func are not comparable",
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
@ -121,7 +123,7 @@ impl Val {
} }
/// Returns the fields if this Val is a tuple. None otherwise. /// Returns the fields if this Val is a tuple. None otherwise.
pub fn get_fields(&self) -> Option<&Vec<(PositionedItem<String>, Rc<Val>)>> { pub fn get_fields(&self) -> Option<&Vec<(String, Rc<Val>)>> {
if let &Val::Tuple(ref fs) = self { if let &Val::Tuple(ref fs) = self {
Some(fs) Some(fs)
} else { } else {
@ -227,7 +229,7 @@ impl Display for Val {
&Val::Tuple(ref def) => { &Val::Tuple(ref def) => {
write!(f, "{{\n")?; write!(f, "{{\n")?;
for v in def.iter() { for v in def.iter() {
write!(f, "\t{} = {},\n", v.0.val, v.1)?; write!(f, "\t{} = {},\n", v.0, v.1)?;
} }
write!(f, "}}") write!(f, "}}")
} }

View File

@ -254,10 +254,10 @@ impl<'a> FileBuilder<'a> {
fields: &Vec<(Token, Expression)>, fields: &Vec<(Token, Expression)>,
scope: &Scope, scope: &Scope,
) -> Result<Rc<Val>, Box<dyn Error>> { ) -> Result<Rc<Val>, Box<dyn Error>> {
let mut new_fields = Vec::<(PositionedItem<String>, Rc<Val>)>::new(); let mut new_fields = Vec::<(String, Rc<Val>)>::new();
for &(ref name, ref expr) in fields.iter() { for &(ref name, ref expr) in fields.iter() {
let val = self.eval_expr(expr, scope)?; let val = self.eval_expr(expr, scope)?;
new_fields.push((name.into(), val)); new_fields.push((name.fragment.clone(), val));
} }
Ok(Rc::new(Val::Tuple(new_fields))) Ok(Rc::new(Val::Tuple(new_fields)))
} }
@ -1014,18 +1014,22 @@ impl<'a> FileBuilder<'a> {
} }
fn get_outputs_as_val(&mut self) -> Rc<Val> { fn get_outputs_as_val(&mut self) -> Rc<Val> {
let fields: Vec<(PositionedItem<String>, Rc<Val>)> = let fields: Vec<(String, Rc<Val>)> = self
self.scope.build_output.drain().collect(); .scope
.build_output
.drain()
.map(|v| (v.0.val, v.1))
.collect();
Rc::new(Val::Tuple(fields)) Rc::new(Val::Tuple(fields))
} }
fn copy_from_base( fn copy_from_base(
&self, &self,
src_fields: &Vec<(PositionedItem<String>, Rc<Val>)>, src_fields: &Vec<(String, Rc<Val>)>,
overrides: &Vec<(Token, Expression)>, overrides: &Vec<(Token, Expression)>,
scope: &Scope, scope: &Scope,
) -> Result<Rc<Val>, Box<dyn Error>> { ) -> Result<Rc<Val>, Box<dyn Error>> {
let mut m = HashMap::<PositionedItem<String>, (i32, Rc<Val>)>::new(); let mut m = HashMap::<String, (i32, Rc<Val>)>::new();
// loop through fields and build up a hashmap // loop through fields and build up a hashmap
let mut count = 0; let mut count = 0;
for &(ref key, ref val) in src_fields.iter() { for &(ref key, ref val) in src_fields.iter() {
@ -1038,16 +1042,16 @@ impl<'a> FileBuilder<'a> {
"Duplicate \ "Duplicate \
field: {} in \ field: {} in \
tuple", tuple",
key.val key
), ),
error::ErrorType::TypeFail, error::ErrorType::TypeFail,
key.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
} }
for &(ref key, ref val) in overrides.iter() { for &(ref key, ref val) in overrides.iter() {
let expr_result = self.eval_expr(val, scope)?; let expr_result = self.eval_expr(val, scope)?;
match m.entry(key.into()) { match m.entry(key.fragment.clone()) {
// brand new field here. // brand new field here.
Entry::Vacant(v) => { Entry::Vacant(v) => {
v.insert((count, expr_result)); v.insert((count, expr_result));
@ -1077,7 +1081,7 @@ impl<'a> FileBuilder<'a> {
} }
}; };
} }
let mut new_fields: Vec<(PositionedItem<String>, (i32, Rc<Val>))> = m.drain().collect(); let mut new_fields: Vec<(String, (i32, Rc<Val>))> = m.drain().collect();
// We want to maintain our order for the fields to make comparing tuples // We want to maintain our order for the fields to make comparing tuples
// easier in later code. So we sort by the field order before constructing a new tuple. // easier in later code. So we sort by the field order before constructing a new tuple.
new_fields.sort_by(|a, b| { new_fields.sort_by(|a, b| {
@ -1312,13 +1316,13 @@ impl<'a> FileBuilder<'a> {
fn eval_functional_tuple_processing( fn eval_functional_tuple_processing(
&self, &self,
fs: &Vec<(PositionedItem<String>, Rc<Val>)>, fs: &Vec<(String, Rc<Val>)>,
def: &FuncDef, def: &FuncDef,
typ: ProcessingOpType, typ: ProcessingOpType,
) -> Result<Rc<Val>, Box<dyn Error>> { ) -> Result<Rc<Val>, Box<dyn Error>> {
let mut out = Vec::new(); let mut out = Vec::new();
for &(ref name, ref val) in fs { for &(ref name, ref val) in fs {
let argvals = vec![Rc::new(Val::Str(name.val.clone())), val.clone()]; let argvals = vec![Rc::new(Val::Str(name.clone())), val.clone()];
let result = def.eval(self, argvals)?; let result = def.eval(self, argvals)?;
match typ { match typ {
ProcessingOpType::Map => { ProcessingOpType::Map => {
@ -1338,10 +1342,7 @@ impl<'a> FileBuilder<'a> {
def.pos.clone(), def.pos.clone(),
))); )));
}; };
out.push(( out.push((new_name, fs[1].clone()));
PositionedItem::new(new_name, name.pos.clone()),
fs[1].clone(),
));
} else { } else {
return Err(Box::new(error::BuildError::new( return Err(Box::new(error::BuildError::new(
format!( format!(
@ -1402,11 +1403,7 @@ impl<'a> FileBuilder<'a> {
} }
&Val::Tuple(ref fs) => { &Val::Tuple(ref fs) => {
for &(ref name, ref val) in fs.iter() { for &(ref name, ref val) in fs.iter() {
let argvals = vec![ let argvals = vec![acc.clone(), Rc::new(Val::Str(name.clone())), val.clone()];
acc.clone(),
Rc::new(Val::Str(name.val.clone())),
val.clone(),
];
let result = funcdef.eval(self, argvals)?; let result = funcdef.eval(self, argvals)?;
acc = result; acc = result;
} }

View File

@ -10,12 +10,9 @@ use crate::ast::PositionedItem;
use crate::build::ir::Val; use crate::build::ir::Val;
use crate::error; use crate::error;
pub fn find_in_fieldlist( pub fn find_in_fieldlist(target: &str, fs: &Vec<(String, Rc<Val>)>) -> Option<Rc<Val>> {
target: &str,
fs: &Vec<(PositionedItem<String>, Rc<Val>)>,
) -> Option<Rc<Val>> {
for (key, val) in fs.iter().cloned() { for (key, val) in fs.iter().cloned() {
if target == &key.val { if target == &key {
return Some(val.clone()); return Some(val.clone());
} }
} }
@ -187,7 +184,7 @@ impl Scope {
fn lookup_in_tuple( fn lookup_in_tuple(
pos: &Position, pos: &Position,
field: &str, field: &str,
fs: &Vec<(PositionedItem<String>, Rc<Val>)>, fs: &Vec<(String, Rc<Val>)>,
) -> Result<Rc<Val>, Box<dyn Error>> { ) -> Result<Rc<Val>, Box<dyn Error>> {
if let Some(vv) = find_in_fieldlist(&field, fs) { if let Some(vv) = find_in_fieldlist(&field, fs) {
Ok(vv) Ok(vv)

View File

@ -16,7 +16,6 @@
use std::io::Write; use std::io::Write;
use std::rc::Rc; use std::rc::Rc;
use crate::ast::PositionedItem;
use crate::build::Val; use crate::build::Val;
use crate::convert::traits::{ConvertResult, Converter}; use crate::convert::traits::{ConvertResult, Converter};
@ -29,11 +28,7 @@ impl EnvConverter {
EnvConverter {} EnvConverter {}
} }
fn convert_tuple( fn convert_tuple(&self, flds: &Vec<(String, Rc<Val>)>, w: &mut Write) -> ConvertResult {
&self,
flds: &Vec<(PositionedItem<String>, Rc<Val>)>,
w: &mut Write,
) -> ConvertResult {
for &(ref name, ref val) in flds.iter() { for &(ref name, ref val) in flds.iter() {
if val.is_tuple() { if val.is_tuple() {
eprintln!("Skipping embedded tuple..."); eprintln!("Skipping embedded tuple...");
@ -43,7 +38,7 @@ impl EnvConverter {
eprintln!("Skipping empty variable: {}", name); eprintln!("Skipping empty variable: {}", name);
return Ok(()); return Ok(());
} }
write!(w, "{}=", name.val)?; write!(w, "{}=", name)?;
self.write(&val, w)?; self.write(&val, w)?;
} }
Ok(()) Ok(())

View File

@ -17,7 +17,7 @@ use std;
use std::io::{Cursor, Write}; use std::io::{Cursor, Write};
use std::rc::Rc; use std::rc::Rc;
use crate::ast::{Position, PositionedItem}; use crate::ast::Position;
use crate::build::Val; use crate::build::Val;
use crate::build::Val::Tuple; use crate::build::Val::Tuple;
use crate::convert; use crate::convert;
@ -49,17 +49,18 @@ impl ExecConverter {
Position::new(0, 0, 0), Position::new(0, 0, 0),
))); )));
} }
let mut env: Option<&Vec<(PositionedItem<String>, Rc<Val>)>> = None; let mut env: Option<&Vec<(String, Rc<Val>)>> = None;
let mut command: Option<&str> = None; let mut command: Option<&str> = None;
let mut args: Option<&Vec<Rc<Val>>> = None; let mut args: Option<&Vec<Rc<Val>>> = None;
for &(ref name, ref val) in fields.iter() { for &(ref name, ref val) in fields.iter() {
// FIXME(jwall): BuildError should not require a Position.
// We require a command field in our exec tuple. // We require a command field in our exec tuple.
if name.val == "command" { if name == "command" {
if command.is_some() { if command.is_some() {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"There can only be one command field in an exec tuple", "There can only be one command field in an exec tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
name.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
if let &Val::Str(ref s) = val.as_ref() { if let &Val::Str(ref s) = val.as_ref() {
@ -69,17 +70,17 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The command field of an exec tuple must be a string", "The command field of an exec tuple must be a string",
ErrorType::TypeFail, ErrorType::TypeFail,
name.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
// We optionally allow an env field in our exec tuple. // We optionally allow an env field in our exec tuple.
if name.val == "env" { if name == "env" {
if let &Val::Tuple(ref l) = val.as_ref() { if let &Val::Tuple(ref l) = val.as_ref() {
if env.is_some() { if env.is_some() {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"There can only be one env field in an exec tuple", "There can only be one env field in an exec tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
name.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
env = Some(l); env = Some(l);
@ -88,17 +89,17 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The env field of an exec tuple must be a list", "The env field of an exec tuple must be a list",
ErrorType::TypeFail, ErrorType::TypeFail,
name.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
// We optionally allow an args field in our exec tuple. // We optionally allow an args field in our exec tuple.
if name.val == "args" { if name == "args" {
if let &Val::List(ref l) = val.as_ref() { if let &Val::List(ref l) = val.as_ref() {
if args.is_some() { if args.is_some() {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"There can only be one args field of an exec tuple", "There can only be one args field of an exec tuple",
ErrorType::TypeFail, ErrorType::TypeFail,
name.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
args = Some(l); args = Some(l);
@ -107,7 +108,7 @@ impl ExecConverter {
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The args field of an exec tuple must be a list", "The args field of an exec tuple must be a list",
ErrorType::TypeFail, ErrorType::TypeFail,
name.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
} }
@ -130,13 +131,13 @@ impl ExecConverter {
for &(ref name, ref v) in env_list.iter() { for &(ref name, ref v) in env_list.iter() {
// We only allow string fields in our env tuple. // We only allow string fields in our env tuple.
if let &Val::Str(ref s) = v.as_ref() { if let &Val::Str(ref s) = v.as_ref() {
write!(script, "{}=\"{}\"\n", name.val, s)?; write!(script, "{}=\"{}\"\n", name, s)?;
continue; continue;
} }
return Err(Box::new(BuildError::new( return Err(Box::new(BuildError::new(
"The env fields of an exec tuple must contain only string values", "The env fields of an exec tuple must contain only string values",
ErrorType::TypeFail, ErrorType::TypeFail,
name.pos.clone(), Position::new(0, 0, 0),
))); )));
} }
} }

View File

@ -84,7 +84,7 @@ impl FlagConverter {
&Val::Tuple(ref flds) => { &Val::Tuple(ref flds) => {
for &(ref name, ref val) in flds.iter() { for &(ref name, ref val) in flds.iter() {
if let &Val::Empty = val.as_ref() { if let &Val::Empty = val.as_ref() {
self.write_flag_name(pfx, &name.val, w)?; self.write_flag_name(pfx, name, w)?;
continue; continue;
} }
match val.as_ref() { match val.as_ref() {
@ -93,10 +93,10 @@ impl FlagConverter {
self.write(&new_pfx, val, w)?; self.write(&new_pfx, val, w)?;
} }
&Val::List(ref def) => { &Val::List(ref def) => {
self.write_list_flag(pfx, &name.val, def, w)?; self.write_list_flag(pfx, name, def, w)?;
} }
_ => { _ => {
self.write_flag_name(pfx, &name.val, w)?; self.write_flag_name(pfx, name, w)?;
self.write(pfx, &val, w)?; self.write(pfx, &val, w)?;
} }
} }

View File

@ -15,7 +15,6 @@ use std::rc::Rc;
use serde_json; use serde_json;
use crate::ast;
use crate::build::Val; use crate::build::Val;
use crate::convert::traits::{ConvertResult, Converter, ImportResult, Importer}; use crate::convert::traits::{ConvertResult, Converter, ImportResult, Importer};
@ -35,13 +34,10 @@ impl JsonConverter {
Ok(serde_json::Value::Array(v)) Ok(serde_json::Value::Array(v))
} }
fn convert_tuple( fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_json::Value> {
&self,
items: &Vec<(ast::PositionedItem<String>, Rc<Val>)>,
) -> std::io::Result<serde_json::Value> {
let mut mp = serde_json::Map::new(); let mut mp = serde_json::Map::new();
for &(ref k, ref v) in items.iter() { for &(ref k, ref v) in items.iter() {
mp.entry(k.val.clone()).or_insert(self.convert_value(v)?); mp.entry(k.clone()).or_insert(self.convert_value(v)?);
} }
Ok(serde_json::Value::Object(mp)) Ok(serde_json::Value::Object(mp))
} }
@ -113,10 +109,7 @@ impl JsonConverter {
serde_json::Value::Object(m) => { serde_json::Value::Object(m) => {
let mut fs = Vec::with_capacity(m.len()); let mut fs = Vec::with_capacity(m.len());
for (key, value) in m { for (key, value) in m {
fs.push(( fs.push((key.to_string(), Rc::new(self.convert_json_val(value)?)));
ast::PositionedItem::new(key.to_string(), ast::Position::new(0, 0, 0)),
Rc::new(self.convert_json_val(value)?),
));
} }
Val::Tuple(fs) Val::Tuple(fs)
} }

View File

@ -20,7 +20,6 @@ use std::rc::Rc;
use simple_error::SimpleError; use simple_error::SimpleError;
use toml; use toml;
use crate::ast;
use crate::build::Val; use crate::build::Val;
use crate::convert::traits::{ConvertResult, Converter}; use crate::convert::traits::{ConvertResult, Converter};
@ -41,10 +40,10 @@ impl TomlConverter {
Ok(toml::Value::Array(v)) Ok(toml::Value::Array(v))
} }
fn convert_tuple(&self, items: &Vec<(ast::PositionedItem<String>, Rc<Val>)>) -> Result { fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> Result {
let mut mp = toml::value::Table::new(); let mut mp = toml::value::Table::new();
for &(ref k, ref v) in items.iter() { for &(ref k, ref v) in items.iter() {
mp.entry(k.val.clone()).or_insert(self.convert_value(v)?); mp.entry(k.clone()).or_insert(self.convert_value(v)?);
} }
Ok(toml::Value::Table(mp)) Ok(toml::Value::Table(mp))
} }

View File

@ -18,7 +18,7 @@ use std::io::Write;
use std::rc::Rc; use std::rc::Rc;
use super::traits::{ConvertResult, Converter}; use super::traits::{ConvertResult, Converter};
use crate::ast::{Position, PositionedItem}; use crate::ast::Position;
use crate::build::Val; use crate::build::Val;
use crate::error::BuildError; use crate::error::BuildError;
use crate::error::ErrorType; use crate::error::ErrorType;
@ -43,9 +43,7 @@ impl XmlConverter {
} }
} }
fn get_tuple_val( fn get_tuple_val(v: &Val) -> std::result::Result<&Vec<(String, Rc<Val>)>, Box<dyn Error>> {
v: &Val,
) -> std::result::Result<&Vec<(PositionedItem<String>, Rc<Val>)>, Box<dyn Error>> {
if let Val::Tuple(ref fs) = v { if let Val::Tuple(ref fs) = v {
Ok(fs) Ok(fs)
} else { } else {
@ -73,15 +71,15 @@ impl XmlConverter {
// First we determine if this is a tag or text node // First we determine if this is a tag or text node
if let Val::Tuple(ref fs) = v { if let Val::Tuple(ref fs) = v {
let mut name: Option<&str> = None; let mut name: Option<&str> = None;
let mut attrs: Option<&Vec<(PositionedItem<String>, Rc<Val>)>> = None; let mut attrs: Option<&Vec<(String, Rc<Val>)>> = None;
let mut children: Option<&Vec<Rc<Val>>> = None; let mut children: Option<&Vec<Rc<Val>>> = None;
let mut text: Option<&str> = None; let mut text: Option<&str> = None;
let mut ns: Option<(&str, &str)> = None; let mut ns: Option<(&str, &str)> = None;
for (ref field, ref val) in fs.iter() { for (ref field, ref val) in fs.iter() {
if field.val == "name" { if field == "name" {
name = Some(Self::get_str_val(val.as_ref())?); name = Some(Self::get_str_val(val.as_ref())?);
} }
if field.val == "ns" { if field == "ns" {
if let Val::Tuple(ref fs) = val.as_ref() { if let Val::Tuple(ref fs) = val.as_ref() {
let mut prefix = ""; let mut prefix = "";
let mut uri = ""; let mut uri = "";
@ -89,10 +87,10 @@ impl XmlConverter {
if val.is_empty() { if val.is_empty() {
continue; continue;
} }
if name.val == "uri" { if name == "uri" {
uri = Self::get_str_val(val.as_ref())?; uri = Self::get_str_val(val.as_ref())?;
} }
if name.val == "prefix" { if name == "prefix" {
prefix = Self::get_str_val(val.as_ref())?; prefix = Self::get_str_val(val.as_ref())?;
} }
} }
@ -103,19 +101,19 @@ impl XmlConverter {
ns = Some(("", s)); ns = Some(("", s));
} }
} }
if field.val == "attrs" { if field == "attrs" {
// This should be a tuple. // This should be a tuple.
if !val.is_empty() { if !val.is_empty() {
attrs = Some(Self::get_tuple_val(val.as_ref())?); attrs = Some(Self::get_tuple_val(val.as_ref())?);
} }
} }
if field.val == "children" { if field == "children" {
// This should be a list of tuples. // This should be a list of tuples.
if !val.is_empty() { if !val.is_empty() {
children = Some(Self::get_list_val(val.as_ref())?); children = Some(Self::get_list_val(val.as_ref())?);
} }
} }
if field.val == "text" { if field == "text" {
if !val.is_empty() { if !val.is_empty() {
text = Some(Self::get_str_val(val.as_ref())?); text = Some(Self::get_str_val(val.as_ref())?);
} }
@ -135,7 +133,7 @@ impl XmlConverter {
if val.is_empty() { if val.is_empty() {
continue; continue;
} }
start = start.attr(name.val.as_ref(), Self::get_str_val(val.as_ref())?); start = start.attr(name.as_ref(), Self::get_str_val(val.as_ref())?);
} }
} }
if let Some((prefix, uri)) = ns { if let Some((prefix, uri)) = ns {
@ -175,19 +173,19 @@ impl XmlConverter {
let mut standalone: Option<bool> = None; let mut standalone: Option<bool> = None;
let mut root: Option<Rc<Val>> = None; let mut root: Option<Rc<Val>> = None;
for &(ref name, ref val) in fs.iter() { for &(ref name, ref val) in fs.iter() {
if name.val == "version" { if name == "version" {
version = Some(Self::get_str_val(val)?); version = Some(Self::get_str_val(val)?);
} }
if name.val == "encoding" { if name == "encoding" {
encoding = Some(Self::get_str_val(val)?); encoding = Some(Self::get_str_val(val)?);
} }
if name.val == "standalone" { if name == "standalone" {
standalone = match val.as_ref() { standalone = match val.as_ref() {
Val::Boolean(b) => Some(*b), Val::Boolean(b) => Some(*b),
_ => None, _ => None,
}; };
} }
if name.val == "root" { if name == "root" {
root = Some(val.clone()); root = Some(val.clone());
} }
} }

View File

@ -7,7 +7,6 @@ use std::result::Result;
use serde_yaml; use serde_yaml;
use super::traits::{ConvertResult, Converter, ImportResult, Importer}; use super::traits::{ConvertResult, Converter, ImportResult, Importer};
use crate::ast;
use crate::build::Val; use crate::build::Val;
pub struct YamlConverter {} pub struct YamlConverter {}
@ -36,16 +35,10 @@ impl YamlConverter {
Ok(serde_yaml::Value::Mapping(mp)) Ok(serde_yaml::Value::Mapping(mp))
} }
fn convert_tuple( fn convert_tuple(&self, items: &Vec<(String, Rc<Val>)>) -> std::io::Result<serde_yaml::Value> {
&self,
items: &Vec<(ast::PositionedItem<String>, Rc<Val>)>,
) -> std::io::Result<serde_yaml::Value> {
let mut mapping = serde_yaml::Mapping::new(); let mut mapping = serde_yaml::Mapping::new();
for &(ref k, ref v) in items.iter() { for &(ref k, ref v) in items.iter() {
mapping.insert( mapping.insert(serde_yaml::Value::String(k.clone()), self.convert_value(v)?);
serde_yaml::Value::String(k.val.clone()),
self.convert_value(v)?,
);
} }
Ok(serde_yaml::Value::Mapping(mapping)) Ok(serde_yaml::Value::Mapping(mapping))
} }
@ -113,10 +106,7 @@ impl YamlConverter {
} }
}; };
eprintln!("yaml key is: {}", key); eprintln!("yaml key is: {}", key);
fs.push(( fs.push((key, Rc::new(self.convert_json_val(value)?)));
ast::PositionedItem::new(key, ast::Position::new(0, 0, 0)),
Rc::new(self.convert_json_val(value)?),
));
} }
Val::Tuple(fs) Val::Tuple(fs)
} }