summaryrefslogtreecommitdiff
path: root/src/Language/Fiddle/Internal/UnitInterface.hs
blob: 465741f418a65ef9b2140f7c5ad693ea5ba1c866 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}

module Language.Fiddle.Internal.UnitInterface where

import Data.Aeson
import Data.List (intercalate)
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
import Data.Maybe (fromMaybe, maybeToList)
import qualified Data.Text
import Data.Word
import GHC.Generics
import Language.Fiddle.Internal.Scopes (Scope)
import qualified Language.Fiddle.Internal.Scopes as Scopes
import Language.Fiddle.Internal.UnitNumbers
import Language.Fiddle.Types (SourceSpan)

data InternalDirectiveExpression
  = InternalDirectiveExpressionNumber String
  | InternalDirectiveExpressionString String
  deriving (Generic, ToJSON, FromJSON, Show, Eq, Ord)

-- | Represents a compiler directive that provides configuration for the compiler
--   or its various backends. Directives can adjust the behavior of the compiler
--   or influence the code generation in the backends.
data InternalDirective = InternalDirective
  { -- | Specifies the backend that this directive is intended for. If 'Nothing',
    --   the directive applies globally across all backends.
    internalDirectiveBackend :: Maybe String,
    -- | The key or name of the directive. This identifies the directive's
    --   purpose, such as enabling specific features or setting options.
    internalDirectiveKey :: String,
    -- | The optional value associated with this directive. Some directives
    --   may not require a value (e.g., flags), in which case this field is 'Nothing'.
    internalDirectiveValue :: Maybe InternalDirectiveExpression
  }
  deriving (Generic, ToJSON, FromJSON, Show, Eq, Ord)

data QualifiedPath a = QualifiedPath
  { -- | The part of the qualified path that belongs to the package.
    packagePart :: [String],
    -- | The part of the qualified path that belongs to the object.
    objectPart :: [String],
    -- | The part of the qualified path that belongs to a register.
    registerPart :: [String],
    -- | The basename (unqualified path)
    basenamePart :: a
  }
  deriving (Generic, ToJSON, FromJSON, Show, Eq, Ord, Functor)

qualifiedPathToString :: String -> String -> QualifiedPath String -> String
qualifiedPathToString majorSeparator minorSeparator qp =
  intercalate majorSeparator $
    map (intercalate minorSeparator) $
      filter
        (not . null)
        [ packagePart qp,
          objectPart qp,
          registerPart qp,
          [basenamePart qp]
        ]

-- | Turn a QualifiedPath with a string to a String list for scope lookups.
qualifiedPathToList :: QualifiedPath String -> NonEmpty String
qualifiedPathToList (QualifiedPath package obj reg base) =
  NonEmpty.prependList (package ++ obj ++ reg) (NonEmpty.singleton base)

-- | Metadata about an exported value. This includes things like the source
-- location, doc comments and compiler directives associated with the exported
-- symbol.
data Metadata = Metadata
  { -- | Fully-qualified path the the element.
    metadataFullyQualifiedPath :: QualifiedPath String,
    -- | Source location for the exported symbol.
    metadataSourceSpan :: SourceSpan,
    -- | Doc comment associated with the symbol.
    metadataDocComment :: Data.Text.Text,
    -- | List of directives associated with this exported symbol.
    metadataDirectives :: [InternalDirective]
  }
  deriving (Generic, ToJSON, FromJSON, Show, Eq, Ord)

-- | Contains a datastructure which represents a FiddleUnit.
--
-- These datastructures contain the exported symobls of a fiddle unit and it's
-- direct dependencies.
data UnitInterface where
  UnitInterface ::
    { rootScope :: Scope String (Metadata, ExportedDecl),
      dependencies :: [FilePath]
    } ->
    UnitInterface
  deriving (Generic, Eq, Ord, Show, FromJSON, ToJSON)

insert :: (ExportableDecl d) => d -> UnitInterface -> UnitInterface
insert decl (UnitInterface sc deps) =
  let metadata = getMetadata decl
      path = qualifiedPathToList (metadataFullyQualifiedPath metadata)
   in UnitInterface (Scopes.insertScope path (metadata, toExportedDecl decl) sc) deps

singleton :: (ExportableDecl d) => d -> UnitInterface
singleton decl =
  let path = qualifiedPathToList (metadataFullyQualifiedPath (getMetadata decl))
      metadata = getMetadata decl
   in UnitInterface (Scopes.singleton path (metadata, toExportedDecl decl)) []

instance Semigroup UnitInterface where
  (<>) (UnitInterface s d) (UnitInterface s1 d1) =
    UnitInterface (s <> s1) (d <> d1)

instance Monoid UnitInterface where
  mempty = UnitInterface mempty mempty

-- | Represents an exported package declaration in the syntax tree.
-- This is a higher-level abstraction with metadata detailing the package.
data ExportedPackageDecl where
  ExportedPackageDecl ::
    { -- | Metadata associated with the package.
      exportedPackageMetadata :: Metadata
    } ->
    ExportedPackageDecl
  deriving (Show, Eq, Ord, Generic, FromJSON, ToJSON)

