;;;; lambda-calculus.lisp --- Untyped lambda calculus based on pattern specializers. ;;;; ;;;; Copyright (C) 2014 Jan Moringen ;;;; ;;;; Author: Jan Moringen ;;;; Partially based on idea from ;;;; ;;;; [1] Benjamin C. Pierce (2002): Types and Programming languages (cl:defpackage #:pattern-specializer.examples.lambda-calculus (:use #:cl #:pattern-specializer)) (cl:in-package #:pattern-specializer.examples.lambda-calculus) ;;; Syntax (defstruct term) (defstruct (value (:include term) (:constructor make-value (value))) (value nil)) ; TODO val? (defstruct (var (:include term) (:constructor make-var (name))) (name nil :type symbol)) (defstruct (abst (:include value) (:constructor make-abst (var body))) (var nil :type var) (body nil :type term)) (defstruct (app (:include term) (:constructor make-app (func arg))) (func nil :type term) (arg nil :type term)) ;;; Parse (defgeneric parse (from) (:generic-function-class pattern-generic-function)) (defmethod parse ((form (pattern (optima:guard value (integerp value))))) ; TODO just (form integer) (make-value value)) (defmethod parse ((form (pattern (optima:guard name (symbolp name))))) ; TODO just (form symbol) (make-var form)) (defmethod parse ((form (pattern (list 'λ (optima:guard name (symbolp name)) body)))) (make-abst (parse name) (parse body))) (defmethod parse ((form (pattern (list func arg)))) (make-app (parse func) (parse arg))) ;;; Substitution (defgeneric substitute1 (term var val)) (defmethod substitute1 ((term value) (var var) (val value)) term) ;; [1 Page 69] (defmethod substitute1 ((term var) (var var) (val value)) (if (equalp term var) val term)) ;; [1 Page 69] (defmethod substitute1 ((term abst) (var var) (val value)) ;; TODO capture (make-abst (abst-var term) (substitute1 (abst-body term) var val))) ;; [1 Page 69] (defmethod substitute1 ((term app) (var var) (val value)) (make-app (substitute1 (app-func term) var val) (substitute1 (app-arg term) var val))) ;;; Evaluation (defgeneric eval1 (term) (:generic-function-class pattern-generic-function)) (defmethod eval1 ((term (pattern (value)))) ; TODO does not need pattern term) ;; Reduce function to value ;; ;; t_1 -> t_1' ;; --------------------- ;; t_1 t_2 -> t_1' t_2 ;; ;; [1 Page 72; Figure 5.3] (defmethod eval1 ((term (pattern (app func arg)))) (eval1 (make-app (eval1 func) arg))) ;; Reduce argument to value ;; ;; t_2 -> t_2' ;; --------------------- ;; v_1 t_2 -> v_1 t_2' ;; ;; [1 Page 72; Figure 5.3] (defmethod eval1 ((term (pattern (app (func (and func (value))) arg)))) (eval1 (make-app func (eval1 arg)))) ;; Application ;; ;; (λx.t_12) v_2 -> [x -> v_2] t_12 ;; ;; [1 Page 72; Figure 5.3] (defmethod eval1 ((term (pattern (app (func (abst var body)) (arg (and arg (value))))))) (let ((arg-value (eval1 arg))) (eval1 (substitute1 body var arg-value)))) ;;; Test (eval1 (make-value 1)) (eval1 (make-abst (make-var 'x) (make-value 1))) (eval1 (make-app (make-abst (make-var 'x) (make-var 'x)) (make-value 1))) ;; => S#(VALUE) (eval1 (parse '(((λ z (λ y z)) 5) 6)))