@@ -98,6 +98,7 @@ partial def builtinType (args : List Value) : InterpM Value := do
9898 | .instance ref => do
9999 let id_ ← heapGetInstanceData ref
100100 return id_.cls
101+ | .exception typeName _ => return .builtin typeName
101102 | _ => return .str s! "<class '{ typeName v} '>"
102103 | _ => throwTypeError "type() takes 1 or 3 arguments"
103104
@@ -112,6 +113,11 @@ def builtinInt (args : List Value) : InterpM Value := do
112113 match s.toList.dropWhile Char.isWhitespace |>.reverse |>.dropWhile Char.isWhitespace |>.reverse |> String.ofList |>.toInt? with
113114 | some n => return .int n
114115 | none => throwValueError s! "invalid literal for int() with base 10: '{ s} '"
116+ | [.instance iref] => do
117+ let id_ ← heapGetInstanceData iref
118+ match id_.wrappedValue with
119+ | some (.int n) => return .int n
120+ | _ => throwTypeError "int() argument must be a string or a number"
115121 | _ => throwTypeError "int() argument must be a string or a number"
116122
117123/-- `float(x)` - convert to float. -/
@@ -320,6 +326,7 @@ partial def builtinIsinstance (args : List Value) : InterpM Value := do
320326 match name with
321327 | "object" => return .bool true -- everything is an instance of object
322328 | _ =>
329+ -- First check if it's a direct built-in value match
323330 let tn := typeName obj
324331 let isMatch := match name with
325332 | "int" => tn == "int" || tn == "bool"
@@ -332,7 +339,24 @@ partial def builtinIsinstance (args : List Value) : InterpM Value := do
332339 | "set" => tn == "set"
333340 | "bytes" => tn == "bytes"
334341 | _ => false
335- return .bool isMatch
342+ if isMatch then return .bool true
343+ -- For instances, check if any class in MRO is the synthetic built-in type
344+ match obj with
345+ | .instance iref => do
346+ let id_ ← heapGetInstanceData iref
347+ match id_.cls with
348+ | .classObj cref => do
349+ let cd ← heapGetClassData cref
350+ let mut found := false
351+ for mroEntry in cd.mro do
352+ match mroEntry with
353+ | .classObj mref => do
354+ let mcd ← heapGetClassData mref
355+ if mcd.name == name then found := true
356+ | _ => pure ()
357+ return .bool found
358+ | _ => return .bool false
359+ | _ => return .bool false
336360 | [.instance instRef, .classObj _] =>
337361 return .bool (← isInstanceOfClass instRef args[1 ]!)
338362 | [.instance instRef, .tuple classes] => do
@@ -341,22 +365,52 @@ partial def builtinIsinstance (args : List Value) : InterpM Value := do
341365 match cls with
342366 | .classObj _ =>
343367 if ← isInstanceOfClass instRef cls then return .bool true
344- | .builtin "object" => return .bool true
368+ | .builtin bname => do
369+ if bname == "object" then return .bool true
370+ -- Check MRO for synthetic built-in type
371+ let id_ ← heapGetInstanceData instRef
372+ match id_.cls with
373+ | .classObj cref => do
374+ let cd ← heapGetClassData cref
375+ for mroEntry in cd.mro do
376+ match mroEntry with
377+ | .classObj mref => do
378+ let mcd ← heapGetClassData mref
379+ if mcd.name == bname then return .bool true
380+ | _ => pure ()
381+ | _ => pure ()
345382 | _ => pure ()
346383 return .bool false
347384 | [_, .classObj _] => return .bool false -- non-instance is not an instance of a custom class
348385 | _ => throwTypeError "isinstance() takes 2 arguments"
349386
387+ /-- Hash a single value for tuple/object hashing. -/
388+ private partial def hashValue : Value → InterpM Int
389+ | .int n => pure n
390+ | .bool b => pure (if b then 1 else 0 )
391+ | .str s => pure (hash s).toNat
392+ | .none => pure 0x345678
393+ | .float f => pure (hash (toString f)).toNat
394+ | .tuple items => do
395+ -- Combine element hashes using simple mixing
396+ let mut h : Int := 0x345678
397+ for item in items do
398+ let ih ← hashValue item
399+ h := h * 1000003 + ih
400+ pure h
401+ | .classObj ref => pure ref
402+ | .instance iref => do
403+ let id_ ← heapGetInstanceData iref
404+ match id_.wrappedValue with
405+ | some v => hashValue v
406+ | none => pure iref -- use heap ref as fallback
407+ | _ => pure 0
408+
350409/-- `hash(obj)` - basic hash. -/
351- def builtinHash (args : List Value) : InterpM Value := do
410+ partial def builtinHash (args : List Value) : InterpM Value := do
352411 match args with
353- | [.int n] => return .int n
354- | [.bool b] => return .int (if b then 1 else 0 )
355- | [.str s] => return .int (hash s).toNat
356- | [.none] => return .int 0
357- | [.float _f] => return .int 0 -- stub
358- | [.tuple _] => return .int 0 -- stub
359- | _ => throwTypeError "unhashable type"
412+ | [v] => return .int (← hashValue v)
413+ | _ => throwTypeError "hash() takes exactly 1 argument"
360414
361415/-- `id(obj)` - identity (stub). -/
362416def builtinId (args : List Value) : InterpM Value := do
@@ -528,10 +582,13 @@ partial def callBuiltin (name : String) (args : List Value)
528582 | "super" => do
529583 match args with
530584 | [] => do
531- -- Implicit super(): look up __class__ and self from current scope
585+ -- Implicit super(): look up __class__ and first param from current scope
532586 let cls ← lookupVariable "__class__"
533- let self ← lookupVariable "self"
534- return .superObj cls self
587+ -- Try "self" first, then "cls" (for __new__ /classmethods)
588+ let inst ← try lookupVariable "self"
589+ catch _ => try lookupVariable "cls"
590+ catch _ => throwTypeError "super(): __class__ cell not found"
591+ return .superObj cls inst
535592 | [cls, inst] => return .superObj cls inst
536593 | _ => throwTypeError "super() takes 0 or 2 arguments"
537594 | "hash" => builtinHash args
@@ -775,6 +832,10 @@ partial def callBuiltin (name : String) (args : List Value)
775832 match args with
776833 | [f] => return f
777834 | _ => throwTypeError "abstractmethod() takes exactly 1 argument"
835+ | "typing.override" => do
836+ match args with
837+ | [f] => return f
838+ | _ => throwTypeError "override() takes exactly 1 argument"
778839 -- ============================================================
779840 -- dataclasses module functions
780841 -- ============================================================
0 commit comments