hc/app/Main.hs
2024-09-27 00:22:12 +02:00

62 lines
2.6 KiB
Haskell

-- hc - haskell command line calculator using rational numbers
-- Copyright (C) 2024 VegOwOtenks
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Affero General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program 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 Affero General Public License for more details.
--
-- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
--
-- contact me via vegowotenks at jossco dot de
module Main (main) where
import Lib (exprparser, evaluate, replaceVars, Expr, extractVariableDefinitions, updateVariables, parseFullString)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Ratio
import System.IO
initVars :: Map String Rational
initVars = Map.fromList [("pi", 245850922 % 78256779), ("e", 271801 % 99990)]
main :: IO ()
main = ioLoop initVars
precision = 5 :: Int
showRatio :: Int -> Rational -> String
showRatio p r = (if (r < 0) then "-" else "") ++ prepoint_digits ++ (if (length postpoint_digits > 0) then ("." ++ postpoint_digits) else "")
where
prepoint_digits = init . show . round . abs $ (r * 10)
postpoint_digits = reverse . dropWhile (=='0') . reverse .(take p) . (drop (length prepoint_digits)) . show . round . abs $ (r * 10^p)
useResult :: Map String Rational -> Expr -> String
useResult vs expr = either id ((showRatio precision) . evaluate) $ replaceVars expr vs
ioLoop :: Map String Rational -> IO ()
ioLoop vs = do done <- isEOF
if done
then putStrLn "Quit!"
else do inp <- getLine
let expr_res = parseFullString inp
case expr_res of
Left err -> do
putStrLn . show $ err
ioLoop vs
Right expr -> do
let vardefs = extractVariableDefinitions expr
let uvs_res = updateVariables vardefs vs
case uvs_res of
Left err -> putStrLn err
Right uvs -> putStrLn $ useResult uvs expr
ioLoop (either (const vs) (id) uvs_res)