@@ -156,6 +156,20 @@ partial def evalApp (state : HState) (originalExpr e1 e2 : HExpr) : HState × HE
156156 -- Second application to StringFieldAccess - return partially applied
157157 -- This handles str.fieldName where fieldName is a string literal
158158 evalStringFieldAccess state2 objExpr e2'
159+ | .deferredOp "LengthAccess" _ =>
160+ -- First application to LengthAccess - return partially applied
161+ (state2, .app (.deferredOp "LengthAccess" none) e2')
162+ | .app (.deferredOp "LengthAccess" _) objExpr =>
163+ -- Second application to LengthAccess - evaluate
164+ evalLengthAccess state2 objExpr e2'
165+ | .deferredOp "FieldDelete" _ =>
166+ -- First application to FieldDelete - return partially applied
167+ (state2, .app (.deferredOp "FieldDelete" none) e2')
168+ | .app (.deferredOp "FieldDelete" _) objExpr =>
169+ -- Second application to FieldDelete - now we can evaluate
170+ -- This handles delete obj[ field ] where field is dynamic
171+ evalFieldDelete state2 objExpr e2'
172+
159173 | .deferredOp op _ =>
160174 -- First application to a deferred operation - return partially applied
161175 (state2, .app (.deferredOp op none) e2')
@@ -219,6 +233,57 @@ partial def evalStringFieldAccess (state : HState) (objExpr fieldExpr : HExpr) :
219233 -- Field is not a string literal
220234 (state, .lambda (LExpr.const "error_non_literal_string_field" none))
221235
236+ -- Handle field deletion: delete obj[ field ]
237+ partial def evalFieldDelete (state : HState) (objExpr fieldExpr : HExpr) : HState × HExpr :=
238+ -- First try to extract a numeric field index from the field expression
239+ match extractFieldIndex fieldExpr with
240+ | some fieldIndex =>
241+ -- We have a numeric field index, delete the field
242+ match objExpr with
243+ | .address addr =>
244+ -- Delete field from the object at this address
245+ match state.deleteField addr fieldIndex with
246+ | some newState => (newState, objExpr) -- Return the object address
247+ | none => (state, .lambda (LExpr.const s! "error_cannot_delete_field_{ fieldIndex} " none))
248+ | _ =>
249+ -- First evaluate the object expression to get an address
250+ let (state1, objVal) := evalHExpr state objExpr
251+ match objVal with
252+ | .address addr =>
253+ match state1.deleteField addr fieldIndex with
254+ | some newState => (newState, objVal)
255+ | none => (state1, .lambda (LExpr.const s! "error_cannot_delete_field_{ fieldIndex} " none))
256+ | _ =>
257+ (state1, .lambda (LExpr.const "error_invalid_address_for_delete" none))
258+ | none =>
259+ -- Can't extract a numeric field index, return error
260+ (state, .lambda (LExpr.const "error_field_delete_failed" none))
261+
262+ -- Handle length access for both strings and arrays
263+ partial def evalLengthAccess (state : HState) (objExpr fieldExpr : HExpr) : HState × HExpr :=
264+ match fieldExpr with
265+ | .lambda (LExpr.const key _) =>
266+ if key == "length" then
267+ match objExpr with
268+ | .lambda (LExpr.const s _) =>
269+ -- String length
270+ let len := s.length
271+ (state, .lambda (LExpr.const (toString len) (some Lambda.LMonoTy.int)))
272+ | .address addr =>
273+ -- Array length
274+ match state.heap.get? addr with
275+ | some obj =>
276+ let len := obj.size
277+ (state, .lambda (LExpr.const (toString len) (some Lambda.LMonoTy.int)))
278+ | none =>
279+ (state, .lambda (LExpr.const "error_invalid_address" none))
280+ | _ =>
281+ (state, .lambda (LExpr.const "error_not_string_or_array" none))
282+ else
283+ (state, .lambda (LExpr.const "error_unknown_length_property" none))
284+ | _ =>
285+ (state, .lambda (LExpr.const "error_non_literal_field" none))
286+
222287-- Extract a numeric field index from an expression
223288partial def extractFieldIndex (expr : HExpr) : Option Nat :=
224289 match expr with
0 commit comments