packages feed

zwirn-0.1.0.0: src/Zwirn/Language/Simple.hs

{-# LANGUAGE OverloadedStrings #-}

module Zwirn.Language.Simple
  ( simplify,
    simplifyDef,
    SimpleTerm (..),
    SimpleDef (..),
    Position (..),
  )
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.Syntax

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

data SimpleDef
  = LetS Var SimpleTerm
  deriving (Eq, Show)

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

simplifyDef :: Def -> SimpleDef
simplifyDef (Let x vs t) = LetS x (simplify $ TLambda vs t)

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

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

getTotalRepeat :: Term -> Term
getTotalRepeat (TRepeat t (Just i)) = getRepeat (t, i)
getTotalRepeat (TRepeat t Nothing) = getRepeat (t, 2)
getTotalRepeat t = t