mirror of
https://github.com/zap-proto/haskell.git
synced 2026-10-30 15:05:00 +00:00
227 lines
8.5 KiB
Haskell
227 lines
8.5 KiB
Haskell
{-# LANGUAGE DuplicateRecordFields #-}
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Trans.FlatToRaw (cgrToFiles) where
|
|
|
|
import qualified IR.Common as C
|
|
import qualified IR.Flat as Flat
|
|
import qualified IR.Name as Name
|
|
import qualified IR.Raw as Raw
|
|
|
|
cgrToFiles :: Flat.CodeGenReq -> [Raw.File]
|
|
cgrToFiles Flat.CodeGenReq {reqFiles} = map fileToFile reqFiles
|
|
|
|
fileToFile :: Flat.File -> Raw.File
|
|
fileToFile Flat.File {nodes, fileId, fileName} =
|
|
Raw.File
|
|
{ fileName,
|
|
fileId,
|
|
decls = concatMap nodeToDecls nodes
|
|
}
|
|
|
|
nodeToDecls :: Flat.Node -> [Raw.Decl]
|
|
nodeToDecls Flat.Node {name = Name.ZapQ {fileId, local}, union_, typeParams} =
|
|
let typeParams' = map C.paramName typeParams
|
|
in case union_ of
|
|
Flat.Enum variants ->
|
|
[ Raw.Enum
|
|
{ typeCtor = local,
|
|
dataCtors = map (Name.mkSub local) variants
|
|
}
|
|
]
|
|
Flat.Struct {fields, isGroup, dataWordCount, pointerCount, union} ->
|
|
concat
|
|
[ [Raw.StructWrapper {typeCtor = local, typeParams = typeParams'}],
|
|
if isGroup
|
|
then []
|
|
else
|
|
[ Raw.StructInstances
|
|
{ typeCtor = local,
|
|
typeParams = typeParams',
|
|
dataWordCount,
|
|
pointerCount
|
|
}
|
|
],
|
|
concatMap (fieldToDecls local typeParams') fields,
|
|
case union of
|
|
Nothing -> []
|
|
Just Flat.Union {variants, tagOffset} ->
|
|
let local' = Name.mkSub local ""
|
|
in [ Raw.UnionVariant
|
|
{ parentTypeCtor = local,
|
|
typeParams = typeParams',
|
|
tagOffset,
|
|
unionDataCtors =
|
|
[ Raw.Variant
|
|
{ name = local,
|
|
tagValue,
|
|
locType = C.bothMap (\Flat.Node {name} -> name) fieldLocType
|
|
}
|
|
| Flat.Variant
|
|
{ field =
|
|
Flat.Field
|
|
{ fieldName = Name.ZapQ {local},
|
|
fieldLocType
|
|
},
|
|
tagValue
|
|
} <-
|
|
variants
|
|
]
|
|
},
|
|
Raw.Getter
|
|
{ fieldName = local',
|
|
typeParams = typeParams',
|
|
containerType = local,
|
|
fieldLocType =
|
|
C.HereField $
|
|
C.StructType
|
|
Name.ZapQ
|
|
{ fileId,
|
|
local = local'
|
|
}
|
|
( C.ListBrand
|
|
[ C.PtrParam
|
|
C.TypeParamRef
|
|
{ paramName,
|
|
paramIndex,
|
|
paramScope = scopeName
|
|
}
|
|
| C.TypeParamRef
|
|
{ paramName,
|
|
paramIndex,
|
|
paramScope = Flat.Node {name = scopeName}
|
|
} <-
|
|
typeParams
|
|
]
|
|
)
|
|
}
|
|
]
|
|
++ [ Raw.Setter
|
|
{ fieldName,
|
|
typeParams = typeParams',
|
|
containerType = local,
|
|
fieldLocType = C.bothMap (\Flat.Node {name} -> name) fieldLocType,
|
|
tag =
|
|
Just
|
|
Raw.TagSetter
|
|
{ tagOffset,
|
|
tagValue
|
|
}
|
|
}
|
|
| Flat.Variant
|
|
{ field =
|
|
Flat.Field
|
|
{ fieldName = Name.ZapQ {local = fieldName},
|
|
fieldLocType
|
|
},
|
|
tagValue
|
|
} <-
|
|
variants
|
|
]
|
|
++
|
|
-- This is kindof another tag setter, but it has to work a bit
|
|
-- differently for the unknown' variant, because it takes an
|
|
-- argument for what the tag should be, but also doesn't need to
|
|
-- set any other values. We can treat is as just a setter for a
|
|
-- uint16 field in the same spot:
|
|
[ Raw.Setter
|
|
{ fieldName = Name.mkSub local "unknown'",
|
|
typeParams = typeParams',
|
|
containerType = local,
|
|
fieldLocType =
|
|
C.DataField
|
|
(Raw.tagOffsetToDataLoc tagOffset)
|
|
(C.PrimWord $ C.PrimInt $ C.IntType C.Unsigned C.Sz16),
|
|
tag = Nothing
|
|
}
|
|
]
|
|
]
|
|
Flat.Interface {} ->
|
|
[ Raw.InterfaceWrapper
|
|
{ typeCtor = local,
|
|
typeParams = typeParams'
|
|
}
|
|
]
|
|
Flat.Constant {value} ->
|
|
[ Raw.Constant
|
|
{ name = local,
|
|
value = C.bothMap (\Flat.Node {name} -> name) value
|
|
}
|
|
]
|
|
Flat.Other -> []
|
|
|
|
fieldToDecls :: Name.LocalQ -> [Name.UnQ] -> Flat.Field -> [Raw.Decl]
|
|
fieldToDecls
|
|
containerType
|
|
typeParams
|
|
Flat.Field {fieldName = Name.ZapQ {local = fieldName}, fieldLocType} =
|
|
[ Raw.Getter
|
|
{ fieldName,
|
|
typeParams,
|
|
containerType,
|
|
fieldLocType = C.bothMap (\Flat.Node {name} -> name) fieldLocType
|
|
}
|
|
]
|
|
++ case fieldLocType of
|
|
C.HereField _ -> []
|
|
_ ->
|
|
[ Raw.Setter
|
|
{ fieldName,
|
|
containerType,
|
|
typeParams,
|
|
fieldLocType = C.bothMap (\Flat.Node {name} -> name) fieldLocType,
|
|
tag = Nothing
|
|
}
|
|
]
|
|
++ case fieldLocType of
|
|
C.PtrField ptrIndex _ ->
|
|
[ Raw.HasFn
|
|
{ fieldName,
|
|
typeParams,
|
|
containerType,
|
|
ptrIndex
|
|
}
|
|
]
|
|
_ ->
|
|
[]
|
|
++ case fieldLocType of
|
|
C.PtrField _ (C.ListOf _) ->
|
|
[ Raw.NewFn
|
|
{ fieldName,
|
|
typeParams,
|
|
containerType,
|
|
fieldLocType = C.bothMap (\Flat.Node {name} -> name) fieldLocType,
|
|
newFnType = Raw.NewList
|
|
}
|
|
]
|
|
C.PtrField _ (C.PrimPtr C.PrimText) ->
|
|
[ Raw.NewFn
|
|
{ fieldName,
|
|
typeParams,
|
|
containerType,
|
|
fieldLocType = C.bothMap (\Flat.Node {name} -> name) fieldLocType,
|
|
newFnType = Raw.NewText
|
|
}
|
|
]
|
|
C.PtrField _ (C.PrimPtr C.PrimData) ->
|
|
[ Raw.NewFn
|
|
{ fieldName,
|
|
typeParams,
|
|
containerType,
|
|
fieldLocType = C.bothMap (\Flat.Node {name} -> name) fieldLocType,
|
|
newFnType = Raw.NewData
|
|
}
|
|
]
|
|
C.PtrField _ (C.PtrComposite _) ->
|
|
[ Raw.NewFn
|
|
{ fieldName,
|
|
typeParams,
|
|
containerType,
|
|
fieldLocType = C.bothMap (\Flat.Node {name} -> name) fieldLocType,
|
|
newFnType = Raw.NewStruct
|
|
}
|
|
]
|
|
_ ->
|
|
[]
|