1-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>2--3-- SPDX-License-Identifier: GPL-3.0-only45module Language.QBE6 ( Program,7 Definition (..),8 globalFuncs,9 Language.QBE.parse,10 ExecError (..),11 parseAndFind,12 )13where1415import Control.Monad.Catch (Exception, MonadThrow, throwM)16import Data.List (find)17import Data.Maybe (mapMaybe)18import Language.QBE.Parser (dataDef, funcDef, skipInitComments, typeDef)19import Language.QBE.Types (DataDef, FuncDef, GlobalIdent, TypeDef, fName)20import Text.ParserCombinators.Parsec21 ( ParseError,22 Parser,23 SourceName,24 choice,25 eof,26 many,27 parse,28 )2930data Definition31 = DefData DataDef32 | DefType TypeDef33 | DefFunc FuncDef34 deriving (Eq, Show)3536parseDef :: Parser Definition37parseDef =38 choice39 [ DefType <$> typeDef,40 DefFunc <$> funcDef,41 DefData <$> dataDef42 ]4344type Program = [Definition]4546globalFuncs :: Program -> [FuncDef]47globalFuncs = mapMaybe globalFuncs'48 where49 globalFuncs' :: Definition -> Maybe FuncDef50 globalFuncs' (DefFunc f) = Just f51 globalFuncs' _ = Nothing5253parse :: SourceName -> String -> Either ParseError Program54parse =55 Text.ParserCombinators.Parsec.parse56 (skipInitComments *> many parseDef <* eof)5758------------------------------------------------------------------------5960data ExecError61 = ESyntaxError ParseError62 | EUnknownEntry GlobalIdent63 deriving (Show)6465instance Exception ExecError6667-- | Utility function for the common task of parsing an input as a QBE68-- 'Program' and, within that program, finding the entry function. If the69-- function doesn't exist or a the input is invalid an exception is thrown.70parseAndFind ::71 (MonadThrow m) =>72 GlobalIdent ->73 String ->74 m (Program, FuncDef)75parseAndFind entryIdent input = do76 prog <- case Language.QBE.parse "" input of -- TODO: file name77 Right rt -> pure rt78 Left err -> throwM $ ESyntaxError err7980 let funcs = globalFuncs prog81 func <- case find (\f -> fName f == entryIdent) funcs of82 Just x -> pure x83 Nothing -> throwM $ EUnknownEntry entryIdent8485 pure (prog, func)