diff --git a/src/Juvix/Compiler/Concrete/Language.hs b/src/Juvix/Compiler/Concrete/Language.hs index b46a7c58e6..201b8274b9 100644 --- a/src/Juvix/Compiler/Concrete/Language.hs +++ b/src/Juvix/Compiler/Concrete/Language.hs @@ -959,6 +959,7 @@ data Expression | ExpressionFunction (Function 'Scoped) | ExpressionHole (HoleType 'Scoped) | ExpressionRecordUpdate RecordUpdateApp + | ExpressionParensRecordUpdate ParensRecordUpdate | ExpressionBraces (WithLoc Expression) | ExpressionIterator (Iterator 'Scoped) | ExpressionNamedApplication (NamedApplication 'Scoped) @@ -1293,6 +1294,11 @@ data RecordUpdateExtra = RecordUpdateExtra } deriving stock (Show) +newtype ParensRecordUpdate = ParensRecordUpdate + { _parensRecordUpdate :: RecordUpdate 'Scoped + } + deriving stock (Show, Eq, Ord) + data RecordUpdate (s :: Stage) = RecordUpdate { _recordUpdateAtKw :: Irrelevant KeywordRef, _recordUpdateDelims :: Irrelevant (KeywordRef, KeywordRef), @@ -1508,6 +1514,7 @@ newtype ModuleIndex = ModuleIndex } makeLenses ''PatternArg +makeLenses ''ParensRecordUpdate makeLenses ''RecordUpdateExtra makeLenses ''RecordUpdate makeLenses ''RecordUpdateApp @@ -1614,6 +1621,7 @@ instance HasAtomicity Expression where ExpressionIterator i -> atomicity i ExpressionNamedApplication i -> atomicity i ExpressionRecordUpdate {} -> Aggregate updateFixity + ExpressionParensRecordUpdate {} -> Atom expressionAtomicity :: forall s. SingI s => ExpressionType s -> Atomicity expressionAtomicity e = case sing :: SStage s of @@ -1735,6 +1743,9 @@ instance SingI s => HasLoc (RecordUpdate s) where instance HasLoc RecordUpdateApp where getLoc r = getLoc (r ^. recordAppExpression) <> getLoc (r ^. recordAppUpdate) +instance HasLoc ParensRecordUpdate where + getLoc = getLoc . (^. parensRecordUpdate) + instance HasLoc Expression where getLoc = \case ExpressionIdentifier i -> getLoc i @@ -1754,6 +1765,7 @@ instance HasLoc Expression where ExpressionIterator i -> getLoc i ExpressionNamedApplication i -> getLoc i ExpressionRecordUpdate i -> getLoc i + ExpressionParensRecordUpdate i -> getLoc i getLocIdentifierType :: forall s. SingI s => IdentifierType s -> Interval getLocIdentifierType e = case sing :: SStage s of @@ -2077,6 +2089,7 @@ instance IsApe Expression ApeLeaf where ExpressionFunction a -> toApe a ExpressionNamedApplication a -> toApe a ExpressionRecordUpdate a -> toApe a + ExpressionParensRecordUpdate {} -> leaf ExpressionParensIdentifier {} -> leaf ExpressionIdentifier {} -> leaf ExpressionList {} -> leaf diff --git a/src/Juvix/Compiler/Concrete/Print/Base.hs b/src/Juvix/Compiler/Concrete/Print/Base.hs index a8b6211b34..ac2738f168 100644 --- a/src/Juvix/Compiler/Concrete/Print/Base.hs +++ b/src/Juvix/Compiler/Concrete/Print/Base.hs @@ -614,6 +614,9 @@ instance PrettyPrint IteratorSyntaxDef where instance PrettyPrint RecordUpdateApp where ppCode = apeHelper +instance PrettyPrint ParensRecordUpdate where + ppCode = parens . ppCode . (^. parensRecordUpdate) + instance PrettyPrint Expression where ppCode = \case ExpressionIdentifier n -> ppCode n @@ -633,6 +636,7 @@ instance PrettyPrint Expression where ExpressionIterator i -> ppCode i ExpressionNamedApplication i -> ppCode i ExpressionRecordUpdate i -> ppCode i + ExpressionParensRecordUpdate i -> ppCode i instance PrettyPrint (WithSource Pragmas) where ppCode pragma = diff --git a/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs b/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs index a895113ad1..410ec9c50f 100644 --- a/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs +++ b/src/Juvix/Compiler/Concrete/Translation/FromParsed/Analysis/Scoping.hs @@ -2019,12 +2019,15 @@ checkParens :: ExpressionAtoms 'Parsed -> Sem r Expression checkParens e@(ExpressionAtoms as _) = case as of - AtomIdentifier s :| [] -> do - scopedId <- checkName s - let scopedIdenNoFix = over scopedIden (set S.nameFixity Nothing) scopedId - return (ExpressionParensIdentifier scopedIdenNoFix) - AtomIterator i :| [] -> ExpressionIterator . set iteratorParens True <$> checkIterator i - AtomCase c :| [] -> ExpressionCase . set caseParens True <$> checkCase c + p :| [] -> case p of + AtomIdentifier s -> do + scopedId <- checkName s + let scopedIdenNoFix = over scopedIden (set S.nameFixity Nothing) scopedId + return (ExpressionParensIdentifier scopedIdenNoFix) + AtomIterator i -> ExpressionIterator . set iteratorParens True <$> checkIterator i + AtomCase c -> ExpressionCase . set caseParens True <$> checkCase c + AtomRecordUpdate u -> ExpressionParensRecordUpdate . ParensRecordUpdate <$> checkRecordUpdate u + _ -> checkParseExpressionAtoms e _ -> checkParseExpressionAtoms e checkExpressionAtoms :: diff --git a/src/Juvix/Compiler/Internal/Translation/FromConcrete.hs b/src/Juvix/Compiler/Internal/Translation/FromConcrete.hs index 7b26ba83a1..b8740ea61e 100644 --- a/src/Juvix/Compiler/Internal/Translation/FromConcrete.hs +++ b/src/Juvix/Compiler/Internal/Translation/FromConcrete.hs @@ -807,6 +807,7 @@ goExpression = \case ExpressionIterator i -> goIterator i ExpressionNamedApplication i -> goNamedApplication i ExpressionRecordUpdate i -> goRecordUpdateApp i + ExpressionParensRecordUpdate i -> Internal.ExpressionLambda <$> goRecordUpdate (i ^. parensRecordUpdate) where goNamedApplication :: Concrete.NamedApplication 'Scoped -> Sem r Internal.Expression goNamedApplication = runNamedArguments >=> goExpression @@ -832,25 +833,25 @@ goExpression = \case mkArgs :: [Indexed Internal.VarName] -> Sem r [Internal.Expression] mkArgs = execOutputList . go (uncurry Indexed <$> IntMap.toAscList fieldMap) - where - go :: [Indexed (RecordUpdateField 'Scoped)] -> [Indexed Internal.VarName] -> Sem (Output Internal.Expression ': r) () - go fields = \case - [] -> return () - Indexed idx var : vars' -> case getArg idx of - Nothing -> do - output (Internal.toExpression var) - go fields vars' - Just (arg, fields') -> do - let fieldVar = goSymbol (arg ^. fieldUpdateName) - val' <- goExpression (arg ^. fieldUpdateValue) - output (Internal.renameVar fieldVar var val') - go fields' vars' - where - getArg :: Int -> Maybe (RecordUpdateField 'Scoped, [Indexed (RecordUpdateField 'Scoped)]) - getArg idx = do - Indexed fidx arg :| fs <- nonEmpty fields - guard (idx == fidx) - return (arg, fs) + where + go :: [Indexed (RecordUpdateField 'Scoped)] -> [Indexed Internal.VarName] -> Sem (Output Internal.Expression ': r) () + go fields = \case + [] -> return () + Indexed idx var : vars' -> case getArg idx of + Nothing -> do + output (Internal.toExpression var) + go fields vars' + Just (arg, fields') -> do + let fieldVar = goSymbol (arg ^. fieldUpdateName) + val' <- goExpression (arg ^. fieldUpdateValue) + output (Internal.renameVar fieldVar var val') + go fields' vars' + where + getArg :: Int -> Maybe (RecordUpdateField 'Scoped, [Indexed (RecordUpdateField 'Scoped)]) + getArg idx = do + Indexed fidx arg :| fs <- nonEmpty fields + guard (idx == fidx) + return (arg, fs) mkClause :: Sem r Internal.LambdaClause mkClause = do diff --git a/tests/Compilation/positive/out/test060.out b/tests/Compilation/positive/out/test060.out index cbaa3efc2b..9cf9bd99f6 100644 --- a/tests/Compilation/positive/out/test060.out +++ b/tests/Compilation/positive/out/test060.out @@ -1 +1 @@ -mkTriple 3 6 2 +mkTriple 30 6 2 diff --git a/tests/Compilation/positive/test060.juvix b/tests/Compilation/positive/test060.juvix index 8146c371c7..2d9bb04617 100644 --- a/tests/Compilation/positive/test060.juvix +++ b/tests/Compilation/positive/test060.juvix @@ -21,4 +21,5 @@ main := fst := fst + 1; snd := snd * 3 }; - in p'; + f : Triple Nat Nat Nat -> Triple Nat Nat Nat := (@Triple {fst := fst * 10}); + in f p';