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:
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(¯o_args[..]);
|
let pat = template.subst_macro_args(¯o_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.
|
||||||
|
|||||||
Reference in New Issue
Block a user