Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record updates #2263

Merged
merged 18 commits into from
Aug 7, 2023
1 change: 1 addition & 0 deletions runtime/src/juvix/info.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ typedef struct {
assoc_t assoc;
} fixity_t;

#define PREC_MINUS_OMEGA1 (-2)
#define PREC_MINUS_OMEGA (-1)
#define PREC_OMEGA 100000

Expand Down
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Backend/C/Translation/FromReg.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ fromReg lims tab =

getPrec :: Precedence -> Expression
getPrec = \case
PrecMinusOmega1 -> macroVar "PREC_MINUS_OMEGA1"
PrecMinusOmega -> macroVar "PREC_MINUS_OMEGA"
PrecOmega -> macroVar "PREC_OMEGA"
PrecNat n -> integer n
Expand Down
5 changes: 5 additions & 0 deletions src/Juvix/Compiler/Concrete/Data/Name.hs
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,8 @@ moduleNameToTopModulePath = \case
NameQualified (QualifiedName (SymbolPath p) s) -> TopModulePath (toList p) s

instance Hashable TopModulePath

splitName :: Name -> ([Symbol], Symbol)
splitName = \case
NameQualified (QualifiedName (SymbolPath p) s) -> (toList p, s)
NameUnqualified s -> ([], s)
6 changes: 6 additions & 0 deletions src/Juvix/Compiler/Concrete/Data/NameSignature/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,11 @@ newtype NameSignature = NameSignature
}
deriving stock (Show)

newtype RecordNameSignature = RecordNameSignature
{ _recordNames :: HashMap Symbol (Symbol, Int)
}
deriving stock (Show)

makeLenses ''NameSignature
makeLenses ''RecordNameSignature
makeLenses ''NameBlock
10 changes: 10 additions & 0 deletions src/Juvix/Compiler/Concrete/Data/NameSignature/Builder.hs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module Juvix.Compiler.Concrete.Data.NameSignature.Builder
( mkNameSignature,
mkRecordNameSignature,
HasNameSignature,
module Juvix.Compiler.Concrete.Data.NameSignature.Base,
-- to supress unused warning
getBuilder,
)
where

import Data.HashMap.Strict qualified as HashMap
import Juvix.Compiler.Concrete.Data.NameSignature.Base
import Juvix.Compiler.Concrete.Data.NameSignature.Error
import Juvix.Compiler.Concrete.Translation.FromParsed.Analysis.Scoping.Error
Expand Down Expand Up @@ -182,3 +184,11 @@ addSymbol' impl sym = do

endBuild' :: Sem (Re r) a
endBuild' = get @BuilderState >>= throw

mkRecordNameSignature :: RhsRecord 'Parsed -> RecordNameSignature
mkRecordNameSignature rhs =
RecordNameSignature
( HashMap.fromList
[ (s, (s, idx)) | (Indexed idx field) <- indexFrom 0 (toList (rhs ^. rhsRecordFields)), let s = field ^. fieldName
]
)
10 changes: 9 additions & 1 deletion src/Juvix/Compiler/Concrete/Data/Scope/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,19 @@ data ScopeParameters = ScopeParameters
_scopeParsedModules :: HashMap TopModulePath (Module 'Parsed 'ModuleTop)
}

data RecordInfo = RecordInfo
{ _recordInfoConstructor :: S.Symbol,
_recordInfoSignature :: RecordNameSignature
}

data ScoperState = ScoperState
{ _scoperModulesCache :: ModulesCache,
-- | Local and top modules
_scoperModules :: HashMap S.ModuleNameId (ModuleRef' 'S.NotConcrete),
_scoperScope :: HashMap TopModulePath Scope,
_scoperSignatures :: HashMap S.NameId NameSignature
_scoperSignatures :: HashMap S.NameId NameSignature,
-- | Indexed by the inductive type. This is meant to be used for record updates
_scoperRecordSignatures :: HashMap S.NameId RecordInfo
}

data SymbolFixity = SymbolFixity
Expand Down Expand Up @@ -84,3 +91,4 @@ makeLenses ''SymbolFixity
makeLenses ''ScoperState
makeLenses ''ScopeParameters
makeLenses ''ModulesCache
makeLenses ''RecordInfo
109 changes: 108 additions & 1 deletion src/Juvix/Compiler/Concrete/Language.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import Juvix.Compiler.Concrete.Data.Literal
import Juvix.Compiler.Concrete.Data.ModuleIsTop
import Juvix.Compiler.Concrete.Data.Name
import Juvix.Compiler.Concrete.Data.NameRef
import Juvix.Compiler.Concrete.Data.NameSignature.Base (NameSignature)
import Juvix.Compiler.Concrete.Data.NameSignature.Base
import Juvix.Compiler.Concrete.Data.NameSpace
import Juvix.Compiler.Concrete.Data.PublicAnn
import Juvix.Compiler.Concrete.Data.ScopedName qualified as S
Expand All @@ -46,6 +46,16 @@ type family NameSpaceEntryType s = res | res -> s where
NameSpaceEntryType 'NameSpaceSymbols = SymbolEntry
NameSpaceEntryType 'NameSpaceModules = ModuleSymbolEntry

