Support for nested variable definitions

This commit is contained in:
vegowotenks 2024-09-16 17:30:25 +02:00
parent 3dc3e3b842
commit d3f63b1d15
2 changed files with 40 additions and 20 deletions

View file

@ -1,5 +1,5 @@
module Lib
( exprparser, evaluate, replaceVars, Expr, extractVariableDefinitions
( exprparser, evaluate, replaceVars, Expr, extractVariableDefinitions, updateVariables
) where
import Control.Applicative((<*))
@ -14,7 +14,7 @@ import Text.Parsec.Expr
import Text.Parsec.Token
import Text.Parsec.Language
data Expr = Variable String | Constant Rational | Binary BinaryOperator Expr Expr | VariableDefinition String Rational
data Expr = Variable String | Constant Rational | Binary BinaryOperator Expr Expr | VariableDefinition String Expr
deriving Show
data BinaryOperator = Plus | Minus | Multiply | Divide | Power
deriving Show
@ -80,7 +80,7 @@ variableDefinition :: Parser Expr
variableDefinition = try (do
name <- m_identifier
_ <- char '='
value <- constantInteger <|> constantRational
value <- exprparser
return (VariableDefinition name value)
)
@ -90,16 +90,29 @@ term = m_parens exprparser
<|> fmap Constant constantInteger
<|> fmap Constant constantRational
extractVariableDefinitions :: Expr -> Map.Map String Rational
extractVariableDefinitions (VariableDefinition name value) = Map.singleton name value
extractVariableDefinitions (Binary _ a b) = Map.union (extractVariableDefinitions a) (extractVariableDefinitions b)
extractVariableDefinitions (Constant _) = Map.empty
extractVariableDefinitions (Variable _) = Map.empty
extractVariableDefinitions :: Expr -> [(String,Expr)]
extractVariableDefinitions (VariableDefinition name value) = [(name, value)]
extractVariableDefinitions (Binary _ a b) = extractVariableDefinitions a ++ extractVariableDefinitions b
extractVariableDefinitions (Constant _) = []
extractVariableDefinitions (Variable _) = []
updateVariables :: [(String, Expr)] -> Map String Rational -> Either String (Map String Rational)
updateVariables ds vs = foldl updateVariable (Right vs) ds
updateVariable :: Either String (Map String Rational) -> (String, Expr) -> Either String (Map String Rational)
updateVariable (Left e) _ = Left e
updateVariable (Right vs) (name, e) = case updateVariables nvs vs of
Left e -> Left e
Right uvs -> case replaceVars e uvs of
Left e -> Left e
Right exp -> Right $ Map.insert name (evaluate exp) uvs
where
nvs = extractVariableDefinitions e
replaceVars :: Expr -> Map.Map String Rational -> Either String Expr
replaceVars (Constant c) vs = Right $ Constant c
replaceVars (Variable name) vs = maybe (Left ("Usage of unknown variable: '" ++ name ++ "'\nSuggestion: define the variable\n++ " ++ name ++ "=42")) (Right . Constant . id) $ Map.lookup name vs
replaceVars (VariableDefinition _ value ) vs = Right $ Constant value
replaceVars (VariableDefinition name _) vs = replaceVars (Variable name) vs
replaceVars (Binary op l r) vs = case leftBranch of
Left s -> Left s
Right a -> case rightBranch of
@ -107,7 +120,7 @@ replaceVars (Binary op l r) vs = case leftBranch of
Right b -> Right $ Binary op a b
where
leftBranch = replaceVars l vs
rightBranch = replaceVars r vs
rightBranch = replaceVars r vs
{-
- a/b ^ c/d