JustusAdam/language-haskell

Limited by the number of highlighted functions?

m-rph opened this issue · 5 comments

m-rph commented

Hi, thanks for the great work!
I am having an issue where, in some files with many small functions highlighting just stops working.

sheaf commented

Hi there, thanks for the bug report.

Could you give an example which causes problems? Hard to know what's the problem might be otherwise, as I haven't run this behaviour I don't think.

m-rph commented

I don't really have a minimal example, but this is a file that causes said issue. But you can't really compile it because it is missing the rest of the definitions...

Paradoxically, highlighting also stops working in Github.

module ExtendedOperators where
import Control.Monad ( (>=>) )
import BoaAST
    ( Op(..), Value(FalseVal, IntVal, ListVal, StringVal, TrueVal) )
import Utils ( showOperatorSign, showValueConstrName )

alwaysSuccess :: (t1 -> t2 -> b) -> (t1, t2) -> Either a b
alwaysSuccess op (a, b) = Right $ op a b

-- Commutative Operators
addE :: (Int, Int) -> Either a Value
addE = alwaysSuccess (+) >=> Right . IntVal

subE :: (Int, Int) -> Either a Value
subE = alwaysSuccess (-) >=> Right . IntVal

mulE :: (Int, Int) -> Either a Value
mulE = alwaysSuccess (*) >=> Right . IntVal

divE :: (Int, Int) -> Either String Value
divE (a,0) = Left "Division by 0"
divE (a,b) = Right . IntVal $ a `div` b 

modE :: (Int, Int) -> Either String Value
modE (a,0) = Left "Modulo 0"
modE (a,b) = Right . IntVal $ a `mod` b

eqE :: Eq a1 => (a1, a1) -> Either String Value
eqE = alwaysSuccess (==) >=> Right . boolToBoolVal

ltE :: Ord a => (a, a) -> Either String Value
ltE = alwaysSuccess (<) >=> Right . boolToBoolVal

gtE :: Ord a => (a, a) -> Either String Value
gtE = alwaysSuccess (>) >=> Right . boolToBoolVal

strAddE :: (String, String) -> Either String Value
strAddE = alwaysSuccess (++) >=> Right . StringVal

listAddE :: ([Value], [Value]) -> Either String Value
listAddE = alwaysSuccess (++) >=> Right . ListVal

-- Taken from user1812457 at https://stackoverflow.com/questions/30588221
substring :: String -> String -> Bool
substring (_:_) [] = False
substring xs ys
    | prefix xs ys = True
    | substring xs (tail ys) = True
    | otherwise = False

prefix :: String -> String -> Bool
prefix [] _ = True
prefix (_:_) [] = False
prefix (x:xs) (y:ys) = (x == y) && prefix xs ys

evaluateToIIOperator :: Op -> [(Int, Int) -> Either String Value]
evaluateToIIOperator Plus = [addE]
evaluateToIIOperator Minus = [subE]
evaluateToIIOperator Times = [mulE]
evaluateToIIOperator Div = [divE]
evaluateToIIOperator Mod = [modE]
evaluateToIIOperator Less = [ltE]
evaluateToIIOperator Greater = [gtE]
evaluateToIIOperator _ = []

evaluateOrdLLOperator :: Op -> [([Value], [Value]) -> Either String Value]
evaluateOrdLLOperator operator = let
  reduction :: Either String Value -> Either String Value -> Either String Value
  reduction accumulated current = accumulated >>= (\f -> 
      let in case (f, current) of 
        (TrueVal, cr) -> cr -- True && a = a
        (_, err@(Left _)) -> err 
        (_, _) -> Right FalseVal
    )
  a = \(a,b)-> let 
    individualElements = zipWith (operate operator) a b
    in foldl reduction (Right TrueVal) individualElements
  in [a]

evaluateToLLOperator :: Op -> [([Value], [Value]) -> Either String Value]
evaluateToLLOperator Plus = [\(a, b) -> Right . ListVal $ a ++ b]
evaluateToLLOperator Less = evaluateOrdLLOperator Less
evaluateToLLOperator Greater = evaluateOrdLLOperator Greater
evaluateToLLOperator _ = []

evaluateToALOperator :: Op -> [(Value, [Value]) ->Either String Value]
evaluateToALOperator In = [\(v,l) -> Right . boolToBoolVal $ v`elem`l]
evaluateToALOperator _ = []

evaluateToILOperator :: (Num t, Enum t) => Op -> [(t, [Value]) -> Either a Value]
evaluateToILOperator Times = [\(a, b) -> Right . ListVal $ [v| _ <- [1..a], v<-b]]
evaluateToILOperator _ = []

