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() {
|
fn main() {
|
||||||
let src = "
|
let src = "
|
||||||
{
|
{
|
||||||
let x: num = 1;
|
let foo : num =
|
||||||
let y: num = 2;
|
let a : num = true,
|
||||||
x
|
b : num = 3
|
||||||
|
in
|
||||||
|
a + b;
|
||||||
|
foo * 2
|
||||||
}
|
}
|
||||||
".to_string();
|
".to_string();
|
||||||
let filename = "?".to_string();
|
let filename = "?".to_string();
|
||||||
|
@ -32,7 +35,7 @@ fn main() {
|
||||||
.with_label(Label::new((filename.clone(), ty_err.loc.into_range()))
|
.with_label(Label::new((filename.clone(), ty_err.loc.into_range()))
|
||||||
.with_message(match ty_err.note {
|
.with_message(match ty_err.note {
|
||||||
Some(note) => note,
|
Some(note) => note,
|
||||||
None => "while type checking this expression".to_string(),
|
None => "While type checking this expression".to_string(),
|
||||||
})
|
})
|
||||||
.with_color(Color::Red)
|
.with_color(Color::Red)
|
||||||
);
|
);
|
||||||
|
|
|
@ -356,7 +356,78 @@ pub fn expr_parser<'tokens, 'src: 'tokens>() -> impl Parser<
|
||||||
None => (f.0, f.1),
|
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) => {
|
Expr::Ident(name) => {
|
||||||
let ty = env.lookup(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))
|
oks!(TExpr::Ident(name, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +112,12 @@ fn type_expr<'src>(
|
||||||
UnaryOp::Not => Type::Bool,
|
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 {
|
oks!(TExpr::Unary {
|
||||||
op,
|
op,
|
||||||
expr: sbox!(te),
|
expr: sbox!(te),
|
||||||
|
@ -122,22 +128,46 @@ fn type_expr<'src>(
|
||||||
Expr::Binary(op, lhs, rhs) => {
|
Expr::Binary(op, lhs, rhs) => {
|
||||||
let tlhs = type_expr(env, unbox!(lhs))?;
|
let tlhs = type_expr(env, unbox!(lhs))?;
|
||||||
let trhs = type_expr(env, unbox!(rhs))?;
|
let trhs = type_expr(env, unbox!(rhs))?;
|
||||||
let ret_ty = match op {
|
let op_ty = match op {
|
||||||
BinaryOp::Add
|
BinaryOp::Add
|
||||||
| BinaryOp::Sub
|
| BinaryOp::Sub
|
||||||
| BinaryOp::Mul
|
| BinaryOp::Mul
|
||||||
| BinaryOp::Div
|
| BinaryOp::Div
|
||||||
| BinaryOp::Rem => Type::Num,
|
| BinaryOp::Rem => Some(Type::Num),
|
||||||
BinaryOp::And
|
BinaryOp::And
|
||||||
| BinaryOp::Or => Type::Bool,
|
| BinaryOp::Or => Some(Type::Bool),
|
||||||
BinaryOp::Eq
|
BinaryOp::Eq
|
||||||
| BinaryOp::Ne
|
| BinaryOp::Ne
|
||||||
| BinaryOp::Lt
|
| BinaryOp::Lt
|
||||||
| BinaryOp::Le
|
| BinaryOp::Le
|
||||||
| BinaryOp::Gt
|
| 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 {
|
oks!(TExpr::Binary {
|
||||||
op,
|
op,
|
||||||
lhs: sbox!(tlhs),
|
lhs: sbox!(tlhs),
|
||||||
|
@ -199,17 +229,17 @@ fn type_expr<'src>(
|
||||||
if param_tys.len() != targs.len() {
|
if param_tys.len() != targs.len() {
|
||||||
return Err(TypeError::new(
|
return Err(TypeError::new(
|
||||||
format!(
|
format!(
|
||||||
"expected {} arguments, got {}",
|
"Expected {} arguments, got {}",
|
||||||
param_tys.len(),
|
param_tys.len(),
|
||||||
targs.len(),
|
targs.len(),
|
||||||
),
|
),
|
||||||
args_span.into(),
|
args_span.into(),
|
||||||
).with_note(format!(
|
).with_note(format!(
|
||||||
"expected {} arguments",
|
"Expected {} arguments",
|
||||||
param_tys.len(),
|
param_tys.len(),
|
||||||
)).with_hint(
|
)).with_hint(
|
||||||
format!(
|
format!(
|
||||||
"this expect arguments of type `{}`",
|
"This expect arguments of type `{}`",
|
||||||
param_tys.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
|
param_tys.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
|
||||||
),
|
),
|
||||||
func.1,
|
func.1,
|
||||||
|
@ -221,13 +251,13 @@ fn type_expr<'src>(
|
||||||
if arg.0.ty() != param {
|
if arg.0.ty() != param {
|
||||||
return Err(TypeError::new(
|
return Err(TypeError::new(
|
||||||
format!(
|
format!(
|
||||||
"expected argument of type `{}`, got `{}`",
|
"Expected argument of type `{}`, got `{}`",
|
||||||
param,
|
param,
|
||||||
arg.0.ty(),
|
arg.0.ty(),
|
||||||
),
|
),
|
||||||
arg.1,
|
arg.1,
|
||||||
).with_note(format!(
|
).with_note(format!(
|
||||||
"expected argument of type `{}`",
|
"Expected argument of type `{}`",
|
||||||
param,
|
param,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -241,7 +271,7 @@ fn type_expr<'src>(
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(TypeError::new(
|
Err(TypeError::new(
|
||||||
format!("expected function, got `{}`", tfunc.0.ty()),
|
format!("Expected function, got `{}`", tfunc.0.ty()),
|
||||||
tfunc.1,
|
tfunc.1,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -255,7 +285,7 @@ fn type_expr<'src>(
|
||||||
// Check if the condition is of type `bool`.
|
// Check if the condition is of type `bool`.
|
||||||
if tcond.0.ty() != &Type::Bool {
|
if tcond.0.ty() != &Type::Bool {
|
||||||
return Err(TypeError::new(
|
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,
|
tcond.1,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -264,13 +294,13 @@ fn type_expr<'src>(
|
||||||
if tt.0.ty() != tf.0.ty() {
|
if tt.0.ty() != tf.0.ty() {
|
||||||
return Err(TypeError::new(
|
return Err(TypeError::new(
|
||||||
format!(
|
format!(
|
||||||
"expected the branches to have the same type, got `{}` and `{}`",
|
"Expected the branches to have the same type, got `{}` and `{}`",
|
||||||
tt.0.ty(),
|
tt.0.ty(),
|
||||||
tf.0.ty(),
|
tf.0.ty(),
|
||||||
),
|
),
|
||||||
tf.1,
|
tf.1,
|
||||||
).with_note(format!(
|
).with_note(format!(
|
||||||
"expected this branch to be type of `{}`",
|
"Expected this branch to be type of `{}`",
|
||||||
tt.0.ty(),
|
tt.0.ty(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -300,13 +330,13 @@ fn type_expr<'src>(
|
||||||
if texpr.0.ty() != &ty {
|
if texpr.0.ty() != &ty {
|
||||||
return Err(TypeError::new(
|
return Err(TypeError::new(
|
||||||
format!(
|
format!(
|
||||||
"expected the binding to be of type `{}`, got `{}`",
|
"Expected the value to be of type `{}`, got `{}`",
|
||||||
ty,
|
ty,
|
||||||
texpr.0.ty(),
|
texpr.0.ty(),
|
||||||
),
|
),
|
||||||
texpr.1,
|
texpr.1,
|
||||||
).with_note(format!(
|
).with_note(format!(
|
||||||
"expected this binding to be of type `{}`",
|
"Expected this value to be of type `{}`",
|
||||||
ty,
|
ty,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
@ -339,13 +369,13 @@ fn type_expr<'src>(
|
||||||
if texpr.0.ty() != &ty {
|
if texpr.0.ty() != &ty {
|
||||||
return Err(TypeError::new(
|
return Err(TypeError::new(
|
||||||
format!(
|
format!(
|
||||||
"expected the binding to be of type `{}`, got `{}`",
|
"Expected the binding to be of type `{}`, got `{}`",
|
||||||
ty,
|
ty,
|
||||||
texpr.0.ty(),
|
texpr.0.ty(),
|
||||||
),
|
),
|
||||||
texpr.1,
|
texpr.1,
|
||||||
).with_note(format!(
|
).with_note(format!(
|
||||||
"expected this binding to be of type `{}`",
|
"Expected this binding to be of type `{}`",
|
||||||
ty,
|
ty,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue