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

Add builtin ByteArray type #2933

Merged
merged 28 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
add76aa
Add builtin ByteArray and primitive ByteArray type
paulcadman Aug 1, 2024
2081d86
Support builtin list constructors in core parser
paulcadman Aug 2, 2024
6b2d9df
Fix test assertion
paulcadman Aug 2, 2024
c0cf4f5
Add support for bytearray-from-list-byte and bytearray-size in Core
paulcadman Aug 2, 2024
9dd0d73
Support UInt8 type in Core parser
paulcadman Aug 6, 2024
daeb99d
Support u8 literals and uint8 type in jvt files
paulcadman Aug 6, 2024
9070d51
Make list, cons, nil predeclared builtins in jvt
paulcadman Aug 6, 2024
7bb873c
Use Str constants for list, nil and cons
paulcadman Aug 6, 2024
60201c2
Pretty print ConstUInt8 with 'u8' suffix
paulcadman Aug 6, 2024
45b2c32
Support ByteArray ops in JuvixTree
paulcadman Aug 6, 2024
a943d55
Add support or non-support for bytearray in the backends
paulcadman Aug 6, 2024
f613de6
Fix CheckNoByteArray check
paulcadman Aug 7, 2024
3012600
Add Nockma stldib function StdilbFoldBytes
paulcadman Aug 7, 2024
830a201
Add StdlibFoldBytes to the Nockma evaluator
paulcadman Aug 8, 2024
c00ab49
Add nock StdlibLengthList
paulcadman Aug 8, 2024
70cd56c
Implement OpByteArraySize and OpByteArrayFromListUInt8 in Nock
paulcadman Aug 8, 2024
28d57c9
casm reg tests, lists are now built-in
paulcadman Aug 8, 2024
e03326a
Add Anoma compilation ByteArray test
paulcadman Aug 8, 2024
fc9f49f
ByteArray Core eval: filter type arguments from constructor arguments
paulcadman Aug 8, 2024
21f849f
Format example
paulcadman Aug 8, 2024
d7e5ac0
Rename bytearray-size to bytearray-length
paulcadman Aug 9, 2024
952a2f6
Use names builtinList{Cons, Nil} for builtin List constructors in Core
paulcadman Aug 9, 2024
252b63a
Exclude ByteArray tests from Core compilation tests
paulcadman Aug 9, 2024
6d91d59
Do not define list as a JuvixTree builtin
paulcadman Aug 9, 2024
8cce437
Exclude ByteArray from JuvixTree -> JuvixAsm test
paulcadman Aug 9, 2024
f953b6e
Restore list types to casm reg tests
paulcadman Aug 9, 2024
3eba6d3
Use ppInductives from main
paulcadman Aug 9, 2024
940a073
Fix output of nockma->tree compile test for bytearray
paulcadman Aug 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Asm/Extra/Memory.hs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ getConstantType = \case
ConstUnit -> TyUnit
ConstVoid -> TyVoid
ConstUInt8 {} -> mkTypeUInt8
ConstByteArray {} -> TyByteArray

getValueType' :: (Member (Error AsmError) r) => Maybe Location -> InfoTable -> Memory -> Value -> Sem r Type
getValueType' loc tab mem = \case
Expand Down
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Asm/Translation/FromTree.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ genCode fi =
Tree.Binop x -> goBinop isTail x
Tree.Unop x -> goUnop isTail x
Tree.Cairo x -> goCairo isTail x
Tree.ByteArray {} -> error "ByteArray instructions are not supported in the Asm backend"
Tree.Anoma {} -> error "Anoma instructions are not supported in the Asm backend"
Tree.Constant x -> goConstant isTail x
Tree.MemRef x -> goMemRef isTail x
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 @@ -350,6 +350,7 @@ fromRegInstr bNoStack info = \case
Reg.ConstUnit -> macroVar "OBJ_UNIT"
Reg.ConstVoid -> macroVar "OBJ_VOID"
Reg.ConstUInt8 x -> macroCall "make_smallint" [integer x]
Reg.ConstByteArray {} -> impossible

fromPrealloc :: Reg.InstrPrealloc -> Statement
fromPrealloc Reg.InstrPrealloc {..} =
Expand Down
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Backend/Rust/Translation/FromReg.hs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ fromRegInstr info = \case
Reg.ConstUnit -> mkVar "OBJ_UNIT"
Reg.ConstVoid -> mkVar "OBJ_VOID"
Reg.ConstUInt8 x -> mkCall "make_smallint" [mkInteger x]
Reg.ConstByteArray {} -> impossible

