From 313c044b4a878a425aaca6554576f5154ace8ff9 Mon Sep 17 00:00:00 2001 From: Joel Kronqvist Date: Wed, 6 Aug 2025 16:23:18 +0300 Subject: Implemented let-bindings --- src/type/check.rs | 39 +++++++++++++++++++-------------------- src/type/display.rs | 7 +++++++ src/type/mod.rs | 2 ++ 3 files changed, 28 insertions(+), 20 deletions(-) (limited to 'src/type') diff --git a/src/type/check.rs b/src/type/check.rs index d0ce807..e536ce7 100644 --- a/src/type/check.rs +++ b/src/type/check.rs @@ -1,6 +1,6 @@ use crate::r#type::{Type, TypeError, Type::*, TypeError::*, util::*}; -use crate::sexp::{SExp, SExp::*, SLeaf::*}; +use crate::sexp::{SExp, SExp::*, SLeaf::*, util::*}; use std::collections::HashMap; impl SExp { @@ -101,23 +101,6 @@ impl SExp { /// ); /// ``` /// - /// As such it must be that the type of the let-binding s-expression is st. - /// ```rust - /// use myslip::{ - /// r#type::{*, Type::*, TypeError::*, util::*}, - /// sexp::{SExp::*, SLeaf::*, util::*}, - /// }; - /// - /// assert_eq!( - /// scons(Let, scons(var("x"), scons(1, Nil))).type_check(), - /// Ok(arr(vt("T"), vt("T"))) - /// ); - /// ``` - /// ie. the identity function. - /// - /// No more behavior on typing let can be defined, as typing the let-keyword - /// would require the yet untyped variable to be typed. - /// /// Though perhaps the most important task of the type system /// is to increase safety by being able to warn about errors /// before evaluation. Here are some failing examples: @@ -184,7 +167,7 @@ impl SExp { } - fn infer_type(&self, ctx: HashMap) -> Result { + fn infer_type(&self, mut ctx: HashMap) -> Result { match self { @@ -210,13 +193,29 @@ impl SExp { vecof(vt("T")), List(vec![VecType, vecof(vt("T"))]) )), - Atom(Let) => todo!(), + Atom(Let) => Ok(LetType), SCons(op, l) => { + + // Let-expressions + if let Some((varname, val)) = (*op).clone().check_let() { + let valtype = val.infer_type(ctx.clone())?; + ctx.insert(varname, valtype); + return match (**l).clone() { + SCons(exp, nil) if *nil == Atom(Nil) => *exp, + t => t + }.infer_type(ctx); + } + if **op == Atom(Let) { + return Err(LetAsOperator(scons(op.clone(), l.clone()))); + } + + // Normal operation let opertype = (*op).infer_type(ctx.clone())?; let argstype = (*l).infer_list_type(ctx)?; + let argstype = if opertype == arr( vecof(vt("T")), List(vec![VecType, vecof(vt("T"))]) diff --git a/src/type/display.rs b/src/type/display.rs index fe54941..4a9b54a 100644 --- a/src/type/display.rs +++ b/src/type/display.rs @@ -103,6 +103,13 @@ impl fmt::Display for TypeError { argtype, generictype ) }, + LetAsOperator(letexp) => { + write!( + f, + "let used as operator instead of generating an operator: maybe try '({} ...)' instead", + letexp + ) + }, OtherError => write!(f, "uncategorized error"), } } diff --git a/src/type/mod.rs b/src/type/mod.rs index 9e0d9ec..afb5a0b 100644 --- a/src/type/mod.rs +++ b/src/type/mod.rs @@ -59,6 +59,8 @@ pub enum TypeError { generictype: Type, }, + LetAsOperator(SExp), + OtherError } -- cgit v1.2.3