From 5e2f365f453f523927b258f8485486491891fb24 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 21 Jan 2024 01:34:40 -0600 Subject: [PATCH] conlang: deprecate the AST --- libconlang/src/ast.rs | 49 ++- libconlang/src/parser.rs | 3 +- libconlang/src/pretty_printer.rs | 3 +- libconlang/src/resolver.rs | 666 ++++++++++++++++--------------- 4 files changed, 390 insertions(+), 331 deletions(-) diff --git a/libconlang/src/ast.rs b/libconlang/src/ast.rs index 7605cd1..24614b5 100644 --- a/libconlang/src/ast.rs +++ b/libconlang/src/ast.rs @@ -7,7 +7,7 @@ //! [`Identifier`]` := `[`IDENTIFIER`](crate::token::token_type::Type::Identifier) //! //! See [statement], [literal], and [expression] for more information. - +#![deprecated] pub mod preamble { #![allow(deprecated)] //! Common imports for working with the [ast](super) @@ -123,12 +123,30 @@ pub mod statement { /// # Syntax /// [`Fn`](Stmt::Fn) := `"fn"` [`Identifier`] `'('` `Args...` `')'` [`Block`] Fn(FnDecl), + /// Contains a module declaration + /// # Syntax + /// [`Mod`](Stmt::Mod) := `"mod"` [`Identifier`] `'{'` + /// + /// `'}'` /// Contains an expression statement /// # Syntax /// [`Expr`](Stmt::Expr) := [`Expr`] `;` Expr(Expr), } + /// Contains the declarations allowed in a module + /// + /// # Syntax + /// [Mod](Module::Mod) := "mod" [Identifier] '{' [Module] '}' + /// [`Let`](Module::Let) := `"let"` [`Identifier`] (`:` `Type`)? (`=` [`Expr`])? `;` + #[derive(Clone, Debug)] + pub enum Module { + Struct(StructDecl), + Mod(ModuleDecl), + Let(Let), + Fn(FnDecl), + } + /// Contains a variable declaration /// # Syntax /// [`Let`] := `let` [`Identifier`] (`:`) `Type`)? (`=` [`Expr`])? `;` @@ -160,7 +178,22 @@ pub mod statement { pub ty: Option, } + /// Contains the name and declaration + #[derive(Clone, Debug)] + pub struct ModuleDecl {} + // TODO: Create closure, transmute fndecl into a name and closure + /// Contains the name and field information for a struct + /// + /// # Syntax + /// [`StructDecl`]` := "struct" `[`Identifier`]` '{' + /// (`[`Identifier`]` ':' `[`TypeExpr`]`),* + /// '}'` + #[derive(Clone, Debug)] + pub struct StructDecl { + pub name: Identifier, + pub data: Vec<(Identifier, TypeExpr)>, + } } pub mod path { @@ -324,6 +357,10 @@ pub mod expression { pub callee: Box, pub args: Vec, } + #[allow(non_snake_case)] + pub fn FnCall(callee: Box, args: Vec) -> FnCall { + FnCall { callee, args } + } } pub mod tuple { @@ -762,6 +799,16 @@ pub mod todo { //! traits, modules, etc. } + pub mod module { + //! Module support + //! - [ ] Add Module Declaration type : ModDecl = "mod" Identifier '{' Module '}' ; + //! - [ ] Change Program to Module : Module = (ModDecl | FnDecl | Let)* + //! - [ ] Implementer's note: Modules must be traversed breadth-first, with no + //! alpha-renaming + //! - [ ] Blocks should probably also be traversed breadth-first, and Let declarations + //! hoisted up, leaving initialization assignments in-place + } + pub mod structure { //! Struct support //! - [ ] Add struct declaration expression (returns a struct declaration) diff --git a/libconlang/src/parser.rs b/libconlang/src/parser.rs index c55df07..31cb880 100644 --- a/libconlang/src/parser.rs +++ b/libconlang/src/parser.rs @@ -1,5 +1,6 @@ //! Parses [tokens](super::token) into an [AST](super::ast) - +#![deprecated] +#![allow(deprecated)] use super::{ast::preamble::*, lexer::Lexer, token::preamble::*}; use error::{Error, *}; diff --git a/libconlang/src/pretty_printer.rs b/libconlang/src/pretty_printer.rs index 24620d7..e977e55 100644 --- a/libconlang/src/pretty_printer.rs +++ b/libconlang/src/pretty_printer.rs @@ -1,5 +1,6 @@ //! A [Printer] pretty-prints a Conlang [syntax tree](crate::ast) - +#![deprecated] +#![allow(deprecated)] use super::ast::preamble::*; use std::{ fmt::Display, diff --git a/libconlang/src/resolver.rs b/libconlang/src/resolver.rs index a179360..2e09ef8 100644 --- a/libconlang/src/resolver.rs +++ b/libconlang/src/resolver.rs @@ -3,8 +3,6 @@ //! This will hopefully become a fully fledged static resolution pass in the future use std::collections::HashMap; -use crate::ast::preamble::*; - use scopeguard::Scoped; pub mod scopeguard { //! Implements a generic RAII scope-guard @@ -488,362 +486,374 @@ pub trait Resolve { Ok(Type::Empty) } } - -impl Resolve for Start { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Self(program) = self; - program.resolve(resolver) - } -} -impl Resolve for Program { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Self(module) = self; - for decl in module { - decl.resolve(resolver)?; - } - // TODO: record the number of module-level assignments into the AST - Ok(Type::Empty) - } -} -impl Resolve for Stmt { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - match self { - Stmt::Let(value) => value.resolve(resolver), - Stmt::Fn(value) => value.resolve(resolver), - Stmt::Expr(value) => value.resolve(resolver), +mod ast1 { + #![allow(deprecated)] + use super::*; + use crate::ast::preamble::*; + impl Resolve for Start { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Self(program) = self; + program.resolve(resolver) } } -} -impl Resolve for Let { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Let { name: Name { symbol: Identifier { name, index }, mutable, ty: _ }, init } = self; - debugln!("ty> let {name} ..."); - if let Some(init) = init { - let ty = init.resolve(resolver)?; - *index = Some(resolver.insert_scope(name, *mutable)?); - resolver.get_mut(name)?.assign(name, &ty)?; - } else { - resolver.insert_scope(name, *mutable)?; - } - Ok(Type::Empty) - } -} -impl Resolve for FnDecl { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let FnDecl { name: Name { symbol: Identifier { name, index }, .. }, args, body } = self; - debugln!("ty> fn {name} ..."); - // register the name at module scope - *index = Some(resolver.insert_module(name, false)?); - // create a new lexical scope - let scopes = std::mem::take(&mut resolver.scopes); - // type-check the function body - let out = { - let mut resolver = resolver.frame(); - let mut evaluated_args = vec![]; - for arg in args { - evaluated_args.push(arg.resolve(&mut resolver)?) + impl Resolve for Program { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Self(module) = self; + for decl in module { + decl.resolve(resolver)?; } - let fn_decl = Type::Fn { args: evaluated_args.clone(), ret: Box::new(Type::Empty) }; - resolver.get_mut(name)?.assign(name, &fn_decl)?; - module!(resolver, name, { body.resolve(&mut resolver) }) - }; - let _ = std::mem::replace(&mut resolver.scopes, scopes); - out - } -} -impl Resolve for Name { - fn resolve(&mut self, _resolver: &mut Resolver) -> TyResult { - Ok(Type::Empty) - } -} -impl Resolve for Block { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Block { let_count: _, statements, expr } = self; - let mut resolver = resolver.frame(); - for stmt in statements { - stmt.resolve(&mut resolver)?; + // TODO: record the number of module-level assignments into the AST + Ok(Type::Empty) } - expr.resolve(&mut resolver) } -} -impl Resolve for Expr { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Expr(expr) = self; - expr.resolve(resolver) + impl Resolve for Stmt { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + match self { + Stmt::Let(value) => value.resolve(resolver), + Stmt::Fn(value) => value.resolve(resolver), + Stmt::Expr(value) => value.resolve(resolver), + } + } + } + impl Resolve for Let { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Let { name: Name { symbol: Identifier { name, index }, mutable, ty: _ }, init } = + self; + debugln!("ty> let {name} ..."); + if let Some(init) = init { + let ty = init.resolve(resolver)?; + *index = Some(resolver.insert_scope(name, *mutable)?); + resolver.get_mut(name)?.assign(name, &ty)?; + } else { + resolver.insert_scope(name, *mutable)?; + } + Ok(Type::Empty) + } + } + impl Resolve for FnDecl { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let FnDecl { name: Name { symbol: Identifier { name, index }, .. }, args, body } = self; + debugln!("ty> fn {name} ..."); + // register the name at module scope + *index = Some(resolver.insert_module(name, false)?); + // create a new lexical scope + let scopes = std::mem::take(&mut resolver.scopes); + // type-check the function body + let out = { + let mut resolver = resolver.frame(); + let mut evaluated_args = vec![]; + for arg in args { + evaluated_args.push(arg.resolve(&mut resolver)?) + } + let fn_decl = Type::Fn { args: evaluated_args.clone(), ret: Box::new(Type::Empty) }; + resolver.get_mut(name)?.assign(name, &fn_decl)?; + module!(resolver, name, { body.resolve(&mut resolver) }) + }; + let _ = std::mem::replace(&mut resolver.scopes, scopes); + out + } + } + impl Resolve for Name { + fn resolve(&mut self, _resolver: &mut Resolver) -> TyResult { + Ok(Type::Empty) + } + } + impl Resolve for Block { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Block { let_count: _, statements, expr } = self; + let mut resolver = resolver.frame(); + for stmt in statements { + stmt.resolve(&mut resolver)?; + } + expr.resolve(&mut resolver) + } + } + impl Resolve for Expr { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Expr(expr) = self; + expr.resolve(resolver) + } } -} -impl Resolve for Operation { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - match self { - Operation::Assign(value) => value.resolve(resolver), - Operation::Binary(value) => value.resolve(resolver), - Operation::Unary(value) => value.resolve(resolver), - Operation::Call(value) => value.resolve(resolver), + impl Resolve for Operation { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + match self { + Operation::Assign(value) => value.resolve(resolver), + Operation::Binary(value) => value.resolve(resolver), + Operation::Unary(value) => value.resolve(resolver), + Operation::Call(value) => value.resolve(resolver), + } } } -} -impl Resolve for Assign { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Assign { target, operator, init } = self; - // Evaluate the initializer expression - let ty = init.resolve(resolver)?; - // Resolve the variable - match (operator, resolver.get_mut(&target.name)?) { - ( - operator::Assign::Assign, - Variable { status: Status::Initialized(_), mutable: false, index }, - ) => Err(Error::ImmutableAssign(target.name.clone(), *index)), - // TODO: make typing more expressive for modifying assignment - (_, variable) => variable - .modify_assign(&target.name, &ty) - .map(|_| Type::Empty), + impl Resolve for Assign { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Assign { target, operator, init } = self; + // Evaluate the initializer expression + let ty = init.resolve(resolver)?; + // Resolve the variable + match (operator, resolver.get_mut(&target.name)?) { + ( + operator::Assign::Assign, + Variable { status: Status::Initialized(_), mutable: false, index }, + ) => Err(Error::ImmutableAssign(target.name.clone(), *index)), + // TODO: make typing more expressive for modifying assignment + (_, variable) => variable + .modify_assign(&target.name, &ty) + .map(|_| Type::Empty), + } } } -} -impl Resolve for Binary { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Binary { first, other } = self; + impl Resolve for Binary { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Binary { first, other } = self; - let mut first = first.resolve(resolver)?; - for (op, other) in other { - let other = other.resolve(resolver)?; - first = resolver.resolve_binary_operator(first, other, op)?; - } - Ok(first) - } -} -impl Resolve for Unary { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Unary { operators, operand } = self; - let mut operand = operand.resolve(resolver)?; - for op in operators { - operand = resolver.resolve_unary_operator(operand, op)?; - } - Ok(operand) - } -} -/// Resolve [operator]s -impl Resolver { - fn resolve_binary_operator( - &mut self, - first: Type, - other: Type, - op: &operator::Binary, - ) -> TyResult { - // TODO: check type compatibility for binary ops - // TODO: desugar binary ops into function calls, when member functions are a thing - eprintln!("Resolve binary operators {first} {op:?} {other}"); - if first != other { - Err(Error::TypeMismatch { want: first, got: other }) - } else { + let mut first = first.resolve(resolver)?; + for (op, other) in other { + let other = other.resolve(resolver)?; + first = resolver.resolve_binary_operator(first, other, op)?; + } Ok(first) } } - fn resolve_unary_operator(&mut self, operand: Type, op: &operator::Unary) -> TyResult { - // TODO: Allow more expressive unary operator type conversions - todo!("Resolve unary operators {op:?} {operand}") - } -} -impl Resolve for Call { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - match self { - Call::FnCall(value) => value.resolve(resolver), - Call::Primary(value) => value.resolve(resolver), + impl Resolve for Unary { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Unary { operators, operand } = self; + let mut operand = operand.resolve(resolver)?; + for op in operators { + operand = resolver.resolve_unary_operator(operand, op)?; + } + Ok(operand) } } -} -impl Resolve for FnCall { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let FnCall { callee, args } = self; - let mut callee = callee.resolve(resolver)?; - for argset in args { - // arguments should always be a tuple here - let arguments = argset.resolve(resolver)?; - let Type::Tuple(arguments) = arguments else { - Err(Error::TypeMismatch { - want: Type::Tuple(vec![Type::ManyInferred]), - got: arguments, - })? - }; - // Verify that the callee is a function, and the arguments match. - // We need the arguments - let Type::Fn { args, ret } = callee else { - return Err(Error::TypeMismatch { - want: Type::Fn { args: arguments, ret: Type::Inferred.into() }, - got: callee, - })?; - }; - for (want, got) in args.iter().zip(&arguments) { - // TODO: verify generics - if let Type::Generic(_) = want { - continue; - } - if want != got { + /// Resolve [operator]s + impl Resolver { + fn resolve_binary_operator( + &mut self, + first: Type, + other: Type, + op: &operator::Binary, + ) -> TyResult { + // TODO: check type compatibility for binary ops + // TODO: desugar binary ops into function calls, when member functions are a thing + eprintln!("Resolve binary operators {first} {op:?} {other}"); + if first != other { + Err(Error::TypeMismatch { want: first, got: other }) + } else { + Ok(first) + } + } + fn resolve_unary_operator( + &mut self, + operand: Type, + op: &operator::Unary, + ) -> TyResult { + // TODO: Allow more expressive unary operator type conversions + todo!("Resolve unary operators {op:?} {operand}") + } + } + impl Resolve for Call { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + match self { + Call::FnCall(value) => value.resolve(resolver), + Call::Primary(value) => value.resolve(resolver), + } + } + } + impl Resolve for FnCall { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let FnCall { callee, args } = self; + let mut callee = callee.resolve(resolver)?; + for argset in args { + // arguments should always be a tuple here + let arguments = argset.resolve(resolver)?; + let Type::Tuple(arguments) = arguments else { + Err(Error::TypeMismatch { + want: Type::Tuple(vec![Type::ManyInferred]), + got: arguments, + })? + }; + // Verify that the callee is a function, and the arguments match. + // We need the arguments + let Type::Fn { args, ret } = callee else { return Err(Error::TypeMismatch { want: Type::Fn { args: arguments, ret: Type::Inferred.into() }, - got: Type::Fn { args, ret }, + got: callee, })?; + }; + for (want, got) in args.iter().zip(&arguments) { + // TODO: verify generics + if let Type::Generic(_) = want { + continue; + } + if want != got { + return Err(Error::TypeMismatch { + want: Type::Fn { args: arguments, ret: Type::Inferred.into() }, + got: Type::Fn { args, ret }, + })?; + } } + callee = *ret; } - callee = *ret; + Ok(callee) } - Ok(callee) } -} -impl Resolve for Primary { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - match self { - Primary::Identifier(value) => value.resolve(resolver), - Primary::Literal(value) => value.resolve(resolver), - Primary::Block(value) => value.resolve(resolver), - Primary::Group(value) => value.resolve(resolver), - Primary::Branch(value) => value.resolve(resolver), + impl Resolve for Primary { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + match self { + Primary::Identifier(value) => value.resolve(resolver), + Primary::Literal(value) => value.resolve(resolver), + Primary::Block(value) => value.resolve(resolver), + Primary::Group(value) => value.resolve(resolver), + Primary::Branch(value) => value.resolve(resolver), + } + } + } + + impl Resolve for Group { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + match self { + Group::Tuple(tuple) => tuple.resolve(resolver), + Group::Single(expr) => expr.resolve(resolver), + Group::Empty => Ok(Type::Empty), + } + } + } + + impl Resolve for Tuple { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Tuple { elements } = self; + let mut types = vec![]; + for expr in elements.iter_mut() { + types.push(expr.resolve(resolver)?); + } + Ok(Type::Tuple(types)) + } + } + + impl Resolve for Identifier { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Identifier { name, index: id_index } = self; + let Variable { index, status, .. } = resolver.get(name)?; + *id_index = Some(*index); + let ty = match status { + Status::Initialized(t) => t, + _ => Err(Error::Uninitialized(name.to_owned(), *index))?, + }; + debugln!("ty> Resolved {} #{index}: {ty}", name); + Ok(ty.to_owned()) + } + } + impl Resolve for Literal { + fn resolve(&mut self, _resolver: &mut Resolver) -> TyResult { + Ok(match self { + Literal::String(_) => Type::String, + Literal::Char(_) => Type::Char, + Literal::Bool(_) => Type::Bool, + Literal::Float(_) => Type::Float, + Literal::Int(_) => Type::Int, + }) + } + } + + impl Resolve for Flow { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + // TODO: Finish this + match self { + Flow::While(value) => value.resolve(resolver), + Flow::If(value) => value.resolve(resolver), + Flow::For(value) => value.resolve(resolver), + Flow::Continue(value) => value.resolve(resolver), + Flow::Return(value) => value.resolve(resolver), + Flow::Break(value) => value.resolve(resolver), + } + } + } + impl Resolve for While { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + // TODO: Finish this + // Visit else first, save that to a break-pattern stack in the Resolver, + // and check it inside Break::resolve() + let While { cond, body, else_ } = self; + cond.resolve(resolver)?; // must be Type::Bool + body.resolve(resolver)?; // discard + else_.resolve(resolver) // compare with returns inside body + } + } + impl Resolve for If { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let If { cond, body, else_ } = self; + let cond = cond.resolve(resolver)?; + if Type::Bool != cond { + return Err(Error::TypeMismatch { want: Type::Bool, got: cond }); + } + let body_ty = body.resolve(resolver)?; + let else_ty = else_.resolve(resolver)?; + if body_ty == else_ty { + Ok(body_ty) + } else { + Err(Error::TypeMismatch { want: body_ty, got: else_ty }) + } + } + } + + impl Resolve for For { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let For { var: Identifier { name, index }, iter, body, else_ } = self; + debugln!("> for {name} in ..."); + // Visit the iter expression and get its type + let range = iter.resolve(resolver)?; + let ty = match range { + Type::Range(t) => t, + got => Err(Error::TypeMismatch { want: Type::Range(Type::Inferred.into()), got })?, + }; + let body_ty = { + let mut resolver = resolver.frame(); + // bind the variable in the loop scope + *index = Some(resolver.insert_scope(name, false)?); + resolver.get_mut(name)?.assign(name, &ty)?; + body.resolve(&mut resolver) + }?; + // visit the else block + let else_ty = else_.resolve(resolver)?; + if body_ty != else_ty { + Err(Error::TypeMismatch { want: body_ty, got: else_ty }) + } else { + Ok(body_ty) + } + } + } + impl Resolve for Else { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + let Else { expr } = self; + expr.resolve(resolver) + } + } + + impl Resolve for Continue { + fn resolve(&mut self, _resolver: &mut Resolver) -> TyResult { + // TODO: Finish control flow + Ok(Type::Never) + } + } + impl Resolve for Break { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + // TODO: Finish control flow + let Break { expr } = self; + expr.resolve(resolver) + } + } + impl Resolve for Return { + fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { + // TODO: Finish control flow + let Return { expr } = self; + expr.resolve(resolver) } } } -impl Resolve for Group { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - match self { - Group::Tuple(tuple) => tuple.resolve(resolver), - Group::Single(expr) => expr.resolve(resolver), - Group::Empty => Ok(Type::Empty), - } - } -} +mod ast2 {} -impl Resolve for Tuple { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Tuple { elements } = self; - let mut types = vec![]; - for expr in elements.iter_mut() { - types.push(expr.resolve(resolver)?); - } - Ok(Type::Tuple(types)) - } -} - -impl Resolve for Identifier { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Identifier { name, index: id_index } = self; - let Variable { index, status, .. } = resolver.get(name)?; - *id_index = Some(*index); - let ty = match status { - Status::Initialized(t) => t, - _ => Err(Error::Uninitialized(name.to_owned(), *index))?, - }; - debugln!("ty> Resolved {} #{index}: {ty}", name); - Ok(ty.to_owned()) - } -} -impl Resolve for Literal { - fn resolve(&mut self, _resolver: &mut Resolver) -> TyResult { - Ok(match self { - Literal::String(_) => Type::String, - Literal::Char(_) => Type::Char, - Literal::Bool(_) => Type::Bool, - Literal::Float(_) => Type::Float, - Literal::Int(_) => Type::Int, - }) - } -} - -impl Resolve for Flow { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - // TODO: Finish this - match self { - Flow::While(value) => value.resolve(resolver), - Flow::If(value) => value.resolve(resolver), - Flow::For(value) => value.resolve(resolver), - Flow::Continue(value) => value.resolve(resolver), - Flow::Return(value) => value.resolve(resolver), - Flow::Break(value) => value.resolve(resolver), - } - } -} -impl Resolve for While { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - // TODO: Finish this - // Visit else first, save that to a break-pattern stack in the Resolver, - // and check it inside Break::resolve() - let While { cond, body, else_ } = self; - cond.resolve(resolver)?; // must be Type::Bool - body.resolve(resolver)?; // discard - else_.resolve(resolver) // compare with returns inside body - } -} -impl Resolve for If { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let If { cond, body, else_ } = self; - let cond = cond.resolve(resolver)?; - if Type::Bool != cond { - return Err(Error::TypeMismatch { want: Type::Bool, got: cond }); - } - let body_ty = body.resolve(resolver)?; - let else_ty = else_.resolve(resolver)?; - if body_ty == else_ty { - Ok(body_ty) - } else { - Err(Error::TypeMismatch { want: body_ty, got: else_ty }) - } - } -} - -impl Resolve for For { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let For { var: Identifier { name, index }, iter, body, else_ } = self; - debugln!("> for {name} in ..."); - // Visit the iter expression and get its type - let range = iter.resolve(resolver)?; - let ty = match range { - Type::Range(t) => t, - got => Err(Error::TypeMismatch { want: Type::Range(Type::Inferred.into()), got })?, - }; - let body_ty = { - let mut resolver = resolver.frame(); - // bind the variable in the loop scope - *index = Some(resolver.insert_scope(name, false)?); - resolver.get_mut(name)?.assign(name, &ty)?; - body.resolve(&mut resolver) - }?; - // visit the else block - let else_ty = else_.resolve(resolver)?; - if body_ty != else_ty { - Err(Error::TypeMismatch { want: body_ty, got: else_ty }) - } else { - Ok(body_ty) - } - } -} -impl Resolve for Else { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - let Else { expr } = self; - expr.resolve(resolver) - } -} - -impl Resolve for Continue { - fn resolve(&mut self, _resolver: &mut Resolver) -> TyResult { - // TODO: Finish control flow - Ok(Type::Never) - } -} -impl Resolve for Break { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - // TODO: Finish control flow - let Break { expr } = self; - expr.resolve(resolver) - } -} -impl Resolve for Return { - fn resolve(&mut self, resolver: &mut Resolver) -> TyResult { - // TODO: Finish control flow - let Return { expr } = self; - expr.resolve(resolver) - } -} // heakc yea man, generics impl Resolve for Option { fn resolve(&mut self, resolver: &mut Resolver) -> TyResult {