knave 0.9.5

A small Lisp for humans and agents that infers types and ownership and compiles to readable Rust
Documentation
use std::rc::Rc;

use super::ty::Type;
use super::typed::{
    Borrow, TypedArgument, TypedBinder, TypedBlock, TypedBodyItem, TypedExpr, TypedExprKind,
    TypedLambda, TypedLeaf, WrappedFunction,
};
use crate::core::{BindingArena, BindingId, BindingInfo, BindingKind};
use crate::source::Span;

pub struct FunctionValueWrapper<'a> {
    bindings: &'a mut BindingArena,
}

impl<'a> FunctionValueWrapper<'a> {
    pub fn new(bindings: &'a mut BindingArena) -> Self {
        Self { bindings }
    }

    pub fn prepare(
        &mut self,
        expected_parameters: &[Type],
        value: TypedExpr,
        function: BindingId,
    ) -> PreparedFunctionValue {
        let span = value.span;
        let wraps = WrappedFunction {
            binding: function,
            ty: value.ty.clone(),
        };
        let mut params = Vec::new();
        let mut arguments = Vec::new();
        for expected in expected_parameters {
            let binding = self.bindings.add(BindingInfo::new(
                "argument".into(),
                BindingKind::Local,
                None,
            ));
            let local = TypedExpr {
                kind: TypedExprKind::Leaf(TypedLeaf::Local(binding)),
                ty: expected.clone(),
                span,
            };
            params.push(TypedBinder {
                binding,
                ty: expected.clone(),
                span,
                annotated: false,
            });
            arguments.push(TypedArgument {
                value: local,
                borrow: Borrow::None,
            });
        }
        PreparedFunctionValue {
            params,
            arguments,
            value,
            span,
            wraps,
        }
    }
}

pub struct PreparedFunctionValue {
    pub params: Vec<TypedBinder>,
    pub arguments: Vec<TypedArgument>,
    value: TypedExpr,
    span: Span,
    wraps: WrappedFunction,
}

impl PreparedFunctionValue {
    pub fn span(&self) -> Span {
        self.span
    }

    pub fn finish(self, expected_result: &Type, found_result: &Type) -> TypedExpr {
        let parameters: Vec<Type> = self.params.iter().map(|param| param.ty.clone()).collect();
        let call = TypedExpr {
            kind: TypedExprKind::Call(Box::new(self.value), self.arguments),
            ty: found_result.clone(),
            span: self.span,
        };
        let lambda = TypedLambda {
            params: self.params,
            body: TypedBlock {
                items: vec![TypedBodyItem::Expr(call)],
            },
            wraps: Some(self.wraps),
            kind: crate::types::ClosureKind::Fn,
            moved_capture: None,
            changed_capture: None,
        };
        TypedExpr {
            kind: TypedExprKind::Fn(Rc::new(lambda)),
            ty: Type::Function(
                crate::types::ClosureKind::Fn,
                parameters,
                Box::new(expected_result.clone()),
            ),
            span: self.span,
        }
    }
}