-- | Represents an exported location declaration in the syntax tree.
-- Contains metadata and the actual integer value of the location.
data ExportedLocationDecl where
  ExportedLocationDecl ::
    { -- | Metadata associated with the location.
      exportedLocationMetadata :: Metadata,
      -- | The value of the location as an integer.
      exportedLocationValue :: N Address
    } ->
    ExportedLocationDecl
  deriving (Show, Eq, Ord, Generic, FromJSON, ToJSON)

-- | Represents an exported bits declaration in the syntax tree.
-- Contains metadata and the size of the bits in a Word32 format.
data ExportedBitsDecl where
  ExportedBitsDecl ::
    { -- | Metadata associated with the bits declaration.
      exportedBitsDeclMetadata :: Metadata,
      -- | The size of the bits in this declaration.
      exportedBitsDeclSizeBits :: N Bits
    } ->
    ExportedBitsDecl
  deriving (Show, Eq, Ord, Generic, FromJSON, ToJSON)

-- | Represents an exported type declaration in the syntax tree.
-- Contains metadata and the size of the type in bytes.
data ExportedTypeDecl where
  ExportedTypeDecl ::
    { -- | Metadata associated with the type declaration.
      exportedTypeDeclMetadata :: Metadata,
      -- | The size of the type in bytes.
      exportedTypeDeclSizeBytes :: N Bytes
    } ->
    ExportedTypeDecl
  deriving (Show, Eq, Ord, Generic, FromJSON, ToJSON)

data ReferencedObjectType where
  ReferencedObjectType ::
    {objectTypeReference :: QualifiedPath String} -> ReferencedObjectType
  ArrayObjectType ::
    { arrayObjectTypeType :: ReferencedObjectType,
      arrayObjectTypeNumber :: N Unitless
    } ->
    ReferencedObjectType
  deriving (Show, Eq, Ord, Generic, FromJSON, ToJSON)

-- | Represents an exported object declaration in the syntax tree.
-- This includes metadata, location, and the type of the object.
data ExportedObjectDecl where
  ExportedObjectDecl ::
    { -- | Metadata associated with the object declaration.
      exportedObjectDeclMetadata :: Metadata,
      -- | The memory location of the object.
      exportedObjectDeclLocation :: N Address,
      -- | The type of the object as a string.
      exportedObjectDeclType :: ReferencedObjectType
    } ->
    ExportedObjectDecl
  deriving (Show, Eq, Ord, Generic, FromJSON, ToJSON)

-- | A typeclass for converting various exported declarations into the
-- generalized 'ExportedDecl' type. This allows treating different exported
-- declarations uniformly in the compilation process.
class ExportableDecl a where
  toExportedDecl :: a -> ExportedDecl
  fromExportedDecl :: ExportedDecl -> Maybe a
  getMetadata :: a -> Metadata

-- Instances of 'ExportableDecl' to convert specific exported declaration types
-- into the generalized 'ExportedDecl' type.
instance ExportableDecl ExportedPackageDecl where
  toExportedDecl = ExportedPackage
  fromExportedDecl = \case
    ExportedPackage x -> Just x
    _ -> Nothing
  getMetadata = exportedPackageMetadata

instance ExportableDecl ExportedLocationDecl where
  toExportedDecl = ExportedLocation
  fromExportedDecl = \case
    ExportedLocation x -> Just x
    _ -> Nothing
  getMetadata = exportedLocationMetadata

instance ExportableDecl ExportedBitsDecl where
  toExportedDecl = ExportedBits
  fromExportedDecl = \case
    ExportedBits x -> Just x
    _ -> Nothing
  getMetadata = exportedBitsDeclMetadata

instance ExportableDecl ExportedTypeDecl where
  toExportedDecl = ExportedType
  fromExportedDecl = \case
    ExportedType x -> Just x
    _ -> Nothing
  getMetadata = exportedTypeDeclMetadata

instance ExportableDecl ExportedObjectDecl where
  toExportedDecl = ExportedObject
  fromExportedDecl = \case
    ExportedObject x -> Just x
    _ -> Nothing
  getMetadata = exportedObjectDeclMetadata

instance ExportableDecl ExportedDecl where
  toExportedDecl = id
  fromExportedDecl = Just
  getMetadata =
    \case
      ExportedPackage e -> getMetadata e
      ExportedLocation e -> getMetadata e
      ExportedBits e -> getMetadata e
      ExportedType e -> getMetadata e
      ExportedObject e -> getMetadata e

-- | A generalized representation of different exported declarations.
-- This data type allows for a uniform way to handle various exportable
-- syntax tree elements (e.g., packages, locations, bits, types, objects).
data ExportedDecl where
  ExportedPackage :: ExportedPackageDecl -> ExportedDecl
  ExportedLocation :: ExportedLocationDecl -> ExportedDecl
  ExportedBits :: ExportedBitsDecl -> ExportedDecl
  ExportedType :: ExportedTypeDecl -> ExportedDecl
  ExportedObject :: ExportedObjectDecl -> ExportedDecl
  deriving (Show, Eq, Ord, Generic, FromJSON, ToJSON)