Implement list literals

This commit is contained in:
Greg Shuflin 2021-11-02 21:19:29 -07:00
parent 8336211a4b
commit a13ad0edaa
5 changed files with 26 additions and 6 deletions

View File

@ -187,7 +187,7 @@ impl<'a, 'b> Reducer<'a, 'b> {
Expression::Loop { cond, statements } Expression::Loop { cond, statements }
} }
ForExpression { .. } => Expression::ReductionError("For expr not implemented".to_string()), ForExpression { .. } => Expression::ReductionError("For expr not implemented".to_string()),
ListLiteral { .. } => Expression::ReductionError("ListLiteral expr not implemented".to_string()), ListLiteral(items) => Expression::List(items.iter().map(|item| self.expression(item)).collect()),
Access { name, expr } => Access { name, expr } =>
Expression::Access { name: name.as_ref().to_string(), expr: Box::new(self.expression(expr)) }, Expression::Access { name: name.as_ref().to_string(), expr: Box::new(self.expression(expr)) },
} }

View File

@ -51,6 +51,7 @@ pub enum Statement {
pub enum Expression { pub enum Expression {
Literal(Literal), Literal(Literal),
Tuple(Vec<Expression>), Tuple(Vec<Expression>),
List(Vec<Expression>),
Lookup(Lookup), Lookup(Lookup),
Assign { lval: DefId, rval: Box<Expression> }, Assign { lval: DefId, rval: Box<Expression> },
Access { name: String, expr: Box<Expression> }, Access { name: String, expr: Box<Expression> },

View File

@ -111,6 +111,12 @@ impl<'a, 'b> Evaluator<'a, 'b> {
.map(|expr| self.expression(expr)) .map(|expr| self.expression(expr))
.collect::<EvalResult<Vec<Primitive>>>()?, .collect::<EvalResult<Vec<Primitive>>>()?,
), ),
Expression::List(items) => Primitive::List(
items
.into_iter()
.map(|expr| self.expression(expr))
.collect::<EvalResult<Vec<Primitive>>>()?,
),
Expression::Lookup(kind) => match kind { Expression::Lookup(kind) => match kind {
Lookup::Function(ref id) => { Lookup::Function(ref id) => {
let mem = id.into(); let mem = id.into();

View File

@ -61,16 +61,16 @@ impl RuntimeError {
} }
} }
fn paren_wrapped(terms: impl Iterator<Item = String>) -> String { fn delim_wrapped(lhs: char, rhs: char, terms: impl Iterator<Item = String>) -> String {
let mut buf = String::new(); let mut buf = String::new();
write!(buf, "(").unwrap(); write!(buf, "{}", lhs).unwrap();
for term in terms.map(Some).intersperse(None) { for term in terms.map(Some).intersperse(None) {
match term { match term {
Some(e) => write!(buf, "{}", e).unwrap(), Some(e) => write!(buf, "{}", e).unwrap(),
None => write!(buf, ", ").unwrap(), None => write!(buf, ", ").unwrap(),
}; };
} }
write!(buf, ")").unwrap(); write!(buf, "{}", rhs).unwrap();
buf buf
} }
@ -110,6 +110,7 @@ impl From<Primitive> for RuntimeValue {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum Primitive { enum Primitive {
Tuple(Vec<Primitive>), Tuple(Vec<Primitive>),
List(Vec<Primitive>),
Literal(Literal), Literal(Literal),
Callable(Callable), Callable(Callable),
Object { type_id: TypeId, tag: u32, ordered_fields: Option<Vec<String>>, items: Vec<Primitive> }, Object { type_id: TypeId, tag: u32, ordered_fields: Option<Vec<String>>, items: Vec<Primitive> },
@ -124,7 +125,7 @@ impl Primitive {
format!( format!(
"{}{}", "{}{}",
type_context.variant_local_name(type_id, *tag).unwrap(), type_context.variant_local_name(type_id, *tag).unwrap(),
paren_wrapped(items.iter().map(|item| item.to_repl(type_context))) delim_wrapped('(', ')', items.iter().map(|item| item.to_repl(type_context)))
) )
} }
Primitive::Object { type_id, items, tag, ordered_fields: Some(fields) } => { Primitive::Object { type_id, items, tag, ordered_fields: Some(fields) } => {
@ -145,7 +146,8 @@ impl Primitive {
Literal::Bool(b) => format!("{}", b), Literal::Bool(b) => format!("{}", b),
Literal::StringLit(s) => format!("\"{}\"", s), Literal::StringLit(s) => format!("\"{}\"", s),
}, },
Primitive::Tuple(terms) => paren_wrapped(terms.iter().map(|x| x.to_repl(type_context))), Primitive::Tuple(terms) => delim_wrapped('(', ')', terms.iter().map(|x| x.to_repl(type_context))),
Primitive::List(terms) => delim_wrapped('[', ']', terms.iter().map(|x| x.to_repl(type_context))),
Primitive::Callable(..) => "<some-callable>".to_string(), Primitive::Callable(..) => "<some-callable>".to_string(),
} }
} }

View File

@ -526,3 +526,14 @@ while a < 10 {
acc"#; acc"#;
eval_assert(source, "19"); eval_assert(source, "19");
} }
#[test]
fn list_literals() {
eval_assert(
r#"
let a = [7, 8, 9]
a
"#,
"[7, 8, 9]",
);
}