diff --git a/src/checked.rs b/src/checked.rs deleted file mode 100644 index 6795737..0000000 --- a/src/checked.rs +++ /dev/null @@ -1,65 +0,0 @@ -#[derive(Clone, PartialEq, Debug)] -pub struct Node { - pub kind: NodeKind, - pub typ: Type, - pub table_id: usize, -} - -#[derive(Clone, PartialEq, Debug)] -pub enum NodeKind { - Error, - Id(u64), - Int(i64), - Str(String), - Group(Box), - Block(Vec), - Call { - subject: Box, - args: Vec, - }, - If { - cond: Box, - truthy: Box, - falsy: Option>, - }, - Loop { - body: Box, - }, - Break, - Assign { - subject: Box, - value: Box, - }, - Let { - subject: Box, - value: Box, - }, - Fn { - subject: Box, - params: Vec, - return_typ: Type, - body: Box, - id: u64, - }, - Return { - value: Option>, - }, - Param { - subject: Box, - typ: Option, - }, -} - -#[derive(Clone, PartialEq, Debug)] -pub enum Type { - Error, - Unit, - I32, - U32, - Str, - Fn { - id: u64, - params: Vec, - return_typ: Box, - }, -} diff --git a/src/checker.rs b/src/checker.rs deleted file mode 100644 index 8039806..0000000 --- a/src/checker.rs +++ /dev/null @@ -1,647 +0,0 @@ -use std::{rc::Rc, sync::Mutex}; - -use rand::random; - -use crate::{ - checked::{Node, NodeKind, Type}, - parsed, - pos::{Error, ErrorAcc, Pos}, - sym::Syms, - util::{hash, Itertewls}, -}; - -pub trait IdGen { - fn new() -> Self; - fn gen(&mut self) -> u64; -} - -pub struct RandIdGen; -impl IdGen for RandIdGen { - fn new() -> Self { - Self - } - fn gen(&mut self) -> u64 { - random() - } -} - -pub struct Checker { - syms: Syms, - fn_id_gen: FnIdGen, - error_acc: Rc>, -} - -impl Checker { - pub fn new(error_acc: Rc>) -> Self { - Self { - syms: Syms::new(), - fn_id_gen: RandIdGen::new(), - error_acc, - } - } -} - -impl Checker { - pub fn new_with_fn_id_gen(error_acc: Rc>) -> Self { - Self { - syms: Syms::new(), - fn_id_gen: FnIdGen::new(), - error_acc, - } - } - - pub fn finish(self) -> Syms { - self.syms - } - - pub fn check(&mut self, ast: &[parsed::Node]) -> Vec { - self.fn_scan(ast); - ast.iter().map(|stmt| self.check_expr(stmt)).collect() - } - - fn fn_scan(&mut self, ast: &[parsed::Node]) { - for node in ast { - let pos = node.pos.clone(); - if let parsed::NodeKind::Fn { - subject, - params, - return_typ, - body: _, - } = &node.kind - { - let Ok(params) = self.fn_scan_params(¶ms) else { - continue; - }; - - if let Some(_) = params.iter().map(|(id, _)| *id).find_first_duplicate() { - self.error("redefinition param", pos.clone()); - continue; - } - - let params = params - .into_iter() - .map(|(_, param)| { - let NodeKind::Param { subject: _, typ } = param.kind else {unreachable!()}; - typ.as_ref().cloned().unwrap() - }) - .collect::>(); - - let parsed::NodeKind::Id(id) = subject.as_ref().kind else { unreachable!() }; - - if self.syms.defined_locally(id) { - self.error("redefinition fn", pos.clone()); - continue; - } - - let return_typ = self.check_type(&return_typ); - - let typ = Type::Fn { - id: self.fn_id_gen.gen(), - params, - return_typ: Box::new(return_typ), - }; - - self.syms.define(id, typ.clone()); - } - } - } - - fn fn_scan_params(&self, params: &[parsed::Node]) -> Result, ()> { - params - .iter() - .map(|param| { - let parsed::NodeKind::Param { subject, typ } = ¶m.kind else { unreachable!() }; - let parsed::NodeKind::Id(id) = subject.as_ref().kind else { unreachable!() }; - let typ = self.check_type(typ.as_ref().ok_or(())?); - Ok(( - id, - self.node( - NodeKind::Param { - subject: Box::new(self.node(NodeKind::Id(id), Type::Unit)), - typ: Some(typ), - }, - Type::Unit, - ), - )) - }) - .collect::, _>>() - } - - fn check_expr(&mut self, node: &parsed::Node) -> Node { - let pos = node.pos.clone(); - match &node.kind { - parsed::NodeKind::Error => self.node(NodeKind::Error, Type::Unit), - parsed::NodeKind::Id(id) => { - let Some(sym) = self.syms.get(*id) else { - self.error("undefined >~<", pos.clone()); - return self.node(NodeKind::Error, Type::Error); - }; - self.node(NodeKind::Id(*id), sym.typ.clone()) - } - parsed::NodeKind::Int(value) => self.node( - NodeKind::Int(*value), - if *value > i32::MAX as i64 { - Type::U32 - } else { - Type::I32 - }, - ), - parsed::NodeKind::Str(value) => self.node(NodeKind::Str(value.clone()), Type::Str), - parsed::NodeKind::Group(expr) => { - let expr = self.check_expr(&expr); - let typ = expr.typ.clone(); - self.node(NodeKind::Group(Box::new(expr)), typ) - } - parsed::NodeKind::Block(stmts) => { - self.syms.enter_scope(); - let stmts = stmts - .iter() - .map(|stmt| self.check_expr(stmt)) - .collect::>(); - self.syms.leave_scope().unwrap(); - let typ = stmts - .last() - .map(|stmt| stmt.typ.clone()) - .unwrap_or(Type::Unit); - self.node(NodeKind::Block(stmts), typ) - } - parsed::NodeKind::Call { subject, args } => { - let subject = Box::new(self.check_expr(&subject)); - - let args = args - .iter() - .map(|arg| self.check_expr(arg)) - .collect::>(); - let typ = 'br: { - match subject.typ.clone() { - Type::Fn { - id: _, - params, - return_typ, - } => { - if args.len() != params.len() { - self.error("too few/many args", pos.clone()); - break 'br Type::Error; - } - if args - .iter() - .zip(params.clone()) - .map(|(arg, param)| self.compatible(&arg.typ, ¶m)) - .any(|is_compatible| !is_compatible) - { - self.error("incorrect args", pos.clone()); - break 'br Type::Error; - } - *return_typ - } - _ => { - self.error("not a function", pos.clone()); - Type::Error - } - } - }; - self.node(NodeKind::Call { subject, args }, typ) - } - parsed::NodeKind::If { - cond, - truthy, - falsy, - } => { - let cond = Box::new(self.check_expr(&cond)); - let truthy = Box::new(self.check_expr(&truthy)); - let falsy = falsy.as_ref().map(|block| Box::new(self.check_expr(block))); - let typ = 'br: { - match falsy.as_ref().map(|block| block.typ.clone()) { - Some(falsy_typ) => { - if !self.compatible(&truthy.typ, &falsy_typ) { - self.error("incompatible types #2", pos.clone()); - break 'br Type::Error; - } - falsy_typ - } - None => Type::Unit, - } - }; - self.node( - NodeKind::If { - cond, - truthy, - falsy, - }, - typ, - ) - } - parsed::NodeKind::Loop { body } => { - self.syms.enter_scope(); - let body = Box::new(self.check_expr(&body)); - let typ = body.typ.clone(); - self.node(NodeKind::Loop { body }, typ) - } - parsed::NodeKind::Break => self.node(NodeKind::Break, Type::Unit), - parsed::NodeKind::Assign { subject, value } => { - let subject = Box::new(self.check_expr(&subject)); - let value = Box::new(self.check_expr(&value)); - - match subject.kind { - NodeKind::Error => { - return *subject; - } - NodeKind::Id(_) => {} - _ => { - self.error("cannot assign to expr", pos.clone()); - return self.node(NodeKind::Error, Type::Error); - } - } - - let _typ = if !self.compatible(&subject.typ, &value.typ) { - self.error("incompatible types #3", pos.clone()); - Type::Error - } else { - subject.typ.clone() - }; - self.node(NodeKind::Assign { subject, value }, Type::Unit) - } - parsed::NodeKind::Let { subject, value } => { - let (subject, subject_typ) = match &subject.as_ref().kind { - parsed::NodeKind::Param { subject, typ } => { - (subject, typ.as_ref().map(|typ| self.check_type(typ))) - } - _ => unreachable!(), - }; - - let value = Box::new(self.check_expr(&value)); - let typ = value.typ.clone(); - - if subject_typ - .as_ref() - .map(|subject_typ| !self.compatible(subject_typ, &typ)) - .unwrap_or(false) - { - self.error("incompatible types #1", pos.clone()); - return self.node(NodeKind::Error, Type::Error); - } - - let subject = match subject.as_ref().kind { - parsed::NodeKind::Id(id) => { - if self.syms.defined_locally(id) { - self.error("redefinition", pos.clone()); - return self.node(NodeKind::Error, Type::Error); - } - self.syms.define(id, typ.clone()); - Box::new(self.node( - NodeKind::Param { - subject: Box::new(self.node(NodeKind::Id(id), Type::Unit)), - typ: Some(Type::Unit), - }, - Type::Unit, - )) - } - _ => unreachable!(), - }; - - self.node(NodeKind::Let { subject, value }, Type::Unit) - } - parsed::NodeKind::Fn { - subject, - params, - return_typ: _, - body, - } => { - let parsed::NodeKind::Id(id) = subject.as_ref().kind else { unreachable!() }; - - let Some(sym) = self.syms.get(id).cloned() else { - // rejected in fn scanner - return self.node(NodeKind::Error,Type::Error); - }; - - let Type::Fn { id: fn_id, params: param_typs, return_typ } = sym.typ else { - self.error("redefintion", pos.clone()); - return self.node(NodeKind::Error,Type::Error); - }; - - self.syms.enter_scope(); - - let params = params - .iter() - .zip(param_typs) - .map(|(param, typ)| { - let parsed::NodeKind::Param { subject, .. } = ¶m.kind else { unreachable!() }; - let parsed::NodeKind::Id(id) = subject.as_ref().kind else { unreachable!() }; - self.node( - NodeKind::Param { - subject: Box::new(self.node(NodeKind::Id(id), Type::Unit)), - typ: Some(typ), - }, - Type::Unit, - ) - }) - .collect::>(); - - for param in ¶ms { - let NodeKind::Param { ref subject, ref typ } = param.kind else { unreachable!() }; - let NodeKind::Id(id) = subject.kind else { unreachable!() }; - self.syms.define(id, typ.as_ref().cloned().unwrap()); - } - - let body = Box::new(self.check_expr(&body)); - - if !self.compatible(&return_typ, &body.typ) { - self.error("return type violated", pos.clone()); - } - - self.syms.leave_scope().unwrap(); - - self.node( - NodeKind::Fn { - subject: Box::new(self.node(NodeKind::Id(id), Type::Unit)), - params, - return_typ: *return_typ, - body, - id: fn_id, - }, - Type::Unit, - ) - } - parsed::NodeKind::Return { value } => { - let value = value.as_ref().map(|value| Box::new(self.check_expr(value))); - let typ = value - .as_ref() - .map(|value| value.typ.clone()) - .unwrap_or(Type::Unit); - self.node(NodeKind::Return { value }, typ) - } - parsed::NodeKind::Param { .. } => unreachable!("handle elsewhere"), - } - } - - fn check_type(&self, node: &parsed::Node) -> Type { - match node.kind { - parsed::NodeKind::Error => Type::Error, - parsed::NodeKind::Id(value) => { - if value == hash("i32") { - Type::I32 - } else if value == hash("u32") { - Type::U32 - } else { - todo!("symbol lookup idk") - } - } - _ => unreachable!(), - } - } - - fn compatible(&self, typ_a: &Type, typ_b: &Type) -> bool { - typ_a == typ_b - } - - fn node(&self, kind: NodeKind, typ: Type) -> Node { - Node { - kind, - typ, - table_id: self.syms.table_id(), - } - } - - fn error>(&mut self, msg: S, pos: Pos) { - let msg = msg.into(); - self.error_acc.lock().unwrap().add(Error { - kind: crate::pos::ErrorKind::CheckerError, - pos: Some(pos), - msg, - }); - } -} - -#[test] -fn test_checker() { - use crate::parser::Parser; - use pretty_assertions::assert_eq; - use NodeKind::{Block, Call, Error, Fn, Id, Int, Let, Param, Return}; - use Type::{Unit, I32}; - - struct SeqIdGen(u64); - impl IdGen for SeqIdGen { - fn new() -> Self { - Self(0) - } - - fn gen(&mut self) -> u64 { - let v = self.0; - self.0 += 1; - v - } - } - - let check = |text| { - let error_acc = Rc::new(Mutex::new(ErrorAcc::new())); - Checker::::new_with_fn_id_gen(error_acc.clone()) - .check(&Parser::new(text, error_acc).parse()) - }; - - assert_eq!( - check("let a = 5; a;"), - vec![ - Node { - kind: Let { - subject: Box::new(Node { - kind: Param { - subject: Box::new(Node { - kind: Id(hash("a")), - typ: Unit, - table_id: 0, - }), - typ: Some(Unit) - }, - typ: Unit, - table_id: 0, - }), - value: Box::new(Node { - kind: Int(5), - typ: I32, - table_id: 0, - }) - }, - typ: Unit, - table_id: 0, - }, - Node { - kind: Id(hash("a")), - typ: I32, - table_id: 0, - } - ] - ); - - assert_eq!( - check("let a = 5; { a; }"), - vec![ - Node { - kind: Let { - subject: Box::new(Node { - kind: Param { - subject: Box::new(Node { - kind: Id(hash("a")), - typ: Unit, - table_id: 0, - }), - typ: Some(Unit) - }, - typ: Unit, - table_id: 0, - }), - value: Box::new(Node { - kind: Int(5), - typ: I32, - table_id: 0, - }) - }, - typ: Unit, - table_id: 0, - }, - Node { - kind: Block(vec![Node { - kind: Id(hash("a")), - typ: I32, - table_id: 1, - },]), - typ: I32, - table_id: 0, - }, - ] - ); - - println!("intentionally undefined"); - assert_eq!( - check("let a = 5; a; { a; let b = 5; b; } a; b;"), - vec![ - Node { - kind: Let { - subject: Box::new(Node { - kind: Param { - subject: Box::new(Node { - kind: Id(hash("a")), - typ: Unit, - table_id: 0, - }), - typ: Some(Unit) - }, - typ: Unit, - table_id: 0, - }), - value: Box::new(Node { - kind: Int(5), - typ: I32, - table_id: 0, - }) - }, - typ: Unit, - table_id: 0, - }, - Node { - kind: Id(hash("a")), - typ: I32, - table_id: 0, - }, - Node { - kind: Block(vec![ - Node { - kind: Id(hash("a")), - typ: I32, - table_id: 1, - }, - Node { - kind: Let { - subject: Box::new(Node { - kind: Param { - subject: Box::new(Node { - kind: Id(hash("b")), - typ: Unit, - table_id: 1, - }), - typ: Some(Unit) - }, - typ: Unit, - table_id: 1, - }), - value: Box::new(Node { - kind: Int(5), - typ: I32, - table_id: 1, - }) - }, - typ: Unit, - table_id: 1, - }, - Node { - kind: Id(hash("b")), - typ: I32, - table_id: 1, - } - ]), - typ: I32, - table_id: 0, - }, - Node { - kind: Id(hash("a")), - typ: I32, - table_id: 0, - }, - Node { - kind: Error, - typ: Type::Error, - table_id: 0, - } - ] - ); - - assert_eq!( - check("fn a() -> i32 { return 0; } \n a();"), - vec![ - Node { - kind: Fn { - subject: Box::new(Node { - kind: Id(hash("a")), - typ: Unit, - table_id: 0, - }), - params: vec![], - return_typ: I32, - body: Box::new(Node { - kind: Block(vec![Node { - kind: Return { - value: Some(Box::new(Node { - kind: Int(0), - typ: I32, - table_id: 2, - }),), - }, - typ: I32, - table_id: 2, - },],), - typ: I32, - table_id: 1, - }), - id: 0, - }, - typ: Unit, - table_id: 0, - }, - Node { - kind: Call { - subject: Box::new(Node { - kind: Id(hash("a")), - typ: Type::Fn { - id: 0, - params: vec![], - return_typ: Box::new(I32) - }, - table_id: 0 - }), - args: vec![] - }, - typ: I32, - table_id: 0, - }, - ] - ); -} diff --git a/src/main.rs b/src/main.rs index e23754c..5ce7e19 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,5 @@ #![allow(dead_code)] -mod checked; -mod checker; -mod hir; -mod hir_compiler; mod lexer; mod parsed; mod parser; diff --git a/src/parser.rs b/src/parser.rs index 74e53a7..464cb7b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -278,13 +278,13 @@ impl<'a> Parser<'a> { fn parse_id(&mut self) -> Node { let pos = self.pos().unwrap(); let Some(Token { - kind: TokenKind::Id, - value: TokenValue::Id(value), - .. - }) = self.current - else { - unreachable!() - }; + kind: TokenKind::Id, + value: TokenValue::Id(value), + .. + }) = self.current + else { + unreachable!() + }; self.step(); self.node(NodeKind::Id(value), pos) } @@ -292,13 +292,13 @@ impl<'a> Parser<'a> { fn parse_int(&mut self) -> Node { let pos = self.pos().unwrap(); let Some(Token { - kind: TokenKind::Int, - value: TokenValue::Int(value), - .. - }) = self.current - else { - unreachable!() - }; + kind: TokenKind::Int, + value: TokenValue::Int(value), + .. + }) = self.current + else { + unreachable!() + }; self.step(); self.node(NodeKind::Int(value), pos) } @@ -306,13 +306,13 @@ impl<'a> Parser<'a> { fn parse_string(&mut self) -> Node { let pos = self.pos().unwrap(); let Some(Token { - kind: TokenKind::Str, - value: TokenValue::Str(value), - .. - }) = self.current.clone() - else { - unreachable!() - }; + kind: TokenKind::Str, + value: TokenValue::Str(value), + .. + }) = self.current.clone() + else { + unreachable!() + }; self.step(); self.node(NodeKind::Str(value.clone()), pos) }