evaluateToSSOperator :: Op -> [(String, String) -> Either String Value]
evaluateToSSOperator Plus = [strAddE]
evaluateToSSOperator Less = [ltE]
evaluateToSSOperator Greater = [gtE]
evaluateToSSOperator In = [\(left,right) -> Right . boolToBoolVal $ substring left right]
evaluateToSSOperator _ = []

evaluateToSIOperator :: Op -> [(Int,String) -> Either String Value]
evaluateToSIOperator Times = [\(a,b) -> Right . StringVal $ [c|i<-[0..a], c<-b]]
evaluateToSIOperator _ = []

evaluateToEqOperator :: Eq a1 => Op -> [(a1, a1) -> Either String Value]
evaluateToEqOperator Eq = [eqE]
evaluateToEqOperator _ = []

evaluateToInt :: Value -> [Int]
evaluateToInt TrueVal = [1]
evaluateToInt FalseVal = [0]
evaluateToInt (IntVal v) = [v]
evaluateToInt _ = []

evaluateToList :: Value -> [[Value]]
evaluateToList (ListVal l) = [l]
evaluateToList _ = []

evaluateToString :: Value -> [String]
evaluateToString (StringVal s) = [s]
evaluateToString _ = []

boolToBoolVal :: Bool -> Value
boolToBoolVal True = TrueVal
boolToBoolVal False = FalseVal

applyFtoCartesian :: [a1] -> [b] -> ((a1, b) -> a2) -> [a2]
applyFtoCartesian xs ys f = [f (x, y) | x <- xs, y <- ys]

operate :: Op -> Value -> Value -> Either [Char] Value
operate op x y = 
  case results of
    [] ->
      Left $
        "unsupported operand type(s) for "
          ++ showOperatorSign op
          ++ ": '"
          ++ showValueConstrName x
          ++ "' and '"
          ++ showValueConstrName y
          ++ "'"
    (r : _) -> r
  where
    numXs = [x] >>= evaluateToInt
    numYs = [y] >>= evaluateToInt
    -- num x num operations
    numericResults = [op] >>= evaluateToIIOperator >>= applyFtoCartesian numXs numYs

    listXs = [x] >>= evaluateToList
    listYs = [y] >>= evaluateToList
    -- operations on lists
    listResults = [op] >>= evaluateToLLOperator >>= applyFtoCartesian listXs listYs

    stringXs = [x] >>= evaluateToString
    stringYs = [y] >>= evaluateToString
    -- operations on strings
    stringResults = [op] >>= evaluateToSSOperator >>= applyFtoCartesian stringXs stringYs

    ilOperators = [op] >>= evaluateToILOperator
    -- int list and list int operations, all commutative,
    -- so we check both sides.
    ilResults = ilOperators >>= applyFtoCartesian numXs listYs
    ilResults2 = ilOperators >>= applyFtoCartesian numYs listXs

    siOperators = [op] >>= evaluateToSIOperator
    -- int string / string int operations, all commutative
    -- we trivially check both sides
    strIntResults = siOperators >>= applyFtoCartesian numXs stringYs
    strIntResults2 = siOperators >>= applyFtoCartesian numYs stringXs

    -- equality check
    eqResults = [op] >>= evaluateToEqOperator >>= applyFtoCartesian [x] [y]
    -- x in someList
    alResults = [op] >>= evaluateToALOperator  >>= applyFtoCartesian [x] listYs

    results = numericResults 
      ++ listResults
      ++ stringResults
      ++ ilResults
      ++ ilResults2
      ++ strIntResults
      ++ strIntResults2
      ++ alResults
      ++ eqResults

If I comment out this part:

evaluateToILOperator :: (Num t, Enum t) => Op -> [(t, [Value]) -> Either a Value]
evaluateToILOperator Times = [\(a, b) -> Right . ListVal $ [v| _ <- [1..a], v<-b]]
evaluateToILOperator _ = []

It makes the following two functions to highlight.

sheaf commented

Right, yeah, the problem is that

[v| _ <- [1..a], v<-b]]

is parsed as a quasi-quotation and not as a list comprehension. Unfortunately that's kind of by design as the syntax is inherently ambiguous. So you need to add a space, e.g.

[ v | _ <- [1..a], v<-b]]
m-rph commented

Oh, okay, that makes a lot of sense! Thanks and sorry for the false positive ^^'.
Feel free to close this :)

Ah right ... yeah that makes sense. It is so unfortunate, but the vscode parser implementations don't allow us to recognize language extensions.