@@ -71,6 +71,14 @@ public inductive SimpleGroundExpr where
7171 compiled to a reference to the mangled version of the name.
7272 -/
7373 | reference (n : Name)
74+ /--
75+ An array of `lean_object*` elements, represented by a `lean_array_object`.
76+ -/
77+ | array (elems : Array SimpleGroundArg)
78+ /--
79+ A byte array (scalar array with elem_size=1), represented by a `lean_sarray_object`.
80+ -/
81+ | byteArray (data : Array UInt8)
7482 deriving Inhabited
7583
7684public structure SimpleGroundExtState where
@@ -141,6 +149,11 @@ inductive SimpleGroundValue where
141149 | uint32 (val : UInt32)
142150 | uint64 (val : UInt64)
143151 | usize (val : UInt64)
152+ /--
153+ Contains the elements of the array in a list in reverse order to enable sharing as we traverse the
154+ expression instead.
155+ -/
156+ | arrayBuilder (elems : List SimpleGroundArg) (remainingCapacity : Nat)
144157 deriving Inhabited
145158
146159structure DetectState where
@@ -157,6 +170,8 @@ The compiler currently supports the following patterns:
157170- Constructor calls with other simple expressions
158171- `Name.mkStrX`, `Name.str._override`, and `Name.num._override`
159172- references to other declarations marked as simple ground expressions
173+ - Array literals (`Array.mkEmpty` + `Array.push` chains)
174+ - ByteArray literals (`Array.mkEmpty` + `Array.push` chains + `ByteArray.mk`)
160175 -/
161176partial def compileToSimpleGroundExpr (code : Code .impure) : CompilerM (Option SimpleGroundExpr) :=
162177 go code |>.run' {} |>.run
@@ -217,6 +232,16 @@ where
217232 go k
218233 -- boxed uint32/uint64 get extracted into separate closed terms automatically
219234 | _ => failure
235+ | .fap ``Array.mkEmpty #[.erased, .fvar sizeId]
236+ | .fap ``Array.emptyWithCapacity #[.erased, .fvar sizeId] =>
237+ let .arg (.tagged size) := (← get).groundMap[sizeId]! | failure
238+ record decl.fvarId (.arrayBuilder [] size)
239+ go k
240+ | .fap ``Array.push #[.erased, .fvar arrId, .fvar elemId] =>
241+ let .arrayBuilder elems remainingCapacity := (← get).groundMap[arrId]! | failure
242+ let .arg elemArg := (← get).groundMap[elemId]! | failure
243+ record decl.fvarId (.arrayBuilder (elemArg :: elems) (remainingCapacity - 1 ))
244+ go k
220245 | _ => failure
221246
222247 compileSetChain (id : FVarId) (info : CtorInfo) (objArgs : Array SimpleGroundArg)
@@ -301,6 +326,29 @@ where
301326 nameAcc := .str nameAcc str
302327 processedArgs := processedArgs.push (ref, nameAcc.hash)
303328 return .nameMkStr processedArgs
329+ | .fap ``Array.mkEmpty #[.erased, .fvar sizeId]
330+ | .fap ``Array.emptyWithCapacity #[.erased, .fvar sizeId] =>
331+ let .arg (.tagged 0 ) := (← get).groundMap[sizeId]! | failure
332+ return .array #[]
333+ | .fap ``ByteArray.mk #[.fvar argId] =>
334+ match (← get).groundMap[argId]! with
335+ | .arrayBuilder elems 0 =>
336+ let bytes ← elems.mapM fun elem => do
337+ let .tagged v := elem | failure
338+ return v.toUInt8
339+ return .byteArray bytes.toArray.reverse
340+ | .arg (.reference ref) =>
341+ let some (.array elems) := getSimpleGroundExprWithResolvedRefs (← getEnv) ref | failure
342+ let bytes ← elems.mapM fun elem => do
343+ let .tagged v := elem | failure
344+ return v.toUInt8
345+ return .byteArray bytes
346+ | _ => failure
347+ | .fap ``Array.push #[.erased, .fvar arrId, .fvar elemId] =>
348+ let .arrayBuilder elems remainingCapacity := (← get).groundMap[arrId]! | failure
349+ if remainingCapacity > 1 then failure
350+ let .arg elemArg := (← get).groundMap[elemId]! | failure
351+ return .array (elemArg :: elems).toArray.reverse
304352 | .fap c #[] =>
305353 guard <| isSimpleGroundDecl (← getEnv) c
306354 return .reference c
0 commit comments