Properly track locations on every AST node. Semantic errors are much more useful now. Also print parse errors in same (pseudo-standard compiler error) output format.

This commit is contained in:
Chris Fallin
2021-09-09 23:56:28 -07:00
parent 7d38b3b6d8
commit 2a574b1b42
5 changed files with 183 additions and 164 deletions

View File

@@ -19,7 +19,7 @@ pub enum Def {
/// An identifier -- a variable, term symbol, or type.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Ident(pub String);
pub struct Ident(pub String, pub Pos);
/// A declaration of a type.
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -35,8 +35,8 @@ pub struct Type {
/// TODO: add structs as well?
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TypeValue {
Primitive(Ident),
Enum(Vec<Variant>),
Primitive(Ident, Pos),
Enum(Vec<Variant>, Pos),
}
/// One variant of an enum type.
@@ -44,6 +44,7 @@ pub enum TypeValue {
pub struct Variant {
pub name: Ident,
pub fields: Vec<Field>,
pub pos: Pos,
}
/// One field of an enum variant.
@@ -51,6 +52,7 @@ pub struct Variant {
pub struct Field {
pub name: Ident,
pub ty: Ident,
pub pos: Pos,
}
/// A declaration of a term with its argument and return types.
@@ -85,22 +87,27 @@ pub struct Extractor {
pub enum Pattern {
/// An operator that binds a variable to a subterm and match the
/// subpattern.
BindPattern { var: Ident, subpat: Box<Pattern> },
BindPattern {
var: Ident,
subpat: Box<Pattern>,
pos: Pos,
},
/// A variable that has already been bound (`=x` syntax).
Var { var: Ident },
Var { var: Ident, pos: Pos },
/// An operator that matches a constant integer value.
ConstInt { val: i64 },
ConstInt { val: i64, pos: Pos },
/// An application of a type variant or term.
Term {
sym: Ident,
args: Vec<TermArgPattern>,
pos: Pos,
},
/// An operator that matches anything.
Wildcard,
Wildcard { pos: Pos },
/// N sub-patterns that must all match.
And { subpats: Vec<Pattern> },
And { subpats: Vec<Pattern>, pos: Pos },
/// Internal use only: macro argument in a template.
MacroArg { index: usize },
MacroArg { index: usize, pos: Pos },
}
impl Pattern {
@@ -118,9 +125,11 @@ impl Pattern {
&Pattern::BindPattern {
ref var,
ref subpat,
} if matches!(&**subpat, &Pattern::Wildcard) => {
pos,
..
} if matches!(&**subpat, &Pattern::Wildcard { .. }) => {
if let Some(i) = macro_args.iter().position(|arg| arg == var) {
Pattern::MacroArg { index: i }
Pattern::MacroArg { index: i, pos }
} else {
self.clone()
}
@@ -128,18 +137,24 @@ impl Pattern {
&Pattern::BindPattern {
ref var,
ref subpat,
pos,
} => Pattern::BindPattern {
var: var.clone(),
subpat: Box::new(subpat.make_macro_template(macro_args)),
pos,
},
&Pattern::And { ref subpats } => {
&Pattern::And { ref subpats, pos } => {
let subpats = subpats
.iter()
.map(|subpat| subpat.make_macro_template(macro_args))
.collect::<Vec<_>>();
Pattern::And { subpats }
Pattern::And { subpats, pos }
}
&Pattern::Term { ref sym, ref args } => {
&Pattern::Term {
ref sym,
ref args,
pos,
} => {
let args = args
.iter()
.map(|arg| arg.make_macro_template(macro_args))
@@ -147,10 +162,13 @@ impl Pattern {
Pattern::Term {
sym: sym.clone(),
args,
pos,
}
}
&Pattern::Var { .. } | &Pattern::Wildcard | &Pattern::ConstInt { .. } => self.clone(),
&Pattern::Var { .. } | &Pattern::Wildcard { .. } | &Pattern::ConstInt { .. } => {
self.clone()
}
&Pattern::MacroArg { .. } => unreachable!(),
}
}
@@ -160,18 +178,24 @@ impl Pattern {
&Pattern::BindPattern {
ref var,
ref subpat,
pos,
} => Pattern::BindPattern {
var: var.clone(),
subpat: Box::new(subpat.subst_macro_args(macro_args)),
pos,
},
&Pattern::And { ref subpats } => {
&Pattern::And { ref subpats, pos } => {
let subpats = subpats
.iter()
.map(|subpat| subpat.subst_macro_args(macro_args))
.collect::<Vec<_>>();
Pattern::And { subpats }
Pattern::And { subpats, pos }
}
&Pattern::Term { ref sym, ref args } => {
&Pattern::Term {
ref sym,
ref args,
pos,
} => {
let args = args
.iter()
.map(|arg| arg.subst_macro_args(macro_args))
@@ -179,11 +203,26 @@ impl Pattern {
Pattern::Term {
sym: sym.clone(),
args,
pos,
}
}
&Pattern::Var { .. } | &Pattern::Wildcard | &Pattern::ConstInt { .. } => self.clone(),
&Pattern::MacroArg { index } => macro_args[index].clone(),
&Pattern::Var { .. } | &Pattern::Wildcard { .. } | &Pattern::ConstInt { .. } => {
self.clone()
}
&Pattern::MacroArg { index, .. } => macro_args[index].clone(),
}
}
pub fn pos(&self) -> Pos {
match self {
&Pattern::ConstInt { pos, .. }
| &Pattern::And { pos, .. }
| &Pattern::Term { pos, .. }
| &Pattern::BindPattern { pos, .. }
| &Pattern::Var { pos, .. }
| &Pattern::Wildcard { pos, .. }
| &Pattern::MacroArg { pos, .. } => pos,
}
}
}
@@ -231,13 +270,32 @@ impl TermArgPattern {
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Expr {
/// A term: `(sym args...)`.
Term { sym: Ident, args: Vec<Expr> },
Term {
sym: Ident,
args: Vec<Expr>,
pos: Pos,
},
/// A variable use.
Var { name: Ident },
Var { name: Ident, pos: Pos },
/// A constant integer.
ConstInt { val: i64 },
ConstInt { val: i64, pos: Pos },
/// The `(let ((var ty val)*) body)` form.
Let { defs: Vec<LetDef>, body: Box<Expr> },
Let {
defs: Vec<LetDef>,
body: Box<Expr>,
pos: Pos,
},
}
impl Expr {
pub fn pos(&self) -> Pos {
match self {
&Expr::Term { pos, .. }
| &Expr::Var { pos, .. }
| &Expr::ConstInt { pos, .. }
| &Expr::Let { pos, .. } => pos,
}
}
}
/// One variable locally bound in a `(let ...)` expression.
@@ -246,6 +304,7 @@ pub struct LetDef {
pub var: Ident,
pub ty: Ident,
pub val: Box<Expr>,
pub pos: Pos,
}
/// An external binding: an extractor or constructor function attached

View File

@@ -23,7 +23,7 @@ impl fmt::Display for Error {
ref filename,
pos,
} => {
write!(f, "{}:{}: {}", filename, pos.line, msg)
write!(f, "{}:{}:{}: error: {}", filename, pos.line, pos.col, msg)
}
&Error::SystemError { ref msg } => {
write!(f, "{}", msg)

View File

@@ -46,7 +46,14 @@ fn main() -> Result<(), error::Error> {
let lexer = lexer::Lexer::from_files(input_files)?;
let mut parser = parser::Parser::new(lexer);
let defs = parser.parse_defs()?;
let defs = match parser.parse_defs() {
Ok(defs) => defs,
Err(error) => {
eprintln!("{}", error);
eprintln!("Failed to parse input.");
std::process::exit(1);
}
};
let code = match compile::compile(&defs) {
Ok(code) => code,
Err(errors) => {

View File

@@ -147,7 +147,7 @@ impl<'a> Parser<'a> {
),
));
}
Ok(Ident(s.to_string()))
Ok(Ident(s.to_string(), pos))
}
fn parse_ident(&mut self) -> ParseResult<Ident> {
@@ -180,7 +180,8 @@ impl<'a> Parser<'a> {
self.symbol()?;
let primitive_ident = self.parse_ident()?;
self.rparen()?;
Ok(TypeValue::Primitive(primitive_ident))
let pos = pos.unwrap();
Ok(TypeValue::Primitive(primitive_ident, pos))
} else if self.is_sym_str("enum") {
self.symbol()?;
let mut variants = vec![];
@@ -189,7 +190,8 @@ impl<'a> Parser<'a> {
variants.push(variant);
}
self.rparen()?;
Ok(TypeValue::Enum(variants))
let pos = pos.unwrap();
Ok(TypeValue::Enum(variants, pos))
} else {
Err(self.error(pos.unwrap(), "Unknown type definition".to_string()))
}
@@ -197,12 +199,15 @@ impl<'a> Parser<'a> {
fn parse_type_variant(&mut self) -> ParseResult<Variant> {
if self.is_sym() {
let pos = self.pos().unwrap();
let name = self.parse_ident()?;
Ok(Variant {
name,
fields: vec![],
pos,
})
} else {
let pos = self.pos();
self.lparen()?;
let name = self.parse_ident()?;
let mut fields = vec![];
@@ -210,16 +215,19 @@ impl<'a> Parser<'a> {
fields.push(self.parse_type_field()?);
}
self.rparen()?;
Ok(Variant { name, fields })
let pos = pos.unwrap();
Ok(Variant { name, fields, pos })
}
}
fn parse_type_field(&mut self) -> ParseResult<Field> {
let pos = self.pos();
self.lparen()?;
let name = self.parse_ident()?;
let ty = self.parse_ident()?;
self.rparen()?;
Ok(Field { name, ty })
let pos = pos.unwrap();
Ok(Field { name, ty, pos })
}
fn parse_decl(&mut self) -> ParseResult<Decl> {
@@ -342,30 +350,38 @@ impl<'a> Parser<'a> {
fn parse_pattern(&mut self) -> ParseResult<Pattern> {
let pos = self.pos();
if self.is_int() {
Ok(Pattern::ConstInt { val: self.int()? })
let pos = pos.unwrap();
Ok(Pattern::ConstInt {
val: self.int()?,
pos,
})
} else if self.is_sym_str("_") {
let pos = pos.unwrap();
self.symbol()?;
Ok(Pattern::Wildcard)
Ok(Pattern::Wildcard { pos })
} else if self.is_sym() {
let pos = pos.unwrap();
let s = self.symbol()?;
if s.starts_with("=") {
let s = &s[1..];
let var = self.str_to_ident(pos.unwrap(), s)?;
Ok(Pattern::Var { var })
let var = self.str_to_ident(pos, s)?;
Ok(Pattern::Var { var, pos })
} else {
let var = self.str_to_ident(pos.unwrap(), &s)?;
let var = self.str_to_ident(pos, &s)?;
if self.is_at() {
self.at()?;
let subpat = Box::new(self.parse_pattern()?);
Ok(Pattern::BindPattern { var, subpat })
Ok(Pattern::BindPattern { var, subpat, pos })
} else {
Ok(Pattern::BindPattern {
var,
subpat: Box::new(Pattern::Wildcard),
subpat: Box::new(Pattern::Wildcard { pos }),
pos,
})
}
}
} else if self.is_lparen() {
let pos = pos.unwrap();
self.lparen()?;
if self.is_sym_str("and") {
self.symbol()?;
@@ -374,7 +390,7 @@ impl<'a> Parser<'a> {
subpats.push(self.parse_pattern()?);
}
self.rparen()?;
Ok(Pattern::And { subpats })
Ok(Pattern::And { subpats, pos })
} else {
let sym = self.parse_ident()?;
let mut args = vec![];
@@ -382,7 +398,7 @@ impl<'a> Parser<'a> {
args.push(self.parse_pattern_term_arg()?);
}
self.rparen()?;
Ok(Pattern::Term { sym, args })
Ok(Pattern::Term { sym, args, pos })
}
} else {
Err(self.error(pos.unwrap(), "Unexpected pattern".into()))
@@ -401,6 +417,7 @@ impl<'a> Parser<'a> {
fn parse_expr(&mut self) -> ParseResult<Expr> {
let pos = self.pos();
if self.is_lparen() {
let pos = pos.unwrap();
self.lparen()?;
if self.is_sym_str("let") {
self.symbol()?;
@@ -413,7 +430,7 @@ impl<'a> Parser<'a> {
self.rparen()?;
let body = Box::new(self.parse_expr()?);
self.rparen()?;
Ok(Expr::Let { defs, body })
Ok(Expr::Let { defs, body, pos })
} else {
let sym = self.parse_ident()?;
let mut args = vec![];
@@ -421,111 +438,37 @@ impl<'a> Parser<'a> {
args.push(self.parse_expr()?);
}
self.rparen()?;
Ok(Expr::Term { sym, args })
Ok(Expr::Term { sym, args, pos })
}
} else if self.is_sym_str("#t") {
let pos = pos.unwrap();
self.symbol()?;
Ok(Expr::ConstInt { val: 1 })
Ok(Expr::ConstInt { val: 1, pos })
} else if self.is_sym_str("#f") {
let pos = pos.unwrap();
self.symbol()?;
Ok(Expr::ConstInt { val: 0 })
Ok(Expr::ConstInt { val: 0, pos })
} else if self.is_sym() {
let pos = pos.unwrap();
let name = self.parse_ident()?;
Ok(Expr::Var { name })
Ok(Expr::Var { name, pos })
} else if self.is_int() {
let pos = pos.unwrap();
let val = self.int()?;
Ok(Expr::ConstInt { val })
Ok(Expr::ConstInt { val, pos })
} else {
Err(self.error(pos.unwrap(), "Invalid expression".into()))
}
}
fn parse_letdef(&mut self) -> ParseResult<LetDef> {
let pos = self.pos();
self.lparen()?;
let pos = pos.unwrap();
let var = self.parse_ident()?;
let ty = self.parse_ident()?;
let val = Box::new(self.parse_expr()?);
self.rparen()?;
Ok(LetDef { var, ty, val })
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn parse_type() {
let text = r"
;; comment
(type Inst extern (enum
(Alu (a Reg) (b Reg) (dest Reg))
(Load (a Reg) (dest Reg))))
(type u32 (primitive u32))
";
let defs = Parser::new(Lexer::from_str(text, "(none)"))
.parse_defs()
.expect("should parse");
assert_eq!(
defs,
Defs {
filenames: vec!["(none)".to_string()],
defs: vec![
Def::Type(Type {
name: Ident("Inst".to_string()),
is_extern: true,
ty: TypeValue::Enum(vec![
Variant {
name: Ident("Alu".to_string()),
fields: vec![
Field {
name: Ident("a".to_string()),
ty: Ident("Reg".to_string()),
},
Field {
name: Ident("b".to_string()),
ty: Ident("Reg".to_string()),
},
Field {
name: Ident("dest".to_string()),
ty: Ident("Reg".to_string()),
},
],
},
Variant {
name: Ident("Load".to_string()),
fields: vec![
Field {
name: Ident("a".to_string()),
ty: Ident("Reg".to_string()),
},
Field {
name: Ident("dest".to_string()),
ty: Ident("Reg".to_string()),
},
],
}
]),
pos: Pos {
file: 0,
offset: 42,
line: 3,
col: 18,
},
}),
Def::Type(Type {
name: Ident("u32".to_string()),
is_extern: false,
ty: TypeValue::Primitive(Ident("u32".to_string())),
pos: Pos {
file: 0,
offset: 167,
line: 6,
col: 18,
},
}),
]
}
);
Ok(LetDef { var, ty, val, pos })
}
}

View File

@@ -356,17 +356,20 @@ impl TypeEnv {
fn type_from_ast(&mut self, tid: TypeId, ty: &ast::Type) -> Option<Type> {
let name = self.intern(&ty.name).unwrap();
match &ty.ty {
&ast::TypeValue::Primitive(ref id) => Some(Type::Primitive(tid, self.intern_mut(id))),
&ast::TypeValue::Enum(ref ty_variants) => {
&ast::TypeValue::Primitive(ref id, ..) => {
Some(Type::Primitive(tid, self.intern_mut(id)))
}
&ast::TypeValue::Enum(ref ty_variants, ..) => {
let mut variants = vec![];
for variant in ty_variants {
let combined_ident = ast::Ident(format!("{}.{}", ty.name.0, variant.name.0));
let combined_ident =
ast::Ident(format!("{}.{}", ty.name.0, variant.name.0), variant.name.1);
let fullname = self.intern_mut(&combined_ident);
let name = self.intern_mut(&variant.name);
let id = VariantId(variants.len());
if variants.iter().any(|v: &Variant| v.name == name) {
self.report_error(
ty.pos,
variant.pos,
format!("Duplicate variant name in type: '{}'", variant.name.0),
);
return None;
@@ -376,7 +379,7 @@ impl TypeEnv {
let field_name = self.intern_mut(&field.name);
if fields.iter().any(|f: &Field| f.name == field_name) {
self.report_error(
ty.pos,
field.pos,
format!(
"Duplicate field name '{}' in variant '{}' of type",
field.name.0, variant.name.0
@@ -389,7 +392,7 @@ impl TypeEnv {
Some(tid) => *tid,
None => {
self.report_error(
ty.pos,
field.ty.1,
format!(
"Unknown type '{}' for field '{}' in variant '{}'",
field.ty.0, field.name.0, variant.name.0
@@ -503,10 +506,7 @@ impl TermEnv {
.map(|id| {
let sym = tyenv.intern_mut(id);
tyenv.type_map.get(&sym).cloned().ok_or_else(|| {
tyenv.report_error(
decl.pos,
format!("Unknown arg type: '{}'", id.0),
);
tyenv.report_error(id.1, format!("Unknown arg type: '{}'", id.0));
()
})
})
@@ -523,7 +523,7 @@ impl TermEnv {
Some(t) => t,
None => {
tyenv.report_error(
decl.pos,
decl.ret_ty.1,
format!("Unknown return type: '{}'", decl.ret_ty.0),
);
continue;
@@ -676,7 +676,6 @@ impl TermEnv {
let (lhs, ty) = match self.translate_pattern(
tyenv,
rule.pos,
&rule.pattern,
None,
&mut bindings,
@@ -688,7 +687,7 @@ impl TermEnv {
}
};
let rhs =
match self.translate_expr(tyenv, rule.pos, &rule.expr, ty, &mut bindings) {
match self.translate_expr(tyenv, &rule.expr, ty, &mut bindings) {
Some(x) => x,
None => {
continue;
@@ -794,7 +793,6 @@ impl TermEnv {
fn translate_pattern(
&self,
tyenv: &mut TypeEnv,
pos: Pos,
pat: &ast::Pattern,
expected_ty: Option<TypeId>,
bindings: &mut Bindings,
@@ -803,7 +801,7 @@ impl TermEnv {
log::trace!("translate_pattern: bindings = {:?}", bindings);
match pat {
// TODO: flag on primitive type decl indicating it's an integer type?
&ast::Pattern::ConstInt { val } => {
&ast::Pattern::ConstInt { val, pos } => {
let ty = match expected_ty {
Some(t) => t,
None => {
@@ -816,7 +814,7 @@ impl TermEnv {
};
Some((Pattern::ConstInt(ty, val), ty))
}
&ast::Pattern::Wildcard => {
&ast::Pattern::Wildcard { pos } => {
let ty = match expected_ty {
Some(t) => t,
None => {
@@ -826,12 +824,12 @@ impl TermEnv {
};
Some((Pattern::Wildcard(ty), ty))
}
&ast::Pattern::And { ref subpats } => {
&ast::Pattern::And { ref subpats, pos } => {
let mut expected_ty = expected_ty;
let mut children = vec![];
for subpat in subpats {
let (subpat, ty) =
match self.translate_pattern(tyenv, pos, &*subpat, expected_ty, bindings) {
match self.translate_pattern(tyenv, &*subpat, expected_ty, bindings) {
Some(x) => x,
None => {
// Try to keep going for more errors.
@@ -851,10 +849,11 @@ impl TermEnv {
&ast::Pattern::BindPattern {
ref var,
ref subpat,
pos,
} => {
// Do the subpattern first so we can resolve the type for sure.
let (subpat, ty) =
self.translate_pattern(tyenv, pos, &*subpat, expected_ty, bindings)?;
self.translate_pattern(tyenv, &*subpat, expected_ty, bindings)?;
let name = tyenv.intern_mut(var);
if bindings.vars.iter().any(|bv| bv.name == name) {
@@ -871,7 +870,7 @@ impl TermEnv {
Some((Pattern::BindPattern(ty, id, Box::new(subpat)), ty))
}
&ast::Pattern::Var { ref var } => {
&ast::Pattern::Var { ref var, pos } => {
// Look up the variable; it must already have been bound.
let name = tyenv.intern_mut(var);
let bv = match bindings.vars.iter().rev().find(|bv| bv.name == name) {
@@ -903,7 +902,11 @@ impl TermEnv {
};
Some((Pattern::Var(ty, bv.id), ty))
}
&ast::Pattern::Term { ref sym, ref args } => {
&ast::Pattern::Term {
ref sym,
ref args,
pos,
} => {
let name = tyenv.intern_mut(&sym);
// Look up the term.
let tid = match self.term_map.get(&name) {
@@ -950,7 +953,7 @@ impl TermEnv {
match &termdata.kind {
&TermKind::EnumVariant { .. } => {
for arg in args {
if let &ast::TermArgPattern::Expr(..) = arg {
if let &ast::TermArgPattern::Expr(_) = arg {
tyenv.report_error(pos, format!("Term in pattern '{}' cannot have an injected expr, because it is an enum variant", sym.0));
}
}
@@ -961,16 +964,16 @@ impl TermEnv {
for (arg, pol) in args.iter().zip(arg_polarity.iter()) {
match (arg, pol) {
(&ast::TermArgPattern::Expr(..), &ArgPolarity::Input) => {}
(&ast::TermArgPattern::Expr(..), &ArgPolarity::Output) => {
(&ast::TermArgPattern::Expr(ref e), &ArgPolarity::Output) => {
tyenv.report_error(
pos,
e.pos(),
"Expression used for output-polarity extractor arg"
.to_string(),
);
}
(_, &ArgPolarity::Output) => {}
(_, &ArgPolarity::Input) => {
tyenv.report_error(pos, "Non-expression used in pattern but expression required for input-polarity extractor arg".to_string());
(&ast::TermArgPattern::Pattern(ref p), &ArgPolarity::Input) => {
tyenv.report_error(p.pos(), "Non-expression used in pattern but expression required for input-polarity extractor arg".to_string());
}
}
}
@@ -993,7 +996,7 @@ impl TermEnv {
}
log::trace!("internal extractor macro args = {:?}", args);
let pat = template.subst_macro_args(&macro_args[..]);
return self.translate_pattern(tyenv, pos, &pat, expected_ty, bindings);
return self.translate_pattern(tyenv, &pat, expected_ty, bindings);
}
&TermKind::ExternalConstructor { .. } | &TermKind::InternalConstructor => {
// OK.
@@ -1043,7 +1046,7 @@ impl TermEnv {
match pat {
&ast::TermArgPattern::Pattern(ref pat) => {
let (subpat, ty) =
self.translate_pattern(tyenv, pos, pat, expected_ty, bindings)?;
self.translate_pattern(tyenv, pat, expected_ty, bindings)?;
Some((TermArgPattern::Pattern(subpat), ty))
}
&ast::TermArgPattern::Expr(ref expr) => {
@@ -1055,7 +1058,7 @@ impl TermEnv {
return None;
}
let ty = expected_ty.unwrap();
let expr = self.translate_expr(tyenv, pos, expr, expected_ty.unwrap(), bindings)?;
let expr = self.translate_expr(tyenv, expr, expected_ty.unwrap(), bindings)?;
Some((TermArgPattern::Expr(expr), ty))
}
}
@@ -1064,14 +1067,17 @@ impl TermEnv {
fn translate_expr(
&self,
tyenv: &mut TypeEnv,
pos: Pos,
expr: &ast::Expr,
ty: TypeId,
bindings: &mut Bindings,
) -> Option<Expr> {
log::trace!("translate_expr: {:?}", expr);
match expr {
&ast::Expr::Term { ref sym, ref args } => {
&ast::Expr::Term {
ref sym,
ref args,
pos,
} => {
// Look up the term.
let name = tyenv.intern_mut(&sym);
// Look up the term.
@@ -1108,7 +1114,7 @@ impl TermEnv {
let mut subexprs = vec![];
for (i, arg) in args.iter().enumerate() {
let arg_ty = self.terms[tid.index()].arg_tys[i];
let subexpr = match self.translate_expr(tyenv, pos, arg, arg_ty, bindings) {
let subexpr = match self.translate_expr(tyenv, arg, arg_ty, bindings) {
Some(s) => s,
None => {
continue;
@@ -1119,7 +1125,7 @@ impl TermEnv {
Some(Expr::Term(ty, *tid, subexprs))
}
&ast::Expr::Var { ref name } => {
&ast::Expr::Var { ref name, pos } => {
let sym = tyenv.intern_mut(name);
// Look through bindings, innermost (most recent) first.
let bv = match bindings.vars.iter().rev().find(|b| b.name == sym) {
@@ -1145,8 +1151,12 @@ impl TermEnv {
Some(Expr::Var(bv.ty, bv.id))
}
&ast::Expr::ConstInt { val } => Some(Expr::ConstInt(ty, val)),
&ast::Expr::Let { ref defs, ref body } => {
&ast::Expr::ConstInt { val, .. } => Some(Expr::ConstInt(ty, val)),
&ast::Expr::Let {
ref defs,
ref body,
pos,
} => {
let orig_binding_len = bindings.vars.len();
// For each new binding...
@@ -1182,7 +1192,7 @@ impl TermEnv {
// Evaluate the variable's value.
let val = Box::new(
match self.translate_expr(tyenv, pos, &def.val, ty, bindings) {
match self.translate_expr(tyenv, &def.val, ty, bindings) {
Some(e) => e,
None => {
// Keep going for more errors.
@@ -1200,7 +1210,7 @@ impl TermEnv {
}
// Evaluate the body, expecting the type of the overall let-expr.
let body = Box::new(self.translate_expr(tyenv, pos, body, ty, bindings)?);
let body = Box::new(self.translate_expr(tyenv, body, ty, bindings)?);
let body_ty = body.ty();
// Pop the bindings.