fromAlloc :: Reg.InstrAlloc -> [Statement]
fromAlloc Reg.InstrAlloc {..} =
Expand Down
2 changes: 2 additions & 0 deletions src/Juvix/Compiler/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ module Juvix.Compiler.Builtins
module Juvix.Compiler.Builtins.Anoma,
module Juvix.Compiler.Builtins.Cairo,
module Juvix.Compiler.Builtins.Byte,
module Juvix.Compiler.Builtins.ByteArray,
)
where

import Juvix.Compiler.Builtins.Anoma
import Juvix.Compiler.Builtins.Bool
import Juvix.Compiler.Builtins.Byte
import Juvix.Compiler.Builtins.ByteArray
import Juvix.Compiler.Builtins.Cairo
import Juvix.Compiler.Builtins.Control
import Juvix.Compiler.Builtins.Debug
Expand Down
27 changes: 27 additions & 0 deletions src/Juvix/Compiler/Builtins/ByteArray.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Juvix.Compiler.Builtins.ByteArray where

import Juvix.Compiler.Builtins.Effect
import Juvix.Compiler.Internal.Extra
import Juvix.Prelude

registerByteArray :: (Member Builtins r) => AxiomDef -> Sem r ()
registerByteArray d = do
unless (isSmallUniverse' (d ^. axiomType)) (error "ByteArray should be in the small universe")
registerBuiltin BuiltinByteArray (d ^. axiomName)

registerByteArrayFromListByte :: (Member Builtins r) => AxiomDef -> Sem r ()
registerByteArrayFromListByte d = do
let loc = getLoc d
byte_ <- getBuiltinName loc BuiltinByte
list_ <- getBuiltinName loc BuiltinList
byteArray <- getBuiltinName loc BuiltinByteArray
unless (d ^. axiomType == (list_ @@ byte_ --> byteArray)) (error "bytearray-from-list-byte has the wrong type")
registerBuiltin BuiltinByteArrayFromListByte (d ^. axiomName)

registerByteArrayLength :: (Member Builtins r) => AxiomDef -> Sem r ()
registerByteArrayLength d = do
let loc = getLoc d
byteArray <- getBuiltinName loc BuiltinByteArray
nat_ <- getBuiltinName loc BuiltinNat
unless (d ^. axiomType == (byteArray --> nat_)) (error "bytearray-length has the wrong type")
registerBuiltin BuiltinByteArrayLength (d ^. axiomName)
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Casm/Translation/FromReg.hs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ fromReg tab = mkResult $ run $ runLabelInfoBuilderWithNextId (Reg.getNextSymbolI
Reg.ConstVoid -> 0
Reg.ConstString {} -> unsupported "strings"
Reg.ConstUInt8 {} -> unsupported "uint8"
Reg.ConstByteArray {} -> unsupported "bytearray"

mkLoad :: Reg.ConstrField -> Sem r RValue
mkLoad Reg.ConstrField {..} = do
Expand Down
10 changes: 9 additions & 1 deletion src/Juvix/Compiler/Concrete/Data/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ data BuiltinAxiom
| BuiltinByteEq
| BuiltinByteToNat
| BuiltinByteFromNat
| BuiltinByteArray
| BuiltinByteArrayFromListByte
| BuiltinByteArrayLength
deriving stock (Show, Eq, Ord, Enum, Bounded, Generic, Data)

instance HasNameKind BuiltinAxiom where
Expand Down Expand Up @@ -263,7 +266,9 @@ instance HasNameKind BuiltinAxiom where
BuiltinByteEq -> KNameFunction
BuiltinByteToNat -> KNameFunction
BuiltinByteFromNat -> KNameFunction

BuiltinByteArray -> KNameInductive
BuiltinByteArrayFromListByte -> KNameFunction
BuiltinByteArrayLength -> KNameFunction
getNameKindPretty :: BuiltinAxiom -> NameKind
getNameKindPretty = getNameKind

Expand Down Expand Up @@ -312,6 +317,9 @@ instance Pretty BuiltinAxiom where
BuiltinByteEq -> Str.byteEq
BuiltinByteToNat -> Str.byteToNat
BuiltinByteFromNat -> Str.byteFromNat
BuiltinByteArray -> Str.byteArray
BuiltinByteArrayFromListByte -> Str.byteArrayFromListByte
BuiltinByteArrayLength -> Str.byteArrayLength

data BuiltinType
= BuiltinTypeInductive BuiltinInductive
Expand Down
11 changes: 11 additions & 0 deletions src/Juvix/Compiler/Core/Data/InfoTableBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,17 @@ declareMaybeBuiltins = do
(tagJust, "just", mkPi' mkDynamic', Just BuiltinMaybeJust)
]

declareListBuiltins :: (Member InfoTableBuilder r) => Sem r ()
declareListBuiltins = do
tagNil <- freshTag
tagCons <- freshTag
declareInductiveBuiltins
"BuiltinList"
(Just (BuiltinTypeInductive BuiltinList))
[ (tagNil, "builtinListNil", mkPis' [mkSmallUniv], Just BuiltinListNil),
(tagCons, "builtinListCons", \x -> mkPis' [mkSmallUniv, mkDynamic', x] x, Just BuiltinListCons)
]

reserveLiteralIntToNatSymbol :: (Member InfoTableBuilder r) => Sem r ()
reserveLiteralIntToNatSymbol = do
sym <- freshSymbol
Expand Down
62 changes: 58 additions & 4 deletions src/Juvix/Compiler/Core/Evaluator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Juvix.Compiler.Core.Evaluator where

import Control.Exception qualified as Exception
import Crypto.Sign.Ed25519 qualified as E
import Data.ByteString qualified as BS
import Data.HashMap.Strict qualified as HashMap
import Data.Serialize qualified as S
import GHC.Base (seq)
Expand Down Expand Up @@ -215,6 +216,8 @@ geval opts herr tab env0 = eval' env0
OpRandomEcPoint -> randomEcPointOp
OpUInt8ToInt -> uint8ToIntOp
OpUInt8FromInt -> uint8FromIntOp
OpByteArrayFromListByte -> byteArrayFromListByteOp
OpByteArrayLength -> byteArrayLengthOp
where
err :: Text -> a
err msg = evalError msg n
Expand Down Expand Up @@ -533,6 +536,30 @@ geval opts herr tab env0 = eval' env0
. uint8FromNode
$ v
{-# INLINE uint8ToIntOp #-}

byteArrayFromListByteOp :: [Node] -> Node
byteArrayFromListByteOp =
unary $ \node ->
let !v = eval' env node
in nodeFromByteString
. BS.pack
. fromMaybe (evalError "expected list byte" v)
. listUInt8FromNode
$ v
{-# INLINE byteArrayFromListByteOp #-}

byteArrayLengthOp :: [Node] -> Node
byteArrayLengthOp =
unary $ \node ->
let !v = eval' env node
in nodeFromInteger
. fromIntegral
. BS.length
. fromMaybe (evalError "expected bytearray" v)
. byteArrayFromNode
$ v
{-# INLINE byteArrayLengthOp #-}

{-# INLINE applyBuiltin #-}

-- secretKey, publicKey are not encoded with their length as
Expand All @@ -558,6 +585,10 @@ geval opts herr tab env0 = eval' env0
nodeFromUInt8 !w = mkConstant' (ConstUInt8 w)
{-# INLINE nodeFromUInt8 #-}

nodeFromByteString :: ByteString -> Node
nodeFromByteString !b = mkConstant' (ConstByteArray b)
{-# INLINE nodeFromByteString #-}

nodeFromBool :: Bool -> Node
nodeFromBool b = mkConstr' (BuiltinTag tag) []
where
Expand All @@ -567,10 +598,10 @@ geval opts herr tab env0 = eval' env0
{-# INLINE nodeFromBool #-}

mkBuiltinConstructor :: BuiltinConstructor -> [Node] -> Maybe Node
mkBuiltinConstructor ctor args =
(\tag -> mkConstr' tag args)
. (^. constructorTag)
<$> lookupTabBuiltinConstructor tab ctor
mkBuiltinConstructor ctor args = (\tag -> mkConstr' tag args) <$> builtinConstructorTag ctor

builtinConstructorTag :: BuiltinConstructor -> Maybe Tag
builtinConstructorTag ctor = (^. constructorTag) <$> lookupTabBuiltinConstructor tab ctor

nodeMaybeNothing :: Node
nodeMaybeNothing =
Expand Down Expand Up @@ -611,6 +642,29 @@ geval opts herr tab env0 = eval' env0
_ -> Nothing
{-# INLINE uint8FromNode #-}

byteArrayFromNode :: Node -> Maybe ByteString
byteArrayFromNode = \case
NCst (Constant _ (ConstByteArray b)) -> Just b
_ -> Nothing
{-# INLINE byteArrayFromNode #-}

listUInt8FromNode :: Node -> Maybe [Word8]
listUInt8FromNode = \case
NCtr (Constr _ t xs) -> do
consTag <- builtinConstructorTag BuiltinListCons
nilTag <- builtinConstructorTag BuiltinListNil
if
| t == nilTag -> return []
| t == consTag -> case (filter (not . isType') xs) of
(hd : tl) -> do
uint8Hd <- uint8FromNode hd
uint8Tl <- concatMapM listUInt8FromNode tl
return (uint8Hd : uint8Tl)
_ -> Nothing
| otherwise -> Nothing
_ -> Nothing
{-# INLINE listUInt8FromNode #-}

printNode :: Node -> Text
printNode = \case
NCst (Constant _ (ConstString s)) -> s
Expand Down
6 changes: 6 additions & 0 deletions src/Juvix/Compiler/Core/Extra/Base.hs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ mkTypeUInt8 i = mkTypePrim i primitiveUInt8
mkTypeUInt8' :: Type
mkTypeUInt8' = mkTypeUInt8 Info.empty

mkTypeByteArray :: Info -> Type
mkTypeByteArray i = mkTypePrim i PrimByteArray

mkTypeByteArray' :: Type
mkTypeByteArray' = mkTypeByteArray Info.empty

mkDynamic :: Info -> Type
mkDynamic i = NDyn (DynamicTy i)

Expand Down
2 changes: 2 additions & 0 deletions src/Juvix/Compiler/Core/Extra/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ builtinOpArgTypes = \case
OpRandomEcPoint -> []
OpUInt8ToInt -> [mkTypeUInt8']
OpUInt8FromInt -> [mkTypeInteger']
OpByteArrayFromListByte -> [mkDynamic']
OpByteArrayLength -> [mkTypeByteArray']

translateCase :: (Node -> Node -> Node -> a) -> a -> Case -> a
translateCase translateIfFun dflt Case {..} = case _caseBranches of
Expand Down
2 changes: 2 additions & 0 deletions src/Juvix/Compiler/Core/Keywords.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import Juvix.Data.Keyword.All
kwBind,
kwBottom,
kwBuiltin,
kwByteArrayFromListByte,
kwByteArrayLength,
kwCase,
kwColon,
kwComma,
Expand Down
12 changes: 12 additions & 0 deletions src/Juvix/Compiler/Core/Language/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ data BuiltinOp
| OpRandomEcPoint
| OpUInt8ToInt
| OpUInt8FromInt
| OpByteArrayFromListByte
| OpByteArrayLength
deriving stock (Eq, Generic)

instance Serialize BuiltinOp
Expand Down Expand Up @@ -94,6 +96,8 @@ builtinOpArgsNum = \case
OpRandomEcPoint -> 0
OpUInt8ToInt -> 1
OpUInt8FromInt -> 1
OpByteArrayFromListByte -> 1
OpByteArrayLength -> 1

builtinConstrArgsNum :: BuiltinDataTag -> Int
builtinConstrArgsNum = \case
Expand Down Expand Up @@ -139,13 +143,18 @@ builtinIsFoldable = \case
OpRandomEcPoint -> False
OpUInt8ToInt -> True
OpUInt8FromInt -> True
OpByteArrayFromListByte -> False
OpByteArrayLength -> False

builtinIsCairo :: BuiltinOp -> Bool
builtinIsCairo op = op `elem` builtinsCairo

builtinIsAnoma :: BuiltinOp -> Bool
builtinIsAnoma op = op `elem` builtinsAnoma

builtinIsByteArray :: BuiltinOp -> Bool
builtinIsByteArray op = op `elem` builtinsByteArray

builtinsString :: [BuiltinOp]
builtinsString = [OpStrConcat, OpStrToInt, OpShow]

Expand All @@ -165,3 +174,6 @@ builtinsAnoma =

builtinsUInt8 :: [BuiltinOp]
builtinsUInt8 = [OpUInt8FromInt, OpUInt8ToInt]

builtinsByteArray :: [BuiltinOp]
builtinsByteArray = [OpByteArrayFromListByte, OpByteArrayLength]
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Core/Language/Nodes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ data ConstantValue
| ConstField !FField
| ConstString !Text
| ConstUInt8 !Word8
| ConstByteArray !ByteString
deriving stock (Eq, Generic)

-- | Info about a single binder. Associated with Lambda, Pi, Let, Case or Match.
Expand Down
1 change: 1 addition & 0 deletions src/Juvix/Compiler/Core/Language/Primitives.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ data Primitive
| PrimBool PrimBoolInfo
| PrimString
| PrimField
| PrimByteArray
deriving stock (Eq, Generic)

primitiveUInt8 :: Primitive
Expand Down
Loading
Loading