diff --git a/src/Juvix/Compiler/Tree/Data/TransformationId.hs b/src/Juvix/Compiler/Tree/Data/TransformationId.hs index afbe62c2e7..93f8c22beb 100644 --- a/src/Juvix/Compiler/Tree/Data/TransformationId.hs +++ b/src/Juvix/Compiler/Tree/Data/TransformationId.hs @@ -12,6 +12,7 @@ data TransformationId | TempHeight | FilterUnreachable | Validate + | CheckNoAnoma deriving stock (Data, Bounded, Enum, Show) data PipelineId @@ -26,7 +27,7 @@ toNockmaTransformations :: [TransformationId] toNockmaTransformations = [Validate, Apply, FilterUnreachable, TempHeight] toAsmTransformations :: [TransformationId] -toAsmTransformations = [Validate] +toAsmTransformations = [Validate, CheckNoAnoma] toCairoAsmTransformations :: [TransformationId] toCairoAsmTransformations = [Validate, Apply, FilterUnreachable] @@ -41,6 +42,7 @@ instance TransformationId' TransformationId where TempHeight -> strTempHeight FilterUnreachable -> strFilterUnreachable Validate -> strValidate + CheckNoAnoma -> strCheckNoAnoma instance PipelineId' TransformationId PipelineId where pipelineText :: PipelineId -> Text diff --git a/src/Juvix/Compiler/Tree/Data/TransformationId/Strings.hs b/src/Juvix/Compiler/Tree/Data/TransformationId/Strings.hs index 1e8aa131ff..ababa4da2f 100644 --- a/src/Juvix/Compiler/Tree/Data/TransformationId/Strings.hs +++ b/src/Juvix/Compiler/Tree/Data/TransformationId/Strings.hs @@ -31,3 +31,6 @@ strFilterUnreachable = "filter-unreachable" strValidate :: Text strValidate = "validate" + +strCheckNoAnoma :: Text +strCheckNoAnoma = "check-no-anoma" diff --git a/src/Juvix/Compiler/Tree/Keywords.hs b/src/Juvix/Compiler/Tree/Keywords.hs index f965bd6aa7..900df036b8 100644 --- a/src/Juvix/Compiler/Tree/Keywords.hs +++ b/src/Juvix/Compiler/Tree/Keywords.hs @@ -9,6 +9,7 @@ import Juvix.Compiler.Tree.Keywords.Base import Juvix.Data.Keyword.All ( kwAdd_, kwAlloc, + kwAnomaGet, kwArgsNum, kwAtoi, kwBr, @@ -68,5 +69,6 @@ allKeywords = kwCCall, kwBr, kwCase, - kwSave + kwSave, + kwAnomaGet ] diff --git a/src/Juvix/Compiler/Tree/Transformation.hs b/src/Juvix/Compiler/Tree/Transformation.hs index 7f58941f89..a1876de891 100644 --- a/src/Juvix/Compiler/Tree/Transformation.hs +++ b/src/Juvix/Compiler/Tree/Transformation.hs @@ -10,6 +10,7 @@ import Juvix.Compiler.Tree.Data.TransformationId import Juvix.Compiler.Tree.Error import Juvix.Compiler.Tree.Transformation.Apply import Juvix.Compiler.Tree.Transformation.Base +import Juvix.Compiler.Tree.Transformation.CheckNoAnoma import Juvix.Compiler.Tree.Transformation.FilterUnreachable import Juvix.Compiler.Tree.Transformation.Identity import Juvix.Compiler.Tree.Transformation.TempHeight @@ -27,3 +28,4 @@ applyTransformations ts tbl = foldM (flip appTrans) tbl ts TempHeight -> return . computeTempHeight FilterUnreachable -> return . filterUnreachable Validate -> mapError (JuvixError @TreeError) . validate + CheckNoAnoma -> \tbl' -> mapError (JuvixError @TreeError) (checkNoAnoma tbl') $> tbl' diff --git a/src/Juvix/Compiler/Tree/Transformation/CheckNoAnoma.hs b/src/Juvix/Compiler/Tree/Transformation/CheckNoAnoma.hs new file mode 100644 index 0000000000..21b6d424c6 --- /dev/null +++ b/src/Juvix/Compiler/Tree/Transformation/CheckNoAnoma.hs @@ -0,0 +1,23 @@ +module Juvix.Compiler.Tree.Transformation.CheckNoAnoma where + +import Juvix.Compiler.Tree.Data.InfoTable +import Juvix.Compiler.Tree.Error +import Juvix.Compiler.Tree.Extra.Recursors +import Juvix.Compiler.Tree.Transformation.Base + +checkNoAnoma :: forall r. (Member (Error TreeError) r) => InfoTable -> Sem r () +checkNoAnoma = walkT checkNode + where + checkNode :: Symbol -> Node -> Sem r () + checkNode _ = \case + Unop NodeUnop {..} -> case _nodeUnopOpcode of + OpAnomaGet -> + throw + TreeError + { _treeErrorMsg = "OpAnomaGet is unsupported", + _treeErrorLoc = _nodeUnopInfo ^. nodeInfoLocation + } + OpFail -> return () + OpTrace -> return () + PrimUnop {} -> return () + _ -> return () diff --git a/src/Juvix/Compiler/Tree/Translation/FromSource.hs b/src/Juvix/Compiler/Tree/Translation/FromSource.hs index ee11a5d802..199e6f57b7 100644 --- a/src/Juvix/Compiler/Tree/Translation/FromSource.hs +++ b/src/Juvix/Compiler/Tree/Translation/FromSource.hs @@ -106,6 +106,7 @@ parseUnop = <|> parseUnaryOp kwTrace OpTrace <|> parseUnaryOp kwFail OpFail <|> parseUnaryOp kwArgsNum (PrimUnop OpArgsNum) + <|> parseUnaryOp kwAnomaGet (OpAnomaGet) parseUnaryOp :: (Members '[Reader ParserSig, InfoTableBuilder, State LocalParams] r) => diff --git a/src/Juvix/Data/Keyword/All.hs b/src/Juvix/Data/Keyword/All.hs index c8df62273a..9e7a7b7fde 100644 --- a/src/Juvix/Data/Keyword/All.hs +++ b/src/Juvix/Data/Keyword/All.hs @@ -433,6 +433,9 @@ kwRet = asciiKw Str.ret kwLive :: Keyword kwLive = asciiKw Str.live +kwAnomaGet :: Keyword +kwAnomaGet = asciiKw Str.anomaGet + delimBraceL :: Keyword delimBraceL = mkDelim Str.braceL diff --git a/test/Compilation/Base.hs b/test/Compilation/Base.hs index 5c673efab1..5cc0270046 100644 --- a/test/Compilation/Base.hs +++ b/test/Compilation/Base.hs @@ -51,6 +51,9 @@ compileErrorAssertion root' mainFile step = do step "Translate to JuvixCore" entryPoint <- testDefaultEntryPointIO root' mainFile PipelineResult {..} <- snd <$> testRunIO entryPoint upToCore - case run $ runReader Core.defaultCoreOptions $ runError @JuvixError $ Core.toStored' (_pipelineResult ^. Core.coreResultModule) >>= Core.toStripped' Core.CheckExec of + case run + . runReader Core.defaultCoreOptions + . runError @JuvixError + $ Core.toStored' (_pipelineResult ^. Core.coreResultModule) >>= Core.toStripped' Core.CheckExec of Left _ -> assertBool "" True Right _ -> assertFailure "no error" diff --git a/test/Tree/Transformation.hs b/test/Tree/Transformation.hs index cf252bcb94..03147269e8 100644 --- a/test/Tree/Transformation.hs +++ b/test/Tree/Transformation.hs @@ -2,6 +2,7 @@ module Tree.Transformation where import Base import Tree.Transformation.Apply qualified as Apply +import Tree.Transformation.CheckNoAnoma qualified as CheckNoAnoma import Tree.Transformation.Identity qualified as Identity import Tree.Transformation.Reachability qualified as Reachability @@ -11,5 +12,6 @@ allTests = "JuvixTree transformations" [ Identity.allTests, Apply.allTests, - Reachability.allTests + Reachability.allTests, + CheckNoAnoma.allTests ] diff --git a/test/Tree/Transformation/CheckNoAnoma.hs b/test/Tree/Transformation/CheckNoAnoma.hs new file mode 100644 index 0000000000..032ae515b0 --- /dev/null +++ b/test/Tree/Transformation/CheckNoAnoma.hs @@ -0,0 +1,67 @@ +module Tree.Transformation.CheckNoAnoma where + +import Base +import Juvix.Compiler.Tree.Error +import Juvix.Compiler.Tree.Transformation as Tree +import Juvix.Compiler.Tree.Translation.FromSource +import Juvix.Data.PPOutput +import Tree.Eval.Negative qualified as Eval + +data CheckNoAnomaTest = CheckNoAnomaTest + { _testEval :: Eval.NegTest + } + +fromTest :: CheckNoAnomaTest -> TestTree +fromTest = mkTest . toTestDescr + +root :: Path Abs Dir +root = relToProject $(mkRelDir "tests/Tree/negative/") + +treeEvalTransformationErrorAssertion :: + Path Abs File -> + [TransformationId] -> + (JuvixError -> IO ()) -> + (String -> IO ()) -> + Assertion +treeEvalTransformationErrorAssertion mainFile trans checkError step = do + step "Parse" + s <- readFile mainFile + case runParser mainFile s of + Left err -> assertFailure (show (pretty err)) + Right tab0 -> do + step "Validate" + case run $ runError @JuvixError $ applyTransformations [Validate] tab0 of + Left err -> assertFailure (show (pretty (fromJuvixError @GenericError err))) + Right tab1 -> do + unless (null trans) $ + step "Transform" + case run $ runError @JuvixError $ applyTransformations trans tab1 of + Left e -> checkError e + Right {} -> assertFailure "Expected error" + +toTestDescr :: CheckNoAnomaTest -> TestDescr +toTestDescr CheckNoAnomaTest {..} = + let Eval.NegTest {..} = _testEval + tRoot = root _relDir + file' = tRoot _file + checkError :: JuvixError -> IO () + checkError e = + unless + (isJust (fromJuvixError @TreeError e)) + (assertFailure (unpack ("Expected TreeError. got: " <> renderTextDefault e))) + in TestDescr + { _testName = _name, + _testRoot = tRoot, + _testAssertion = Steps $ treeEvalTransformationErrorAssertion file' [CheckNoAnoma] checkError + } + +allTests :: TestTree +allTests = testGroup "CheckNoAnoma" (map (fromTest . CheckNoAnomaTest) tests) + +tests :: [Eval.NegTest] +tests = + [ Eval.NegTest + "anomaGet" + $(mkRelDir ".") + $(mkRelFile "test009.jvt") + ] diff --git a/tests/Tree/negative/test009.jvt b/tests/Tree/negative/test009.jvt new file mode 100644 index 0000000000..39e5008270 --- /dev/null +++ b/tests/Tree/negative/test009.jvt @@ -0,0 +1,5 @@ +-- calling unsupported anoma-get + +function main() : * { + anoma-get(1) +}