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

View File

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

View File

@@ -46,7 +46,14 @@ fn main() -> Result<(), error::Error> {
let lexer = lexer::Lexer::from_files(input_files)?; let lexer = lexer::Lexer::from_files(input_files)?;
let mut parser = parser::Parser::new(lexer); 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) { let code = match compile::compile(&defs) {
Ok(code) => code, Ok(code) => code,
Err(errors) => { 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> { fn parse_ident(&mut self) -> ParseResult<Ident> {
@@ -180,7 +180,8 @@ impl<'a> Parser<'a> {
self.symbol()?; self.symbol()?;
let primitive_ident = self.parse_ident()?; let primitive_ident = self.parse_ident()?;
self.rparen()?; self.rparen()?;
Ok(TypeValue::Primitive(primitive_ident)) let pos = pos.unwrap();
Ok(TypeValue::Primitive(primitive_ident, pos))
} else if self.is_sym_str("enum") { } else if self.is_sym_str("enum") {
self.symbol()?; self.symbol()?;
let mut variants = vec![]; let mut variants = vec![];
@@ -189,7 +190,8 @@ impl<'a> Parser<'a> {
variants.push(variant); variants.push(variant);
} }
self.rparen()?; self.rparen()?;
Ok(TypeValue::Enum(variants)) let pos = pos.unwrap();
Ok(TypeValue::Enum(variants, pos))
} else { } else {
Err(self.error(pos.unwrap(), "Unknown type definition".to_string())) 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> { fn parse_type_variant(&mut self) -> ParseResult<Variant> {
if self.is_sym() { if self.is_sym() {
let pos = self.pos().unwrap();
let name = self.parse_ident()?; let name = self.parse_ident()?;
Ok(Variant { Ok(Variant {
name, name,
fields: vec![], fields: vec![],
pos,
}) })
} else { } else {
let pos = self.pos();
self.lparen()?; self.lparen()?;
let name = self.parse_ident()?; let name = self.parse_ident()?;
let mut fields = vec![]; let mut fields = vec![];
@@ -210,16 +215,19 @@ impl<'a> Parser<'a> {
fields.push(self.parse_type_field()?); fields.push(self.parse_type_field()?);
} }
self.rparen()?; self.rparen()?;
Ok(Variant { name, fields }) let pos = pos.unwrap();
Ok(Variant { name, fields, pos })
} }
} }
fn parse_type_field(&mut self) -> ParseResult<Field> { fn parse_type_field(&mut self) -> ParseResult<Field> {
let pos = self.pos();
self.lparen()?; self.lparen()?;
let name = self.parse_ident()?; let name = self.parse_ident()?;
let ty = self.parse_ident()?; let ty = self.parse_ident()?;
self.rparen()?; self.rparen()?;
Ok(Field { name, ty }) let pos = pos.unwrap();
Ok(Field { name, ty, pos })
} }
fn parse_decl(&mut self) -> ParseResult<Decl> { fn parse_decl(&mut self) -> ParseResult<Decl> {
@@ -342,30 +350,38 @@ impl<'a> Parser<'a> {
fn parse_pattern(&mut self) -> ParseResult<Pattern> { fn parse_pattern(&mut self) -> ParseResult<Pattern> {
let pos = self.pos(); let pos = self.pos();
if self.is_int() { 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("_") { } else if self.is_sym_str("_") {
let pos = pos.unwrap();
self.symbol()?; self.symbol()?;
Ok(Pattern::Wildcard) Ok(Pattern::Wildcard { pos })
} else if self.is_sym() { } else if self.is_sym() {
let pos = pos.unwrap();
let s = self.symbol()?; let s = self.symbol()?;
if s.starts_with("=") { if s.starts_with("=") {
let s = &s[1..]; let s = &s[1..];
let var = self.str_to_ident(pos.unwrap(), s)?; let var = self.str_to_ident(pos, s)?;
Ok(Pattern::Var { var }) Ok(Pattern::Var { var, pos })
} else { } else {
let var = self.str_to_ident(pos.unwrap(), &s)?; let var = self.str_to_ident(pos, &s)?;
if self.is_at() { if self.is_at() {
self.at()?; self.at()?;
let subpat = Box::new(self.parse_pattern()?); let subpat = Box::new(self.parse_pattern()?);
Ok(Pattern::BindPattern { var, subpat }) Ok(Pattern::BindPattern { var, subpat, pos })
} else { } else {
Ok(Pattern::BindPattern { Ok(Pattern::BindPattern {
var, var,
subpat: Box::new(Pattern::Wildcard), subpat: Box::new(Pattern::Wildcard { pos }),
pos,
}) })
} }
} }
} else if self.is_lparen() { } else if self.is_lparen() {
let pos = pos.unwrap();
self.lparen()?; self.lparen()?;
if self.is_sym_str("and") { if self.is_sym_str("and") {
self.symbol()?; self.symbol()?;
@@ -374,7 +390,7 @@ impl<'a> Parser<'a> {
subpats.push(self.parse_pattern()?); subpats.push(self.parse_pattern()?);
} }
self.rparen()?; self.rparen()?;
Ok(Pattern::And { subpats }) Ok(Pattern::And { subpats, pos })
} else { } else {
let sym = self.parse_ident()?; let sym = self.parse_ident()?;
let mut args = vec![]; let mut args = vec![];
@@ -382,7 +398,7 @@ impl<'a> Parser<'a> {
args.push(self.parse_pattern_term_arg()?); args.push(self.parse_pattern_term_arg()?);
} }
self.rparen()?; self.rparen()?;
Ok(Pattern::Term { sym, args }) Ok(Pattern::Term { sym, args, pos })
} }
} else { } else {
Err(self.error(pos.unwrap(), "Unexpected pattern".into())) Err(self.error(pos.unwrap(), "Unexpected pattern".into()))
@@ -401,6 +417,7 @@ impl<'a> Parser<'a> {
fn parse_expr(&mut self) -> ParseResult<Expr> { fn parse_expr(&mut self) -> ParseResult<Expr> {
let pos = self.pos(); let pos = self.pos();
if self.is_lparen() { if self.is_lparen() {
let pos = pos.unwrap();
self.lparen()?; self.lparen()?;
if self.is_sym_str("let") { if self.is_sym_str("let") {
self.symbol()?; self.symbol()?;
@@ -413,7 +430,7 @@ impl<'a> Parser<'a> {
self.rparen()?; self.rparen()?;
let body = Box::new(self.parse_expr()?); let body = Box::new(self.parse_expr()?);
self.rparen()?; self.rparen()?;
Ok(Expr::Let { defs, body }) Ok(Expr::Let { defs, body, pos })
} else { } else {
let sym = self.parse_ident()?; let sym = self.parse_ident()?;
let mut args = vec![]; let mut args = vec![];
@@ -421,111 +438,37 @@ impl<'a> Parser<'a> {
args.push(self.parse_expr()?); args.push(self.parse_expr()?);
} }
self.rparen()?; self.rparen()?;
Ok(Expr::Term { sym, args }) Ok(Expr::Term { sym, args, pos })
} }
} else if self.is_sym_str("#t") { } else if self.is_sym_str("#t") {
let pos = pos.unwrap();
self.symbol()?; self.symbol()?;
Ok(Expr::ConstInt { val: 1 }) Ok(Expr::ConstInt { val: 1, pos })
} else if self.is_sym_str("#f") { } else if self.is_sym_str("#f") {
let pos = pos.unwrap();
self.symbol()?; self.symbol()?;
Ok(Expr::ConstInt { val: 0 }) Ok(Expr::ConstInt { val: 0, pos })
} else if self.is_sym() { } else if self.is_sym() {
let pos = pos.unwrap();
let name = self.parse_ident()?; let name = self.parse_ident()?;
Ok(Expr::Var { name }) Ok(Expr::Var { name, pos })
} else if self.is_int() { } else if self.is_int() {
let pos = pos.unwrap();
let val = self.int()?; let val = self.int()?;
Ok(Expr::ConstInt { val }) Ok(Expr::ConstInt { val, pos })
} else { } else {
Err(self.error(pos.unwrap(), "Invalid expression".into())) Err(self.error(pos.unwrap(), "Invalid expression".into()))
} }
} }
fn parse_letdef(&mut self) -> ParseResult<LetDef> { fn parse_letdef(&mut self) -> ParseResult<LetDef> {
let pos = self.pos();
self.lparen()?; self.lparen()?;
let pos = pos.unwrap();
let var = self.parse_ident()?; let var = self.parse_ident()?;
let ty = self.parse_ident()?; let ty = self.parse_ident()?;
let val = Box::new(self.parse_expr()?); let val = Box::new(self.parse_expr()?);
self.rparen()?; self.rparen()?;
Ok(LetDef { var, ty, val }) Ok(LetDef { var, ty, val, pos })
}
}
#[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,
},
}),
]
}
);
} }
} }

View File

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