type RecordUpdateExtraType :: Stage -> GHC.Type
type family RecordUpdateExtraType s = res | res -> s where
RecordUpdateExtraType 'Parsed = ()
RecordUpdateExtraType 'Scoped = RecordUpdateExtra

type FieldUpdateArgIxType :: Stage -> GHC.Type
type family FieldUpdateArgIxType s = res | res -> s where
FieldUpdateArgIxType 'Parsed = ()
FieldUpdateArgIxType 'Scoped = Int

type SymbolType :: Stage -> GHC.Type
type family SymbolType s = res | res -> s where
SymbolType 'Parsed = Symbol
Expand Down Expand Up @@ -400,6 +410,25 @@ deriving stock instance Ord (ConstructorDef 'Parsed)

deriving stock instance Ord (ConstructorDef 'Scoped)

data RecordUpdateField (s :: Stage) = RecordUpdateField
{ _fieldUpdateName :: SymbolType s,
_fieldUpdateArgIx :: FieldUpdateArgIxType s,
_fieldUpdateAssignKw :: Irrelevant (KeywordRef),
_fieldUpdateValue :: ExpressionType s
}

deriving stock instance Show (RecordUpdateField 'Parsed)

deriving stock instance Show (RecordUpdateField 'Scoped)

deriving stock instance Eq (RecordUpdateField 'Parsed)

deriving stock instance Eq (RecordUpdateField 'Scoped)

deriving stock instance Ord (RecordUpdateField 'Parsed)

deriving stock instance Ord (RecordUpdateField 'Scoped)

data RecordField (s :: Stage) = RecordField
{ _fieldName :: SymbolType s,
_fieldColon :: Irrelevant (KeywordRef),
Expand Down Expand Up @@ -919,6 +948,8 @@ data Expression
| ExpressionLiteral LiteralLoc
| ExpressionFunction (Function 'Scoped)
| ExpressionHole (HoleType 'Scoped)
| ExpressionRecordUpdate RecordUpdateApp
| ExpressionParensRecordUpdate ParensRecordUpdate
| ExpressionBraces (WithLoc Expression)
| ExpressionIterator (Iterator 'Scoped)
| ExpressionNamedApplication (NamedApplication 'Scoped)
Expand Down Expand Up @@ -1233,6 +1264,43 @@ deriving stock instance Ord (ArgumentBlock 'Parsed)

deriving stock instance Ord (ArgumentBlock 'Scoped)

data RecordUpdateExtra = RecordUpdateExtra
{ _recordUpdateExtraConstructor :: S.Symbol,
_recordUpdateExtraSignature :: RecordNameSignature
}
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),
_recordUpdateTypeName :: IdentifierType s,
_recordUpdateExtra :: Irrelevant (RecordUpdateExtraType s),
_recordUpdateFields :: NonEmpty (RecordUpdateField s)
}

deriving stock instance Show (RecordUpdate 'Parsed)

deriving stock instance Show (RecordUpdate 'Scoped)

deriving stock instance Eq (RecordUpdate 'Parsed)

deriving stock instance Eq (RecordUpdate 'Scoped)

deriving stock instance Ord (RecordUpdate 'Parsed)

deriving stock instance Ord (RecordUpdate 'Scoped)

data RecordUpdateApp = RecordUpdateApp
{ _recordAppUpdate :: RecordUpdate 'Scoped,
_recordAppExpression :: Expression
}
deriving stock (Show, Eq, Ord)

data NamedApplication (s :: Stage) = NamedApplication
{ _namedAppName :: IdentifierType s,
_namedAppArgs :: NonEmpty (ArgumentBlock s),
Expand Down Expand Up @@ -1260,6 +1328,7 @@ data ExpressionAtom (s :: Stage)
| AtomHole (HoleType s)
| AtomBraces (WithLoc (ExpressionType s))
| AtomLet (Let s)
| AtomRecordUpdate (RecordUpdate s)
| AtomUniverse Universe
| AtomFunction (Function s)
| AtomFunArrow KeywordRef
Expand Down Expand Up @@ -1420,6 +1489,11 @@ newtype ModuleIndex = ModuleIndex
}

makeLenses ''PatternArg
makeLenses ''ParensRecordUpdate
makeLenses ''RecordUpdateExtra
makeLenses ''RecordUpdate
makeLenses ''RecordUpdateApp
makeLenses ''RecordUpdateField
makeLenses ''NonDefinitionsSection
makeLenses ''DefinitionsSection
makeLenses ''ProjectionDef
Expand Down Expand Up @@ -1520,6 +1594,8 @@ instance HasAtomicity Expression where
ExpressionCase c -> atomicity c
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
Expand Down Expand Up @@ -1632,6 +1708,18 @@ instance HasLoc (List s) where
instance SingI s => HasLoc (NamedApplication s) where
getLoc NamedApplication {..} = getLocIdentifierType _namedAppName <> getLoc (last _namedAppArgs)

instance SingI s => HasLoc (RecordUpdateField s) where
getLoc f = getLocSymbolType (f ^. fieldUpdateName) <> getLocExpressionType (f ^. fieldUpdateValue)

instance SingI s => HasLoc (RecordUpdate s) where
getLoc r = getLoc (r ^. recordUpdateAtKw) <> getLocSpan (r ^. recordUpdateFields)

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
Expand All @@ -1650,6 +1738,8 @@ instance HasLoc Expression where
ExpressionBraces i -> getLoc i
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
Expand Down Expand Up @@ -1955,13 +2045,25 @@ instance IsApe (Function 'Scoped) ApeLeaf where
_infixOp = ApeLeafFunctionKw kw
}

instance IsApe RecordUpdateApp ApeLeaf where
toApe :: RecordUpdateApp -> Ape ApeLeaf
toApe a =
ApePostfix
Postfix
{ _postfixFixity = updateFixity,
_postfixOp = ApeLeafAtom (sing :&: AtomRecordUpdate (a ^. recordAppUpdate)),
_postfixLeft = toApe (a ^. recordAppExpression)
}

instance IsApe Expression ApeLeaf where
toApe e = case e of
ExpressionApplication a -> toApe a
ExpressionInfixApplication a -> toApe a
ExpressionPostfixApplication a -> toApe a
ExpressionFunction a -> toApe a
ExpressionNamedApplication a -> toApe a
ExpressionRecordUpdate a -> toApe a
ExpressionParensRecordUpdate {} -> leaf
ExpressionParensIdentifier {} -> leaf
ExpressionIdentifier {} -> leaf
ExpressionList {} -> leaf
Expand Down Expand Up @@ -2045,3 +2147,8 @@ exportNameSpace :: forall ns. SingI ns => Lens' ExportInfo (HashMap Symbol (Name
exportNameSpace = case sing :: SNameSpace ns of
SNameSpaceSymbols -> exportSymbols
SNameSpaceModules -> exportModuleSymbols

_ConstructorRhsRecord :: Traversal' (ConstructorRhs s) (RhsRecord s)
_ConstructorRhsRecord f rhs = case rhs of
ConstructorRhsRecord r -> ConstructorRhsRecord <$> f r
_ -> pure rhs
33 changes: 33 additions & 0 deletions src/Juvix/Compiler/Concrete/Print/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,29 @@ instance SingI s => PrettyPrint (NamedApplication s) where
-- ppCode :: Members '[ExactPrint, Reader Options] r => NamedApplication s -> Sem r ()
ppCode = apeHelper

instance SingI s => PrettyPrint (RecordUpdateField s) where
ppCode RecordUpdateField {..} =
ppSymbolType _fieldUpdateName <+> ppCode _fieldUpdateAssignKw <+> ppExpressionType _fieldUpdateValue

instance SingI s => PrettyPrint (RecordUpdate s) where
ppCode RecordUpdate {..} = do
let Irrelevant (l, r) = _recordUpdateDelims
fields'
| null (_recordUpdateFields ^. _tail1) = ppCode (_recordUpdateFields ^. _head1)
| otherwise =
line
<> indent
( sequenceWith
(semicolon >> line)
(ppCode <$> _recordUpdateFields)
)
<> line
ppCode _recordUpdateAtKw
<> ppIdentifierType _recordUpdateTypeName
<> ppCode l
<> fields'
<> ppCode r

instance SingI s => PrettyPrint (ExpressionAtom s) where
ppCode = \case
AtomIdentifier n -> ppIdentifierType n
Expand All @@ -270,6 +293,7 @@ instance SingI s => PrettyPrint (ExpressionAtom s) where
AtomCase c -> ppCode c
AtomList l -> ppCode l
AtomUniverse uni -> ppCode uni
AtomRecordUpdate u -> ppCode u
AtomFunction fun -> ppCode fun
AtomLiteral lit -> ppCode lit
AtomFunArrow a -> ppCode a
Expand Down Expand Up @@ -543,6 +567,7 @@ instance SingI s => PrettyPrint (Lambda s) where

instance PrettyPrint Precedence where
ppCode = \case
PrecMinusOmega1 -> noLoc (pretty ("-ω₁" :: Text))
PrecMinusOmega -> noLoc (pretty ("-ω" :: Text))
PrecNat n -> noLoc (pretty n)
PrecOmega -> noLoc (pretty ("ω" :: Text))
Expand Down Expand Up @@ -576,6 +601,12 @@ instance PrettyPrint IteratorSyntaxDef where
<+> iterSymbol'
<+?> fmap ppCode _iterAttribs

instance PrettyPrint RecordUpdateApp where
ppCode = apeHelper

instance PrettyPrint ParensRecordUpdate where
ppCode = parens . ppCode . (^. parensRecordUpdate)

instance PrettyPrint Expression where
ppCode = \case
ExpressionIdentifier n -> ppCode n
Expand All @@ -594,6 +625,8 @@ instance PrettyPrint Expression where
ExpressionCase c -> ppCode c
ExpressionIterator i -> ppCode i
ExpressionNamedApplication i -> ppCode i
ExpressionRecordUpdate i -> ppCode i
ExpressionParensRecordUpdate i -> ppCode i

instance PrettyPrint (WithSource Pragmas) where
ppCode pragma = do
Expand Down
Loading
Loading