Skip to content

Commit bfaad1f

Browse files
committed
Wip overload example type-checker
1 parent 409ebb1 commit bfaad1f

File tree

3 files changed

+62
-13
lines changed

3 files changed

+62
-13
lines changed

scopegraphs/examples/overload/ast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct Arg {
1818
pub type_ann: Option<Type>,
1919
}
2020

21-
#[derive(Debug, Clone, PartialEq, Eq)]
21+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2222
pub enum Type {
2323
IntT,
2424
BoolT,

scopegraphs/examples/overload/main.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::parse::parse;
66
mod ast;
77
mod parse;
88
mod union_find;
9+
mod type_check;
910

1011
pub fn main() {
1112
let program = "
@@ -25,17 +26,21 @@ pub fn main() {
2526
$ and(not(false), tt())
2627
";
2728

28-
assert!(parse(program).is_ok())
29+
let result = parse(program);
30+
31+
println!("{:?}", result);
32+
33+
assert!(result.is_ok())
2934
}
3035

31-
#[derive(Debug, Clone, PartialEq, Eq)]
36+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3237
pub enum PartialType {
3338
// Types are not recursive, so no need to have separate constructors for each variant
3439
Type(Type),
3540
Variable(TypeVar),
3641
}
3742

38-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3944
pub struct TypeVar(usize);
4045

4146
pub struct FunType {

scopegraphs/examples/overload/parse.rs

+53-9
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ use winnow::seq;
1010
use winnow::stream::AsChar;
1111
use winnow::token::{one_of, take_while};
1212

13+
const KEYWORDS: [&str; 7] = ["fun", "if", "else", "true", "false", "int", "bool"];
14+
1315
fn ws<'a, F, O, E: ParserError<&'a str>>(inner: F) -> impl Parser<&'a str, O, E>
1416
where
1517
F: Parser<&'a str, O, E>,
@@ -23,7 +25,7 @@ fn parse_ident(input: &mut &'_ str) -> PResult<String> {
2325
take_while(0.., |c: char| c.is_alphanum() || c == '_'),
2426
)
2527
.recognize()
26-
.verify(|i: &str| !["fun", "if", "else", "true", "false", "int", "bool"].contains(&i)))
28+
.verify(|i: &str| !KEYWORDS.contains(&i)))
2729
.context(StrContext::Label("parse ident"))
2830
.parse_next(input)
2931
.map(|i| i.to_string())
@@ -63,7 +65,6 @@ fn parse_base_expr(input: &mut &'_ str) -> PResult<Expr> {
6365
alt((
6466
parse_int.map(Expr::IntLit),
6567
parse_bool.map(Expr::BoolLit),
66-
parse_ident.map(Expr::Ident),
6768
seq! {
6869
_: ws("if"),
6970
parse_expr,
@@ -85,6 +86,7 @@ fn parse_base_expr(input: &mut &'_ str) -> PResult<Expr> {
8586
_: ws(")")
8687
}
8788
.map(|(function_name, args)| Expr::FunCall(function_name, args)),
89+
parse_ident.map(Expr::Ident), // must come after funcall
8890
parse_bracketed,
8991
))
9092
.context(StrContext::Label("parse base expr"))
@@ -190,7 +192,7 @@ pub fn parse_program(input: &mut &'_ str) -> PResult<Program> {
190192
}
191193

192194
pub fn parse(mut input: &str) -> PResult<Program> {
193-
terminated(parse_program, eof).parse_next(&mut input)
195+
terminated(ws(parse_program), eof).parse_next(&mut input)
194196
}
195197

196198
pub fn parse_trace(mut input: &str) -> PResult<Program> {
@@ -208,7 +210,7 @@ mod test {
208210

209211
use crate::{
210212
parse::{parse, parse_arith_expr, parse_base_expr, parse_cmp_expr, parse_ident},
211-
Expr,
213+
Expr, Type,
212214
};
213215

214216
use super::{parse_args, parse_expr, parse_function, parse_trace};
@@ -328,15 +330,57 @@ mod test {
328330
.is_err());
329331
}
330332

333+
#[test]
334+
pub fn parse_funcall_no_args() {
335+
let mut input = "foo()";
336+
assert_eq!(
337+
Expr::FunCall("foo".into(), vec![],),
338+
trace("parse expr", parse_expr)
339+
.parse_next(&mut input)
340+
.unwrap(),
341+
);
342+
}
343+
344+
#[test]
345+
pub fn parse_if_in_if() {
346+
let mut input = "if a { if b < f(42, false) { c + 2 } else { d(true) } } else { f : int }";
347+
assert_eq!(
348+
Expr::IfThenElse(
349+
Expr::Ident("a".into()).into(),
350+
Expr::IfThenElse(
351+
Expr::Lt(
352+
Expr::Ident("b".into()).into(),
353+
Expr::FunCall("f".into(), vec![Expr::IntLit(42), Expr::BoolLit(false),])
354+
.into(),
355+
)
356+
.into(),
357+
Expr::Plus(Expr::Ident("c".into()).into(), Expr::IntLit(2).into(),).into(),
358+
Expr::FunCall("d".into(), vec![Expr::BoolLit(true),]).into(),
359+
)
360+
.into(),
361+
Expr::Ascribe(Expr::Ident("f".into()).into(), Type::IntT,).into(),
362+
),
363+
parse_expr(&mut input).unwrap()
364+
);
365+
}
366+
331367
#[test]
332368
pub fn parse_all_constructs() {
333369
let program = "
334370
fun tt() = true;
335-
fun lt(i1, i2) = (1 < 2);
336-
fun and(b1, b2: bool): bool =
337-
if b1 { b2: int } else { false };
338-
339-
$ tt()
371+
fun not(b) = if b { false } else { true };
372+
fun and(b1: bool, b2): bool =
373+
if b1 {
374+
if b2 {
375+
true
376+
} else {
377+
false
378+
}
379+
} else {
380+
false
381+
};
382+
383+
$ and(not(false), tt())
340384
";
341385

342386
assert!(parse_trace(program).is_ok());

0 commit comments

Comments
 (0)