Files
gyehoek-hs/app/Gyehoek/Scheme/Syntax.hs
T
2026-05-18 10:08:03 -06:00

118 lines
2.8 KiB
Haskell

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PartialTypeSignatures #-}
module Gyehoek.Scheme.Syntax where
import Data.Text (Text)
import Data.List (List)
import Language.SexpGrammar as Sexp hiding (List)
import Language.SexpGrammar.Generic
import GHC.Generics
import Prelude hiding ((.), id)
import Control.Category
import Data.List.NonEmpty (NonEmpty ((:|)))
import Gyehoek.Sexp qualified
import Control.Lens (Each)
type Name = Text
data Prim e
= PrimAdd e e
| PrimSub e e
| PrimMul e e
| PrimDiv e e
| PrimCons e e
| PrimCar e
| PrimCdr e
| PrimImmediateP e
| PrimConsP e
| PrimIntegerP e
| PrimWrite e
deriving (Show, Generic, Functor, Foldable, Traversable)
instance Each (Prim e) (Prim e') e e'
data Lit
= LitInt Int
| LitNil
| LitBool Bool
| LitString Text
deriving (Show, Generic)
data Define
= DefineConstant Name Exp
| DefineProcedure Name (List Name) (List Exp)
deriving (Show, Generic)
data Exp
= ExpLet (NonEmpty (Name, Exp)) Exp
| ExpPrim (Prim Exp)
| ExpBegin (List Exp)
| ExpDefine Define
| ExpIf Exp Exp Exp
| ExpLit Lit
| ExpApply Exp (List Exp)
| ExpLambda (List Name) Exp
| ExpVar Name
deriving (Show, Generic)
instance SexpIso a => SexpIso (Prim a) where
sexpIso = match
$ With (. binop "+")
$ With (. binop "-")
$ With (. binop "*")
$ With (. binop "/")
$ With (. binop "cons")
$ With (. unop "car")
$ With (. unop "cdr")
$ With (. unop "immediate?")
$ With (. unop "cons?")
$ With (. unop "integer?")
$ With (. unop "write")
$ End
where
primname = ("prim:" <>)
unop s = list $ el (sym (primname s)) >>> el sexpIso
binop s = list $ el (sym (primname s)) >>> el sexpIso >>> el sexpIso
instance SexpIso Lit where
sexpIso = match
$ With (. sexpIso)
$ With (. sym "nil")
$ With (. sexpIso)
$ With (. sexpIso)
$ End
instance SexpIso Define where
sexpIso = match
$ With (. defconst)
$ With (. defun)
$ End
where
defconst = list $ el (sym "define") >>> el symbol >>> el sexpIso
defun = list $ el (sym "define") >>> el args >>> rest sexpIso
args = list $ el symbol >>> rest symbol
instance SexpIso Exp where
sexpIso = match
$ With (. Gyehoek.Sexp.let_ symbol sexpIso sexpIso)
$ With (. sexpIso)
$ With (\bgn -> bgn . list (el (sym "begin") >>> rest sexpIso))
$ With (. sexpIso)
$ With (. if_)
$ With (. sexpIso)
$ With (\app -> app . list (el sexpIso >>> rest sexpIso))
$ With (. lam)
$ With (. symbol)
$ End
where
if_ = list $ el (sym "if") >>> el sexpIso >>> el sexpIso >>> el sexpIso
lam = list
( el (sym "lambda")
>>> el (sexpIso @(List Name))
>>> el sexpIso )