@@ -12,30 +12,25 @@
1212-- This module provides basic inlining capabilities
1313--
1414-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE CPP #-}
17−
18−module Language.PureScript.CodeGen.Cpp.Optimizer.Inliner (
19− inlineVariables,
20− inlineValues,
21− inlineOperator,
22− inlineCommonOperators,
23− inlineFnComposition,
24− etaConvert,
25− unThunk,
26− evaluateIifes
27−) where
15+module Language.PureScript.CodeGen.Cpp.Optimizer.Inliner
16+ ( inlineVariables
17+ , inlineCommonValues
18+ , inlineOperator
19+ , inlineCommonOperators
20+ , inlineFnComposition
21+ , etaConvert
22+ , unThunk
23+ , evaluateIifes
24+ ) where
2825
2926import Prelude.Compat
3027
31−#if __GLASGOW_HASKELL__ < 710
32−import Control.Applicative (Applicative)
33−#endif
3428import Control.Monad.Supply.Class (MonadSupply, freshName)
35−import Language.PureScript.CodeGen.Cpp.Types
29+
3630import Language.PureScript.CodeGen.Cpp.AST
3731import Language.PureScript.CodeGen.Cpp.Common
3832import Language.PureScript.CodeGen.Cpp.Optimizer.Common
33+import Language.PureScript.CodeGen.Cpp.Types
3934import Language.PureScript.Names
4035import qualified Language.PureScript.Constants as C
4136
@@ -101,36 +96,30 @@ inlineVariables = everywhereOnCpp $ removeFromBlock go
10196 go (map (replaceIdent var cpp) sts)
10297 go (s:sts) = s : go sts
10398
104−inlineValues :: Cpp -> Cpp
105−inlineValues = everywhereOnCpp convert
99+inlineCommonValues :: Cpp -> Cpp
100+inlineCommonValues = everywhereOnCpp convert
106101 where
107102 convert :: Cpp -> Cpp
108− convert (CppApp fn [dict]) | isDict semiringNumber dict && isFn fnZero fn = CppNumericLiteral (Left 0)
109− | isDict semiringNumber dict && isFn fnOne fn = CppNumericLiteral (Left 1)
110− | isDict semiringInt dict && isFn fnZero fn = CppNumericLiteral (Left 0)
111− | isDict semiringInt dict && isFn fnOne fn = CppNumericLiteral (Left 1)
112− | isDict boundedBoolean dict && isFn fnBottom fn = CppBooleanLiteral False
113− | isDict boundedBoolean dict && isFn fnTop fn = CppBooleanLiteral True
114− convert (CppApp fn [dict, x, y])
115− | isDict semiringInt dict && isFn fnAdd fn = CppBinary Add x y
116− | isDict semiringInt dict && isFn fnMultiply fn = CppBinary Multiply x y
117− | isDict moduloSemiringInt dict && isFn fnDivide fn = CppBinary Divide x y
118− | isDict ringInt dict && isFn fnSubtract fn = CppBinary Subtract x y
103+ convert (CppApp fn [dict])
104+ | isDict' [semiringNumber, semiringInt] dict && isFn fnZero fn = CppNumericLiteral (Left 0)
105+ | isDict' [semiringNumber, semiringInt] dict && isFn fnOne fn = CppNumericLiteral (Left 1)
106+ | isDict boundedBoolean dict && isFn fnBottom fn = CppBooleanLiteral False
107+ | isDict boundedBoolean dict && isFn fnTop fn = CppBooleanLiteral True
119108 convert (CppApp (CppApp (CppApp fn [dict]) [x]) [y])
120− | isDict semiringInt dict && isFn fnAdd fn = CppBinary Add x y
121− | isDict semiringInt dict && isFn fnMultiply fn = CppBinary Multiply x y
122− | isDict moduloSemiringInt dict && isFn fnDivide fn = CppBinary Divide x y
123− | isDict ringInt dict && isFn fnSubtract fn = CppBinary Subtract x y
124−
109+ | isDict semiringInt dict && isFn fnAdd fn = intOp Add x y
110+ | isDict semiringInt dict && isFn fnMultiply fn = intOp Multiply x y
111+ | isDict euclideanRingInt dict && isFn fnDivide fn = intOp Divide x y
112+ | isDict ringInt dict && isFn fnSubtract fn = intOp Subtract x y
125113 convert other = other
126− fnZero = (C.prelude, C.zero)
127− fnOne = (C.prelude, C.one)
128− fnBottom = (C.prelude, C.bottom)
129− fnTop = (C.prelude, C.top)
130− fnAdd = (C.prelude, (C.+))
131− fnDivide = (C.prelude, (C./))
132− fnMultiply = (C.prelude, (C.*))
133− fnSubtract = (C.prelude, (C.-))
114+ fnZero = (C.dataSemiring, C.zero)
115+ fnOne = (C.dataSemiring, C.one)
116+ fnBottom = (C.dataBounded, C.bottom)
117+ fnTop = (C.dataBounded, C.top)
118+ fnAdd = (C.dataSemiring, C.add)
119+ fnDivide = (C.dataEuclideanRing, C.div)
120+ fnMultiply = (C.dataSemiring, C.mul)
121+ fnSubtract = (C.dataRing, C.sub)
122+ intOp op x y = CppBinary BitwiseOr (CppBinary op x y) (CppNumericLiteral (Left 0))
134123
135124inlineOperator :: (String, String) -> (Cpp -> Cpp -> Cpp) -> Cpp -> Cpp
136125inlineOperator (m, op) f = everywhereOnCpp convert
@@ -139,49 +128,60 @@ inlineOperator (m, op) f = everywhereOnCpp convert
139128 convert (CppApp op' [x, y]) | isOp op' = f x y
140129 convert (CppApp (CppApp op' [x]) [y]) | isOp op' = f x y
141130 convert other = other
142− isOp (CppAccessor (CppVar longForm) (CppVar m')) = m == m' && longForm == identToCpp (Op op)
131+ isOp (CppAccessor (CppVar longForm) (CppVar m')) = m == m' && longForm == identToCpp (Ident op)
143132 isOp (CppIndexer (CppStringLiteral op') (CppVar m')) = m == m' && op == op'
144133 isOp _ = False
145134
146135inlineCommonOperators :: Cpp -> Cpp
147136inlineCommonOperators = applyAll $
148− [ binary semiringNumber (C.+) Add
149− , binary semiringNumber (C.*) Multiply
150−
151− , binary ringNumber (C.-) Subtract
152− , unary ringNumber C.negate CppNegate
153− , binary ringInt (C.-) Subtract
154− , unary ringInt C.negate CppNegate
155−
156− , binary moduloSemiringNumber (C./) Divide
157− , binary moduloSemiringInt C.mod Modulus
158−
159− , binary eqNumber (C.==) Equal
160− , binary eqNumber (C./=) NotEqual
161− , binary eqInt (C.==) Equal
162− , binary eqInt (C./=) NotEqual
163− , binary eqString (C.==) Equal
164− , binary eqString (C./=) NotEqual
165− , binary eqBoolean (C.==) Equal
166− , binary eqBoolean (C./=) NotEqual
167−
168− , binary ordNumber (C.<) LessThan
169− , binary ordNumber (C.>) GreaterThan
170− , binary ordNumber (C.<=) LessThanOrEqual
171− , binary ordNumber (C.>=) GreaterThanOrEqual
172− , binary ordInt (C.<) LessThan
173− , binary ordInt (C.>) GreaterThan
174− , binary ordInt (C.<=) LessThanOrEqual
175− , binary ordInt (C.>=) GreaterThanOrEqual
176−
177− , binary semigroupString (C.<>) Add
178− , binary semigroupString (C.++) Add
179−
180− , binary booleanAlgebraBoolean (C.&&) And
181− , binary booleanAlgebraBoolean (C.||) Or
182− , binaryFunction booleanAlgebraBoolean C.conj And
183− , binaryFunction booleanAlgebraBoolean C.disj Or
184− , unary booleanAlgebraBoolean C.not CppNot
137+ [ binary semiringNumber opAdd Add
138+ , binary semiringNumber opMul Multiply
139+
140+ , binary ringNumber opSub Subtract
141+ , unary ringNumber opNegate Negate
142+ , binary ringInt opSub Subtract
143+ , unary ringInt opNegate Negate
144+
145+ , binary euclideanRingNumber opDiv Divide
146+ , binary euclideanRingInt opMod Modulus
147+
148+ , binary eqNumber opEq EqualTo
149+ , binary eqNumber opNotEq NotEqualTo
150+ , binary eqInt opEq EqualTo
151+ , binary eqInt opNotEq NotEqualTo
152+ , binary eqString opEq EqualTo
153+ , binary eqString opNotEq NotEqualTo
154+ , binary eqChar opEq EqualTo
155+ , binary eqChar opNotEq NotEqualTo
156+ , binary eqBoolean opEq EqualTo
157+ , binary eqBoolean opNotEq NotEqualTo
158+
159+ , binary ordBoolean opLessThan LessThan
160+ , binary ordBoolean opLessThanOrEq LessThanOrEqualTo
161+ , binary ordBoolean opGreaterThan GreaterThan
162+ , binary ordBoolean opGreaterThanOrEq GreaterThanOrEqualTo
163+ , binary ordChar opLessThan LessThan
164+ , binary ordChar opLessThanOrEq LessThanOrEqualTo
165+ , binary ordChar opGreaterThan GreaterThan
166+ , binary ordChar opGreaterThanOrEq GreaterThanOrEqualTo
167+ , binary ordInt opLessThan LessThan
168+ , binary ordInt opLessThanOrEq LessThanOrEqualTo
169+ , binary ordInt opGreaterThan GreaterThan
170+ , binary ordInt opGreaterThanOrEq GreaterThanOrEqualTo
171+ , binary ordNumber opLessThan LessThan
172+ , binary ordNumber opLessThanOrEq LessThanOrEqualTo
173+ , binary ordNumber opGreaterThan GreaterThan
174+ , binary ordNumber opGreaterThanOrEq GreaterThanOrEqualTo
175+ , binary ordString opLessThan LessThan
176+ , binary ordString opLessThanOrEq LessThanOrEqualTo
177+ , binary ordString opGreaterThan GreaterThan
178+ , binary ordString opGreaterThanOrEq GreaterThanOrEqualTo
179+
180+ , binary semigroupString opAppend Add
181+
182+ , binary heytingAlgebraBoolean opConj And
183+ , binary heytingAlgebraBoolean opDisj Or
184+ , unary heytingAlgebraBoolean opNot Not
185185
186186 , binary' C.dataIntBits (C..|.) BitwiseOr
187187 , binary' C.dataIntBits (C..&.) BitwiseAnd
@@ -189,43 +189,30 @@ inlineCommonOperators = applyAll $
189189 , binary' C.dataIntBits C.shl ShiftLeft
190190 , binary' C.dataIntBits C.shr ShiftRight
191191 -- , binary' C.dataIntBits C.zshr ZeroFillShiftRight
192− , unary' C.dataIntBits C.complement CppBitwiseNot
193− ] -- ++ -- DISABLE mkFn/runFn inlining
192+ , unary' C.dataIntBits C.complement BitwiseNot
193+ ] ++
194+ []
194195 -- [ fn | i <- [0..10], fn <- [ mkFn i, runFn i ] ]
195196 where
196− binary :: (String, String) -> String -> BinaryOp -> Cpp -> Cpp
197− binary dict opString op = everywhereOnCpp convert
197+ binary :: (String, String) -> (String, String) -> BinaryOperator -> Cpp -> Cpp
198+ binary dict fns op = everywhereOnCpp convert
198199 where
199200 convert :: Cpp -> Cpp
200− convert (CppApp fn [dict', CppStringLiteral x, CppStringLiteral y])
201− | isDict dict dict' && isPreludeFn opString fn = CppStringLiteral (x ++ y)
202− convert (CppApp fn [dict', x, y]) | isDict dict dict' && isPreludeFn opString fn = CppBinary op x y
203− convert (CppApp (CppApp (CppApp fn [dict']) [CppStringLiteral x]) [CppStringLiteral y])
204− | isDict dict dict' && isPreludeFn opString fn = CppStringLiteral (x ++ y)
205− convert (CppApp (CppApp (CppApp fn [dict']) [x]) [y]) | isDict dict dict' && isPreludeFn opString fn = CppBinary op x y
201+ convert (CppApp (CppApp (CppApp fn [dict']) [x]) [y]) | isDict dict dict' && isFn fns fn = CppBinary op x y
206202 convert other = other
207− binary' :: String -> String -> BinaryOp -> Cpp -> Cpp
203+ binary' :: String -> String -> BinaryOperator -> Cpp -> Cpp
208204 binary' moduleName opString op = everywhereOnCpp convert
209205 where
210206 convert :: Cpp -> Cpp
211− convert (CppApp fn [x, y]) | isFn (moduleName, opString) fn = CppBinary op x y
212207 convert (CppApp (CppApp fn [x]) [y]) | isFn (moduleName, opString) fn = CppBinary op x y
213208 convert other = other
214− binaryFunction :: (String, String) -> String -> BinaryOp -> Cpp -> Cpp
215− binaryFunction dict fnName op = everywhereOnCpp convert
216− where
217− convert :: Cpp -> Cpp
218− convert (CppApp fn [dict', x, y]) | isPreludeFn fnName fn && isDict dict dict' = CppBinary op x y
219− convert (CppApp (CppApp (CppApp fn [dict']) [x]) [y]) | isPreludeFn fnName fn && isDict dict dict' = CppBinary op x y
220− convert other = other
221− unary :: (String, String) -> String -> CppUnaryOp -> Cpp -> Cpp
222− unary dict fnName op = everywhereOnCpp convert
209+ unary :: (String, String) -> (String, String) -> UnaryOperator -> Cpp -> Cpp
210+ unary dicts fns op = everywhereOnCpp convert
223211 where
224212 convert :: Cpp -> Cpp
225− convert (CppApp fn [dict', x]) | isPreludeFn fnName fn && isDict dict dict' = CppUnary op x
226− convert (CppApp (CppApp fn [dict']) [x]) | isPreludeFn fnName fn && isDict dict dict' = CppUnary op x
213+ convert (CppApp (CppApp fn [dict']) [x]) | isDict dicts dict' && isFn fns fn = CppUnary op x
227214 convert other = other
228− unary' :: String -> String -> CppUnaryOp -> Cpp -> Cpp
215+ unary' :: String -> String -> UnaryOperator -> Cpp -> Cpp
229216 unary' moduleName fnName op = everywhereOnCpp convert
230217 where
231218 convert :: Cpp -> Cpp
@@ -235,8 +222,8 @@ inlineCommonOperators = applyAll $
235222 -- mkFn 0 = everywhereOnCpp convert
236223 -- where
237224 -- convert :: Cpp -> Cpp
238− -- convert (CppApp mkFnN [CppLambda caps [_] _ (CppBlock cpp)]) | isNFn C.mkFn 0 mkFnN =
239− -- CppLambda caps [] Nothing (CppBlock cpp)
225+ -- convert (CppApp mkFnN [CppLambda _ [_] _ (CppBlock cpp)]) | isNFn C.mkFn 0 mkFnN =
226+ -- CppLambda [CppCaptureAll] [] Nothing (CppBlock cpp)
240227 -- convert other = other
241228 -- mkFn n = everywhereOnCpp convert
242229 -- where
@@ -246,14 +233,14 @@ inlineCommonOperators = applyAll $
246233 -- Just (args, cpp) -> CppLambda [CppCaptureAll] args Nothing (CppBlock cpp)
247234 -- Nothing -> orig
248235 -- convert other = other
249− -- collectArgs :: Int -> [(String, Maybe CppType)] -> Cpp -> Maybe ([(String, Maybe CppType)], [Cpp])
236+ -- collectArgs :: Int -> [String] -> Cpp -> Maybe ([String], [Cpp])
250237 -- collectArgs 1 acc (CppLambda _ [oneArg] _ (CppBlock cpp)) | length acc == n - 1 = Just (reverse (oneArg : acc), cpp)
251238 -- collectArgs m acc (CppLambda _ [oneArg] _ (CppBlock [CppReturn ret])) = collectArgs (m - 1) (oneArg : acc) ret
252239 -- collectArgs _ _ _ = Nothing
253240 --
254241 -- isNFn :: String -> Int -> Cpp -> Bool
255242 -- isNFn prefix n (CppVar name) = name == (prefix ++ show n)
256− -- isNFn prefix n (CppAccessor (CppVar name) (CppVar dataFunction)) | dataFunction == C.dataFunction = name == (prefix ++ show n)
243+ -- isNFn prefix n (CppAccessor _ name (CppVar dataFunction)) | dataFunction == C.dataFunction = name == (prefix ++ show n)
257244 -- isNFn _ _ _ = False
258245 --
259246 -- runFn :: Int -> Cpp -> Cpp
@@ -269,78 +256,134 @@ inlineCommonOperators = applyAll $
269256
270257-- (f <<< g $ x) = f (g x)
271258-- (f <<< g) = \x -> f (g x)
272−inlineFnComposition :: (Applicative m, MonadSupply m) => Cpp -> m Cpp
259+inlineFnComposition :: (MonadSupply m) => Cpp -> m Cpp
273260inlineFnComposition = everywhereOnCppTopDownM convert
274261 where
275262 convert :: (MonadSupply m) => Cpp -> m Cpp
276− convert (CppApp fn [dict', x, y]) | isFnCompose dict' fn = do
277− arg <- freshName
278− return $ CppLambda [CppCaptureAll] [(arg, Just (CppAny [CppConst, CppRef]))] (Just $ CppAny []) (CppBlock [CppReturn $ CppApp x [CppApp y [CppVar arg]]])
279− convert (CppApp (CppApp (CppApp (CppApp fn [dict']) [x]) [y]) [z]) | isFnCompose dict' fn =
280− return $ CppApp x [CppApp y [z]]
281− convert (CppApp (CppApp (CppApp fn [dict']) [x]) [y]) | isFnCompose dict' fn = do
282− arg <- freshName
283− return $ CppLambda [CppCaptureAll] [(arg, Just (CppAny [CppConst, CppRef]))] (Just $ CppAny []) (CppBlock [CppReturn $ CppApp x [CppApp y [CppVar arg]]])
263+ convert (CppApp (CppApp (CppApp (CppApp fn [dict']) [x]) [y]) [z])
264+ | isFnCompose dict' fn = return $ CppApp x [CppApp y [z]]
265+ | isFnComposeFlipped dict' fn = return $ CppApp y [CppApp x [z]]
266+ convert (CppApp (CppApp (CppApp fn [dict']) [x]) [y])
267+ | isFnCompose dict' fn = do
268+ arg <- freshName
269+ return $ CppLambda [CppCaptureAll] [(arg, constAnyRef)] Nothing (CppBlock [CppReturn $ CppApp x [CppApp y [CppVar arg]]])
270+ | isFnComposeFlipped dict' fn = do
271+ arg <- freshName
272+ return $ CppLambda [CppCaptureAll] [(arg, constAnyRef)] Nothing (CppBlock [CppReturn $ CppApp y [CppApp x [CppVar arg]]])
284273 convert other = return other
285274 isFnCompose :: Cpp -> Cpp -> Bool
286− isFnCompose dict' fn = isDict semigroupoidFn dict' && (isPreludeFn (C.<<<) fn || isPreludeFn (C.compose) fn)
287−
288−isDict :: (String, String) -> Cpp -> Bool
289−isDict (moduleName, dictName) (CppAccessor (CppVar x) (CppVar y)) = x == dictName && y == moduleName
290−isDict _ _ = False
291−
292−isFn :: (String, String) -> Cpp -> Bool
293−isFn (moduleName, fnName) (CppAccessor (CppVar x) (CppVar y)) = x == (identToCpp (Ident fnName)) && y == moduleName
294−isFn (moduleName, fnName) (CppIndexer (CppStringLiteral x) (CppVar y)) = x == fnName && y == moduleName
295−isFn _ _ = False
296−
297−isPreludeFn :: String -> Cpp -> Bool
298−isPreludeFn fnName = isFn (C.prelude, fnName)
275+ isFnCompose dict' fn = isDict semigroupoidFn dict' && isFn fnCompose fn
276+ isFnComposeFlipped :: Cpp -> Cpp -> Bool
277+ isFnComposeFlipped dict' fn = isDict semigroupoidFn dict' && isFn fnComposeFlipped fn
278+ fnCompose :: (String, String)
279+ fnCompose = (C.controlSemigroupoid, C.compose)
280+ fnComposeFlipped :: (String, String)
281+ fnComposeFlipped = (C.controlSemigroupoid, C.composeFlipped)
299282
300283semiringNumber :: (String, String)
301−semiringNumber = (C.prelude, C.semiringNumber)
284+semiringNumber = (C.dataSemiring, C.semiringNumber)
302285
303286semiringInt :: (String, String)
304−semiringInt = (C.prelude, C.semiringInt)
287+semiringInt = (C.dataSemiring, C.semiringInt)
305288
306289ringNumber :: (String, String)
307−ringNumber = (C.prelude, C.ringNumber)
290+ringNumber = (C.dataRing, C.ringNumber)
308291
309292ringInt :: (String, String)
310−ringInt = (C.prelude, C.ringInt)
293+ringInt = (C.dataRing, C.ringInt)
311294
312−moduloSemiringNumber :: (String, String)
313−moduloSemiringNumber = (C.prelude, C.moduloSemiringNumber)
295+euclideanRingNumber :: (String, String)
296+euclideanRingNumber = (C.dataEuclideanRing, C.euclideanRingNumber)
314297
315−moduloSemiringInt :: (String, String)
316−moduloSemiringInt = (C.prelude, C.moduloSemiringInt)
298+euclideanRingInt :: (String, String)
299+euclideanRingInt = (C.dataEuclideanRing, C.euclideanRingInt)
317300
318301eqNumber :: (String, String)
319−eqNumber = (C.prelude, C.eqNumber)
302+eqNumber = (C.dataEq, C.eqNumber)
320303
321304eqInt :: (String, String)
322−eqInt = (C.prelude, C.eqInt)
305+eqInt = (C.dataEq, C.eqInt)
323306
324307eqString :: (String, String)
325−eqString = (C.prelude, C.eqNumber)
308+eqString = (C.dataEq, C.eqString)
309+
310+eqChar :: (String, String)
311+eqChar = (C.dataEq, C.eqChar)
326312
327313eqBoolean :: (String, String)
328−eqBoolean = (C.prelude, C.eqNumber)
314+eqBoolean = (C.dataEq, C.eqBoolean)
315+
316+ordBoolean :: (String, String)
317+ordBoolean = (C.dataOrd, C.ordBoolean)
329318
330319ordNumber :: (String, String)
331−ordNumber = (C.prelude, C.ordNumber)
320+ordNumber = (C.dataOrd, C.ordNumber)
332321
333322ordInt :: (String, String)
334−ordInt = (C.prelude, C.ordInt)
323+ordInt = (C.dataOrd, C.ordInt)
324+
325+ordString :: (String, String)
326+ordString = (C.dataOrd, C.ordString)
327+
328+ordChar :: (String, String)
329+ordChar = (C.dataOrd, C.ordChar)
335330
336331semigroupString :: (String, String)
337−semigroupString = (C.prelude, C.semigroupString)
332+semigroupString = (C.dataSemigroup, C.semigroupString)
338333
339334boundedBoolean :: (String, String)
340−boundedBoolean = (C.prelude, C.boundedBoolean)
335+boundedBoolean = (C.dataBounded, C.boundedBoolean)
341336
342−booleanAlgebraBoolean :: (String, String)
343−booleanAlgebraBoolean = (C.prelude, C.booleanAlgebraBoolean)
337+heytingAlgebraBoolean :: (String, String)
338+heytingAlgebraBoolean = (C.dataHeytingAlgebra, C.heytingAlgebraBoolean)
344339
345340semigroupoidFn :: (String, String)
346−semigroupoidFn = (C.prelude, C.semigroupoidFn)
341+semigroupoidFn = (C.controlSemigroupoid, C.semigroupoidFn)
342+
343+opAdd :: (String, String)
344+opAdd = (C.dataSemiring, C.add)
345+
346+opMul :: (String, String)
347+opMul = (C.dataSemiring, C.mul)
348+
349+opEq :: (String, String)
350+opEq = (C.dataEq, C.eq)
351+
352+opNotEq :: (String, String)
353+opNotEq = (C.dataEq, C.notEq)
354+
355+opLessThan :: (String, String)
356+opLessThan = (C.dataOrd, C.lessThan)
357+
358+opLessThanOrEq :: (String, String)
359+opLessThanOrEq = (C.dataOrd, C.lessThanOrEq)
360+
361+opGreaterThan :: (String, String)
362+opGreaterThan = (C.dataOrd, C.greaterThan)
363+
364+opGreaterThanOrEq :: (String, String)
365+opGreaterThanOrEq = (C.dataOrd, C.greaterThanOrEq)
366+
367+opAppend :: (String, String)
368+opAppend = (C.dataSemigroup, C.append)
369+
370+opSub :: (String, String)
371+opSub = (C.dataRing, C.sub)
372+
373+opNegate :: (String, String)
374+opNegate = (C.dataRing, C.negate)
375+
376+opDiv :: (String, String)
377+opDiv = (C.dataEuclideanRing, C.div)
378+
379+opMod :: (String, String)
380+opMod = (C.dataEuclideanRing, C.mod)
381+
382+opConj :: (String, String)
383+opConj = (C.dataHeytingAlgebra, C.conj)
384+
385+opDisj :: (String, String)
386+opDisj = (C.dataHeytingAlgebra, C.disj)
387+
388+opNot :: (String, String)
389+opNot = (C.dataHeytingAlgebra, C.not)