packages feed

zwirn-0.2.2.0: src/zwirn-lang/Zwirn/Language/Simple.hs

{-# LANGUAGE OverloadedStrings #-}

module Zwirn.Language.Simple
  ( simplify,
    simplifyLoc,
    SimpleTerm (..),
    SimpleDef (..),
    LocSimpleTerm,
  )
where

{-
    Simple.hs - desugaring of the zwirn AST
    Copyright (C) 2023, Martin Gius

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
-}

import Data.Text as Text (Text, filter, pack)
import Zwirn.Language.Location
import Zwirn.Language.Syntax

type LocSimpleTerm = Located SimpleTerm

-- simple representation of patterns
data SimpleTerm
  = SVar !Var
  | SText !Text
  | SNum !Text
  | SRest
  | SSeq [LocSimpleTerm]
  | SStack [LocSimpleTerm]
  | SChoice Int [LocSimpleTerm]
  | SLambda Var LocSimpleTerm
  | SApp LocSimpleTerm LocSimpleTerm
  | SInfix LocSimpleTerm LocVar LocSimpleTerm
  | SBracket LocSimpleTerm
  deriving (Eq, Show)

data SimpleDef
  = LetS !Var LocSimpleTerm
  deriving (Eq, Show)

simplifyLoc :: LocTerm -> LocSimpleTerm
simplifyLoc (Located p t) = Located p (simplify t)

simplify :: Term -> SimpleTerm
simplify (TVar x) = SVar x
simplify (TText x) = SText $ stripText x
  where
    stripText = Text.filter (/= '\"')
simplify (TNum x) = SNum x
simplify TRest = SRest
simplify x@(TRepeat _ _) = SSeq $ map (fmap simplify) $ resolveRepeat (Located NoLoc x)
simplify (TSeq ts) = SSeq (map (fmap simplify) $ concatMap resolveRepeat ts)
simplify (TStack ts) = SStack (map (fmap simplify) ts)
simplify (TChoice i ts) = SChoice i (map (fmap simplify) ts)
simplify (TAlt ts) = SBracket $ noLoc $ SInfix (noLoc $ SSeq ss) (noLoc "(/)") (noLoc $ SNum (pack $ show $ length ss))
  where
    ss = map (fmap simplify) $ concatMap resolveRepeat ts
simplify (TPoly (Located _ (TSeq ts)) n) = SBracket $ noLoc $ SInfix (noLoc $ SInfix (noLoc $ SSeq ss) (noLoc "(/)") (noLoc $ SNum (pack $ show $ length ss))) (noLoc "(*)") (fmap simplify n)
  where
    ss = map (fmap simplify) $ concatMap resolveRepeat ts
simplify (TPoly x n) = SInfix (fmap simplify x) (noLoc "(*)") (fmap simplify n)
simplify (TLambda [] t) = simplify (lValue t)
simplify (TLambda (x : xs) t) = SLambda x (noLoc $ simplify $ TLambda xs t)
simplify (TIfThenElse x y (Just z)) = SApp (noLoc $ SApp (noLoc $ SApp (noLoc $ SVar "ifthen") (fmap simplify x)) (fmap simplify y)) (fmap simplify z)
simplify (TIfThenElse x y Nothing) = SApp (noLoc $ SApp (noLoc $ SVar "if") (fmap simplify x)) (fmap simplify y)
simplify (TApp x y) = SApp (fmap simplify x) (fmap simplify y)
simplify (TInfix x op y) = SInfix (fmap simplify x) op (fmap simplify y)
simplify (TSectionR op y) = SLambda "_x" (noLoc $ SInfix (noLoc $ SVar "_x") op (fmap simplify y))
simplify (TSectionL x op) = SLambda "_x" (noLoc $ SInfix (fmap simplify x) op (noLoc $ SVar "_x"))
simplify (TBracket x) = SBracket (fmap simplify x)
simplify (TEnum Run x y) = SApp (noLoc $ SApp (noLoc $ SVar "runFromTo") (fmap simplify x)) (fmap simplify y)
simplify (TEnumThen Run x y z) = SApp (noLoc $ SApp (noLoc $ SApp (noLoc $ SVar "runFromThenTo") (fmap simplify x)) (fmap simplify y)) (fmap simplify z)
simplify (TEnum Alt x y) = SApp (noLoc $ SApp (noLoc $ SVar "slowrunFromTo") (fmap simplify x)) (fmap simplify y)
simplify (TEnumThen Alt x y z) = SApp (noLoc $ SApp (noLoc $ SApp (noLoc $ SVar "slowrunFromThenTo") (fmap simplify x)) (fmap simplify y)) (fmap simplify z)
simplify (TEnum Cord x y) = SApp (noLoc $ SApp (noLoc $ SVar "cordFromTo") (fmap simplify x)) (fmap simplify y)
simplify (TEnumThen Cord x y z) = SApp (noLoc $ SApp (noLoc $ SApp (noLoc $ SVar "cordFromThenTo") (fmap simplify x)) (fmap simplify y)) (fmap simplify z)
simplify (TEnum Choice x y) = SApp (noLoc $ SApp (noLoc $ SVar "chooseFromTo") (fmap simplify x)) (fmap simplify y)
simplify (TEnumThen Choice x y z) = SApp (noLoc $ SApp (noLoc $ SApp (noLoc $ SVar "chooseFromThenTo") (fmap simplify x)) (fmap simplify y)) (fmap simplify z)
simplify _ = error "Found unsubstituted macro while desugaring!"

resolveRepeat :: LocTerm -> [LocTerm]
resolveRepeat t = case getTotalRepeat t of
  Located _ (TRepeat x (Just i)) -> replicate i x
  Located _ (TRepeat x Nothing) -> [x, x]
  x -> [x]

-- TODO : not completely right when Nothing followed by Just...
getRepeat :: (LocTerm, Int) -> LocTerm
getRepeat (Located _ (TRepeat x (Just j)), k) = getRepeat (x, j * k)
getRepeat (Located _ (TRepeat x Nothing), k) = getRepeat (x, k + 1)
getRepeat (x, j) = noLoc $ TRepeat x (Just j)

getTotalRepeat :: LocTerm -> LocTerm
getTotalRepeat (Located _ (TRepeat t (Just i))) = getRepeat (t, i)
getTotalRepeat (Located _ (TRepeat t Nothing)) = getRepeat (t, 2)
getTotalRepeat t = t