mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
parse ops
This commit is contained in:
parent
646f9f6bd2
commit
454a31e2e9
11
src/main.rs
11
src/main.rs
|
@ -8,9 +8,12 @@ pub mod typing;
|
|||
fn main() {
|
||||
let src = "
|
||||
{
|
||||
let x: num = 1;
|
||||
let y: num = 2;
|
||||
x
|
||||
let foo : num =
|
||||
let a : num = true,
|
||||
b : num = 3
|
||||
in
|
||||
a + b;
|
||||
foo * 2
|
||||
}
|
||||
".to_string();
|
||||
let filename = "?".to_string();
|
||||
|
@ -32,7 +35,7 @@ fn main() {
|
|||
.with_label(Label::new((filename.clone(), ty_err.loc.into_range()))
|
||||
.with_message(match ty_err.note {
|
||||
Some(note) => note,
|
||||
None => "while type checking this expression".to_string(),
|
||||
None => "While type checking this expression".to_string(),
|
||||
})
|
||||
.with_color(Color::Red)
|
||||
);
|
||||
|
|
|
@ -356,7 +356,78 @@ pub fn expr_parser<'tokens, 'src: 'tokens>() -> impl Parser<
|
|||
None => (f.0, f.1),
|
||||
});
|
||||
|
||||
call
|
||||
let op = choice((
|
||||
just(Token::Sub).to(UnaryOp::Neg),
|
||||
just(Token::Not).to(UnaryOp::Not),
|
||||
));
|
||||
let unary = op
|
||||
.map_with_span(|op, s| (op, s))
|
||||
.repeated()
|
||||
.foldr(
|
||||
call,
|
||||
|op, expr| {
|
||||
let span = op.1.start..expr.1.end;
|
||||
(Expr::Unary(op.0, boxspan(expr)), span.into())
|
||||
});
|
||||
|
||||
let op = choice((
|
||||
just(Token::Mul).to(BinaryOp::Mul),
|
||||
just(Token::Div).to(BinaryOp::Div),
|
||||
));
|
||||
let product = unary.clone()
|
||||
.foldl(
|
||||
op.then(unary).repeated(),
|
||||
|a, (op, b)| {
|
||||
let span = a.1.start..b.1.end;
|
||||
(Expr::Binary(op, boxspan(a), boxspan(b)), span.into())
|
||||
}
|
||||
);
|
||||
|
||||
let op = choice((
|
||||
just(Token::Add).to(BinaryOp::Add),
|
||||
just(Token::Sub).to(BinaryOp::Sub),
|
||||
));
|
||||
let sum = product.clone()
|
||||
.foldl(
|
||||
op.then(product).repeated(),
|
||||
|a, (op, b)| {
|
||||
let span = a.1.start..b.1.end;
|
||||
(Expr::Binary(op, boxspan(a), boxspan(b)), span.into())
|
||||
}
|
||||
);
|
||||
|
||||
let op = choice((
|
||||
just(Token::Eq).to(BinaryOp::Eq),
|
||||
just(Token::Ne).to(BinaryOp::Ne),
|
||||
just(Token::Lt).to(BinaryOp::Lt),
|
||||
just(Token::Le).to(BinaryOp::Le),
|
||||
just(Token::Gt).to(BinaryOp::Gt),
|
||||
just(Token::Ge).to(BinaryOp::Ge),
|
||||
));
|
||||
let comparison = sum.clone()
|
||||
.foldl(
|
||||
op.then(sum).repeated(),
|
||||
|a, (op, b)| {
|
||||
let span = a.1.start..b.1.end;
|
||||
(Expr::Binary(op, boxspan(a), boxspan(b)), span.into())
|
||||
}
|
||||
);
|
||||
|
||||
let op = choice((
|
||||
just(Token::And).to(BinaryOp::And),
|
||||
just(Token::Or).to(BinaryOp::Or),
|
||||
));
|
||||
let logical = comparison.clone()
|
||||
.foldl(
|
||||
op.then(comparison).repeated(),
|
||||
|a, (op, b)| {
|
||||
let span = a.1.start..b.1.end;
|
||||
(Expr::Binary(op, boxspan(a), boxspan(b)), span.into())
|
||||
}
|
||||
);
|
||||
|
||||
#[allow(clippy::let_and_return)]
|
||||
logical
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ fn type_expr<'src>(
|
|||
|
||||
Expr::Ident(name) => {
|
||||
let ty = env.lookup(name)
|
||||
.ok_or(TypeError::new(format!("unknown identifier `{}`", name), expr.1))?;
|
||||
.ok_or(TypeError::new(format!("Unknown identifier `{}`", name), expr.1))?;
|
||||
oks!(TExpr::Ident(name, ty))
|
||||
}
|
||||
|
||||
|
@ -112,6 +112,12 @@ fn type_expr<'src>(
|
|||
UnaryOp::Not => Type::Bool,
|
||||
};
|
||||
|
||||
if te.0.ty() != &ret_ty {
|
||||
return Err(TypeError::new(format!("Expected `{}` but found `{}`", ret_ty, te.0.ty()), te.1)
|
||||
.with_note(format!("This have type `{}`", te.0.ty()))
|
||||
.with_hint(format!("This operator requires a `{}`", ret_ty), (te.1.start-1..te.1.start).into()));
|
||||
}
|
||||
|
||||
oks!(TExpr::Unary {
|
||||
op,
|
||||
expr: sbox!(te),
|
||||
|
@ -122,22 +128,46 @@ fn type_expr<'src>(
|
|||
Expr::Binary(op, lhs, rhs) => {
|
||||
let tlhs = type_expr(env, unbox!(lhs))?;
|
||||
let trhs = type_expr(env, unbox!(rhs))?;
|
||||
let ret_ty = match op {
|
||||
let op_ty = match op {
|
||||
BinaryOp::Add
|
||||
| BinaryOp::Sub
|
||||
| BinaryOp::Mul
|
||||
| BinaryOp::Div
|
||||
| BinaryOp::Rem => Type::Num,
|
||||
| BinaryOp::Rem => Some(Type::Num),
|
||||
BinaryOp::And
|
||||
| BinaryOp::Or => Type::Bool,
|
||||
| BinaryOp::Or => Some(Type::Bool),
|
||||
BinaryOp::Eq
|
||||
| BinaryOp::Ne
|
||||
| BinaryOp::Lt
|
||||
| BinaryOp::Le
|
||||
| BinaryOp::Gt
|
||||
| BinaryOp::Ge => Type::Bool,
|
||||
| BinaryOp::Ge => None,
|
||||
};
|
||||
|
||||
let ret_ty;
|
||||
if let Some(op_ty) = op_ty {
|
||||
if tlhs.0.ty() != &op_ty {
|
||||
return Err(TypeError::new(format!("Expected `{}` but found `{}`", op_ty, tlhs.0.ty()), tlhs.1)
|
||||
.with_note(format!("This have type `{}`", tlhs.0.ty()))
|
||||
.with_hint(format!("This operator requires a `{}`", op_ty), (tlhs.1.start-1..tlhs.1.start).into()));
|
||||
}
|
||||
if trhs.0.ty() != &op_ty {
|
||||
return Err(TypeError::new(format!("Expected `{}` but found `{}`", op_ty, trhs.0.ty()), trhs.1)
|
||||
.with_note(format!("This have type `{}`", trhs.0.ty()))
|
||||
.with_hint(format!("This operator requires a `{}`", op_ty), (trhs.1.start-1..trhs.1.start).into()));
|
||||
}
|
||||
ret_ty = op_ty;
|
||||
} else {
|
||||
if tlhs.0.ty() != trhs.0.ty() {
|
||||
return Err(TypeError::new(format!("Expected `{}` but found `{}`", tlhs.0.ty(), trhs.0.ty()), trhs.1)
|
||||
.with_hint(
|
||||
format!("Both have to be the same type. Got `{}` and `{}`", tlhs.0.ty(), trhs.0.ty()),
|
||||
(tlhs.1.start..trhs.1.end).into(),
|
||||
));
|
||||
}
|
||||
ret_ty = Type::Bool;
|
||||
}
|
||||
|
||||
oks!(TExpr::Binary {
|
||||
op,
|
||||
lhs: sbox!(tlhs),
|
||||
|
@ -199,17 +229,17 @@ fn type_expr<'src>(
|
|||
if param_tys.len() != targs.len() {
|
||||
return Err(TypeError::new(
|
||||
format!(
|
||||
"expected {} arguments, got {}",
|
||||
"Expected {} arguments, got {}",
|
||||
param_tys.len(),
|
||||
targs.len(),
|
||||
),
|
||||
args_span.into(),
|
||||
).with_note(format!(
|
||||
"expected {} arguments",
|
||||
"Expected {} arguments",
|
||||
param_tys.len(),
|
||||
)).with_hint(
|
||||
format!(
|
||||
"this expect arguments of type `{}`",
|
||||
"This expect arguments of type `{}`",
|
||||
param_tys.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
|
||||
),
|
||||
func.1,
|
||||
|
@ -221,13 +251,13 @@ fn type_expr<'src>(
|
|||
if arg.0.ty() != param {
|
||||
return Err(TypeError::new(
|
||||
format!(
|
||||
"expected argument of type `{}`, got `{}`",
|
||||
"Expected argument of type `{}`, got `{}`",
|
||||
param,
|
||||
arg.0.ty(),
|
||||
),
|
||||
arg.1,
|
||||
).with_note(format!(
|
||||
"expected argument of type `{}`",
|
||||
"Expected argument of type `{}`",
|
||||
param,
|
||||
)));
|
||||
}
|
||||
|
@ -241,7 +271,7 @@ fn type_expr<'src>(
|
|||
})
|
||||
} else {
|
||||
Err(TypeError::new(
|
||||
format!("expected function, got `{}`", tfunc.0.ty()),
|
||||
format!("Expected function, got `{}`", tfunc.0.ty()),
|
||||
tfunc.1,
|
||||
))
|
||||
}
|
||||
|
@ -255,7 +285,7 @@ fn type_expr<'src>(
|
|||
// Check if the condition is of type `bool`.
|
||||
if tcond.0.ty() != &Type::Bool {
|
||||
return Err(TypeError::new(
|
||||
format!("expected condition of type `bool`, got `{}`", tcond.0.ty()),
|
||||
format!("Expected condition of type `bool`, got `{}`", tcond.0.ty()),
|
||||
tcond.1,
|
||||
));
|
||||
}
|
||||
|
@ -264,13 +294,13 @@ fn type_expr<'src>(
|
|||
if tt.0.ty() != tf.0.ty() {
|
||||
return Err(TypeError::new(
|
||||
format!(
|
||||
"expected the branches to have the same type, got `{}` and `{}`",
|
||||
"Expected the branches to have the same type, got `{}` and `{}`",
|
||||
tt.0.ty(),
|
||||
tf.0.ty(),
|
||||
),
|
||||
tf.1,
|
||||
).with_note(format!(
|
||||
"expected this branch to be type of `{}`",
|
||||
"Expected this branch to be type of `{}`",
|
||||
tt.0.ty(),
|
||||
)));
|
||||
}
|
||||
|
@ -300,13 +330,13 @@ fn type_expr<'src>(
|
|||
if texpr.0.ty() != &ty {
|
||||
return Err(TypeError::new(
|
||||
format!(
|
||||
"expected the binding to be of type `{}`, got `{}`",
|
||||
"Expected the value to be of type `{}`, got `{}`",
|
||||
ty,
|
||||
texpr.0.ty(),
|
||||
),
|
||||
texpr.1,
|
||||
).with_note(format!(
|
||||
"expected this binding to be of type `{}`",
|
||||
"Expected this value to be of type `{}`",
|
||||
ty,
|
||||
)));
|
||||
}
|
||||
|
@ -339,13 +369,13 @@ fn type_expr<'src>(
|
|||
if texpr.0.ty() != &ty {
|
||||
return Err(TypeError::new(
|
||||
format!(
|
||||
"expected the binding to be of type `{}`, got `{}`",
|
||||
"Expected the binding to be of type `{}`, got `{}`",
|
||||
ty,
|
||||
texpr.0.ty(),
|
||||
),
|
||||
texpr.1,
|
||||
).with_note(format!(
|
||||
"expected this binding to be of type `{}`",
|
||||
"Expected this binding to be of type `{}`",
|
||||
ty,
|
||||
)));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue