diff --git a/books/Books/FastPower/Proof.lean b/books/Books/FastPower/Proof.lean index 7b90cfa6..b267716f 100644 --- a/books/Books/FastPower/Proof.lean +++ b/books/Books/FastPower/Proof.lean @@ -74,17 +74,17 @@ def entry (b n : Int) : Machine := (stepN 61 (start (program b n))).getD default /-- The machine at the loop test when the loop's variables hold these values. Everything the loop does not touch is taken from `entry`; what it does touch is spelled out — the locals of `raise_to`'s frame (frame 3) and the - instance variables of the `Power` object (object 105), whose `revision` + instance variables of the `Power` object (object 114), whose `revision` counts the writes it has received. -/ def loopHead (b n : Int) (result square left : Int) (steps : Nat) : Machine := let m := entry b n let f := m.frames.getD 3 default - let o := m.heap.objs.getD 105 default + let o := m.heap.objs.getD 114 default { m with frames := m.frames.set! 3 { f with locals := [("left", .int left), ("square", .int square), ("result", .int result), ("exponent", .int n)] } - heap := { m.heap with objs := m.heap.objs.set! 105 { o with + heap := { m.heap with objs := m.heap.objs.set! 114 { o with ivars := [("@steps", .int steps), ("@base", .int b)], revision := steps + 2 } } } /-- `left > 0` has been evaluated to `t` and the `while` is about to act on it. -/ @@ -151,7 +151,7 @@ theorem finish (b n r s e : Int) (c : Nat) : stepFn (final b n r s e c) = .done (outcome b n r s e c).1 (outcome b n r s e c).2 := by kernel_rfl -theorem outcome_value (b n r s e : Int) (c : Nat) : (outcome b n r s e c).1 = .ref 106 := by +theorem outcome_value (b n r s e : Int) (c : Nat) : (outcome b n r s e c).1 = .ref 115 := by kernel_rfl /-- What `puts answer` wrote: the decimal digits of `result` and a newline. -/ @@ -161,7 +161,7 @@ theorem outcome_out (b n r s e : Int) (c : Nat) : /-- The value is an Array of the final `result` and `@steps`. -/ theorem outcome_array (b n r s e : Int) (c : Nat) : - ((outcome b n r s e c).2.heap.get 106).payload = .arr #[.int r, .int c] := by kernel_rfl + ((outcome b n r s e c).2.heap.get 115).payload = .arr #[.int r, .int c] := by kernel_rfl /-! ## 3. Arithmetic -/ @@ -291,7 +291,7 @@ theorem fast_power_correct (b n : Int) : let r := b ^ n.toNat let c := bitLength n.toNat refine ⟨(outcome b n r s' e' c).1, (outcome b n r s' e' c).2, ⟨_, boot_ok _, ?_⟩, ?_, - 106, outcome_value b n r s' e' c, outcome_array b n r s' e' c⟩ + 115, outcome_value b n r s' e' c, outcome_array b n r s' e' c⟩ · exact .of_reaches ((Reaches.of_stepN (setup b n)).trans <| hloop.trans (.of_stepN (leave b n r s' e' c))) (finish b n r s' e' c) diff --git a/books/Books/Metatheory/Framing/RootFramePrimitives.lean b/books/Books/Metatheory/Framing/RootFramePrimitives.lean index 74dacd47..6da09f76 100644 --- a/books/Books/Metatheory/Framing/RootFramePrimitives.lean +++ b/books/Books/Metatheory/Framing/RootFramePrimitives.lean @@ -849,6 +849,34 @@ set_option maxRecDepth 400000 in | split) all_goals root_hof +set_option maxHeartbeats 4000000 in +set_option maxRecDepth 400000 in +@[rootFrameLem] theorem pathArg?_frame (K : List Kont) (m : Machine) (v : Value) : + Builtins.pathArg? (pushRootK K m) v = Builtins.pathArg? m v := by + cases v <;> simp [Builtins.pathArg?, pushRootK_heap] + +@[rootFrameLem] theorem vfs_lookup_frame (K : List Kont) (m : Machine) (p : String) : + VFS.lookup (pushRootK K m).heap p = VFS.lookup m.heap p := by + simp [VFS.lookup, VFS.resolve, pushRootK_heap] + +set_option maxHeartbeats 4000000 in +set_option maxRecDepth 400000 in +@[rootFrameLem] theorem runFS_frame (K : List Kont) (bid : String) (recv : Value) + (args : List Value) (m : Machine) : + runFS bid recv args (pushRootK K m) = bRootPush K (runFS bid recv args m) := by + rw [runFS.eq_def, runFS.eq_def] + root_simp + root_arms + all_goals root_hof + all_goals (repeat' first + | rfl + | (simp only [rootFrameLem]; done) + | (simp [rootFrameLem]; done) + | (rw [foldPair_frame K]; try simp only [rootFrameLem]) + | (rw [foldPairArray_frame K]; try simp only [rootFrameLem]) + | intro _ + | split) + @[rootFrameLem] theorem nativeModuleName_frame (K : List Kont) (m : Machine) (cp : ClassPayload) : nativeModuleName (pushRootK K m) cp = bRootPush K (nativeModuleName m cp) := by unfold nativeModuleName diff --git a/books/Books/TypeSoundness/Checker/Guards/GlobalConsts.lean b/books/Books/TypeSoundness/Checker/Guards/GlobalConsts.lean index 5e95da64..42c20ae8 100644 --- a/books/Books/TypeSoundness/Checker/Guards/GlobalConsts.lean +++ b/books/Books/TypeSoundness/Checker/Guards/GlobalConsts.lean @@ -3,7 +3,7 @@ The semantic boot gate checks this data against the actual prelude heap. -/ namespace Checker def bootGlobalConsts : List String := - ["T", "Struct", "Encoding", "File", "URI", "Pathname", "JSON", "Forwardable", + ["T", "Struct", "Encoding", "File", "IO", "Dir", "URI", "Pathname", "JSON", "Forwardable", "Enumerable", "Comparable", "BasicObject", "Object", "Module", "Class", "NilClass", "TrueClass", "FalseClass", "Integer", "Float", "String", "Symbol", "Array", "Hash", "Exception", "StandardError", "RuntimeError", "ArgumentError", "TypeError", "NameError", diff --git a/books/Books/TypeSoundness/Conformance/Core/State.lean b/books/Books/TypeSoundness/Conformance/Core/State.lean index a2ae1b90..e2b8684b 100644 --- a/books/Books/TypeSoundness/Conformance/Core/State.lean +++ b/books/Books/TypeSoundness/Conformance/Core/State.lean @@ -498,9 +498,16 @@ def coreClsNames : List String := "IOError", "FrozenError", "NotImplementedError"] /-- The boot metaclasses of Integer and String: `Integer === x` and `String === x` dispatch -from here, where Module#=== is installed (checked at boot by `coreDataB`). -/ -def intMetaId : ObjId := 76 -def strMetaId : ObjId := 85 +from here, where Module#=== is installed (checked at boot by `coreDataB`). + +These are ids in the **prelude-booted** heap (`Prelude.boot`), not `H₀`'s: phase 1 +realizes the `File`/`Dir`/`IO` singleton eigenclasses (issue #7 step 1) and the +exception eigenclasses, so the ids depend on the whole boot. They are re-pinned by +hand whenever a bootstrap class or a boot-time eigenclass is added, and `#guard +bootOkB` catches a stale value. Deriving them from the heap instead of pinning +them is tracked as follow-up debt. -/ +def intMetaId : ObjId := 87 +def strMetaId : ObjId := 96 /-- **The core classes are what they are.** diff --git a/books/Books/TypeSoundness/Controls/ConstantReachControls.lean b/books/Books/TypeSoundness/Controls/ConstantReachControls.lean index bd886da3..398d6da1 100644 --- a/books/Books/TypeSoundness/Controls/ConstantReachControls.lean +++ b/books/Books/TypeSoundness/Controls/ConstantReachControls.lean @@ -22,7 +22,7 @@ private def eigenPayload : ClassPayload := { superclass := some Boot.basicObjectId, name := "", attached := some 45, methods := hooks } private def eigenObj : Object := { klass := Boot.classId, payload := .cls eigenPayload } private def h : Heap := - { objs := ((((Array.replicate 47 (default : Object)).set! 0 basic).set! 1 root).set! 45 detached).set! 46 eigenObj } + { objs := ((((Array.replicate 48 (default : Object)).set! 0 basic).set! 1 root).set! 45 detached).set! 46 eigenObj } private def m : Machine := { ctl := .value .nil, heap := h, frames := #[{ self := .ref Boot.mainId, defmod := Boot.objectId, cref := [], kind := .toplevel }], stack := [0] } @@ -86,7 +86,7 @@ theorem old_site_not_preserved : intro site have he := site.constants "Next" have hmiss : instanceConstResolve (FreshClassActual.heap m "Next" 46) 45 "Next" = none := rfl - have hglobal : constLookup (FreshClassActual.heap m "Next" 46) "Next" = some (.ref 47) := rfl + have hglobal : constLookup (FreshClassActual.heap m "Next" 46) "Next" = some (.ref 48) := rfl rw [hmiss, hglobal] at he cases he diff --git a/ruby-lean/RubyCore/Boot.lean b/ruby-lean/RubyCore/Boot.lean index 6abe2af1..7effe201 100644 --- a/ruby-lean/RubyCore/Boot.lean +++ b/ruby-lean/RubyCore/Boot.lean @@ -46,6 +46,25 @@ def boot : Except String Machine := let initial := Boot.classTable.foldl (fun m entry => if (ancestors m.heap entry.1).contains Boot.exceptionId then (Interp.eigenclassOf m entry.1).2 else m) initial + -- Filesystem singleton methods (issue #7 step 1): the `File.`/`Dir.`/`IO.` + -- class methods that actually exist in CRuby and are modeled, installed on + -- the constants' eigenclasses here exactly like `Exception.exception`, and + -- reached by ordinary dispatch — no interpreter special case, and the + -- prelude's own `File.basename`/`method_missing` continue to resolve as + -- before. Only real CRuby class methods are installed, so an unknown call + -- still reaches the prelude's `method_missing` and gates rather than + -- answering. + let fsSingleton : List (ObjId × List String) := + [ (Boot.fileId, ["read", "write", "exist?", "file?", "directory?", "size"]), + (Boot.dirId, ["exist?"]), + (Boot.ioId, ["read", "write"]) ] + let initial := fsSingleton.foldl (fun m (cls, names) => + let (eigen, m) := Interp.eigenclassOf m cls + let cname := match m.heap.classPayload? cls with | some c => c.name | none => "" + names.foldl (fun m name => + let bid := cname ++ "#" ++ name + let md : MethodDef := { params := [], body := .nil, owner := eigen, builtin := some bid } + { m with heap := defineMethod m.heap eigen name md }) m) initial match Interp.run bootFuel initial with | .value _ m => .ok m | .uncaught exc m => diff --git a/ruby-lean/RubyCore/Builtins/FS.lean b/ruby-lean/RubyCore/Builtins/FS.lean new file mode 100644 index 00000000..8824b613 --- /dev/null +++ b/ruby-lean/RubyCore/Builtins/FS.lean @@ -0,0 +1,101 @@ +import RubyCore.Builtins.Regex + +/-! +The filesystem singleton methods of issue #7 step 1: `File.read`/`write`/ +`exist?`/`file?`/`directory?`/`size` over the symbolic boot fixture +(`RubyCore/Heap.lean` §Virtual filesystem). + +The pure machine never performs OS effects; every operation here reads or mutates +the fixture tree that lives in the heap. An unmodeled operation is a named +`Unsupported` — never a guessed value and never a fake `Errno` (issue #7's +"gate stays honest"). `Errno` classes and message fidelity are step 7. + +`File.write` mutates inode bytes in place; `flush` is a no-op because descriptor +writes update the inode on write (the documented step-2 simplification, and the +only descriptor behavior step 1 needs). +-/ + +namespace RubyCore + +namespace Builtins + +/-- Read a String argument as a path, or `none` if it is not a String. -/ +def pathArg? (m : Machine) : Value → Option String + | .ref o => match (m.heap.get o).payload with + | .str s => some s + | _ => none + | _ => none + +/-- A `File.*` / `Dir.*` / `IO.*` singleton operation. `recv` is the class + object; `args` are the Ruby arguments. -/ +def runFS (bid : String) (recv : Value) (args : List Value) (m : Machine) : BRes := + let h := m.heap + match bid with + | "File#read" | "IO#read" => + match args with + | [p] => + match pathArg? m p with + | some path => + match VFS.lookup h path with + | some o => + match (h.get o).payload with + | .file bytes => okStr m bytes + | .dir _ _ => .unsupported "File.read: is a directory (Errno::EISDIR gated at step 1)" + | _ => .unsupported "File.read: not a regular file" + | none => .unsupported "File.read: no such file (Errno::ENOENT gated at step 1)" + | none => .unsupported "File.read: path argument is not a String" + | _ => .unsupported s!"{bid}: argument shape outside step 1" + | "File#write" | "IO#write" => + match args with + | [p, data] => + match pathArg? m p, pathArg? m data with + | some path, some bytes => + match VFS.lookup h path with + | some o => + match (h.get o).payload with + | .file _ => + let h' := h.set o { h.get o with payload := .file bytes } + .ok (.int (Int.ofNat bytes.length)) { m with heap := h' } + | .dir _ _ => .unsupported "File.write: is a directory (Errno::EISDIR gated at step 1)" + | _ => .unsupported "File.write: not a regular file" + | none => .unsupported "File.write: no such file (Errno::ENOENT gated at step 1)" + | _, _ => .unsupported "File.write: path or data argument is not a String" + | _ => .unsupported s!"{bid}: argument shape outside step 1" + | "File#exist?" | "Dir#exist?" => + match args with + | [p] => (match pathArg? m p with + | some path => .ok (.bool (VFS.lookup h path).isSome) m + | none => .unsupported s!"{bid}: path argument is not a String") + | _ => .unsupported s!"{bid}: argument shape outside step 1" + | "File#file?" => + match args with + | [p] => (match pathArg? m p with + | some path => match VFS.lookup h path with + | some o => .ok (.bool (match (h.get o).payload with | .file _ => true | _ => false)) m + | none => .ok (.bool false) m + | none => .unsupported s!"{bid}: path argument is not a String") + | _ => .unsupported s!"{bid}: argument shape outside step 1" + | "File#directory?" => + match args with + | [p] => (match pathArg? m p with + | some path => match VFS.lookup h path with + | some o => .ok (.bool (match (h.get o).payload with | .dir _ _ => true | _ => false)) m + | none => .ok (.bool false) m + | none => .unsupported s!"{bid}: path argument is not a String") + | _ => .unsupported s!"{bid}: argument shape outside step 1" + | "File#size" => + match args with + | [p] => (match pathArg? m p with + | some path => match VFS.lookup h path with + | some o => match (h.get o).payload with + | .file bytes => .ok (.int (Int.ofNat bytes.length)) m + | .dir _ _ => .unsupported "File.size: is a directory (Errno::EISDIR gated at step 1)" + | _ => .unsupported "File.size: not a regular file" + | none => .unsupported "File.size: no such file (Errno::ENOENT gated at step 1)" + | none => .unsupported "File.size: path argument is not a String") + | _ => .unsupported "File#size: argument shape outside step 1" + | _ => runRegex bid recv args m + +end Builtins + +end RubyCore diff --git a/ruby-lean/RubyCore/Builtins/Modules.lean b/ruby-lean/RubyCore/Builtins/Modules.lean index 2994985f..32657d36 100644 --- a/ruby-lean/RubyCore/Builtins/Modules.lean +++ b/ruby-lean/RubyCore/Builtins/Modules.lean @@ -1,4 +1,5 @@ import RubyCore.Builtins.Regex +import RubyCore.Builtins.FS import RubyCore.Generated.CRubyNames /-! @@ -253,7 +254,7 @@ def runModules (bid : String) (recv : Value) (args : List Value) (m : Machine) : if names.length != args.length then .unsupported "constant visibility: name conversion" else setConstantVisibility m recv o (bid == "Module#private_constant") names | _ => .unsupported "private_constant on a non-module" - | _ => runRegex bid recv args m + | _ => runFS bid recv args m end Builtins diff --git a/ruby-lean/RubyCore/Builtins/Support.lean b/ruby-lean/RubyCore/Builtins/Support.lean index fd9ecf90..658b805e 100644 --- a/ruby-lean/RubyCore/Builtins/Support.lean +++ b/ruby-lean/RubyCore/Builtins/Support.lean @@ -110,6 +110,8 @@ def nativeReprOwner (h : Heap) (name : String) : Value → String | .mdata .. => "MatchData" | .enumerator _ => if name == "to_s" then "Object" else "Enumerator" | .chain _ => if name == "to_s" then "Object" else "Enumerator::Chain" + | .file _ => "File" + | .dir _ _ => "Dir" def reprUnchanged (h : Heap) (sens : List String) (value : Value) : Bool := sens.all fun name => diff --git a/ruby-lean/RubyCore/Generated/Prelude.lean b/ruby-lean/RubyCore/Generated/Prelude.lean index f1711a72..d121b269 100644 --- a/ruby-lean/RubyCore/Generated/Prelude.lean +++ b/ruby-lean/RubyCore/Generated/Prelude.lean @@ -8793,8 +8793,9 @@ def core_46 : Expr := none)))) def core_47 : Expr := - RubyCore.Expr.module' + RubyCore.Expr.class' "File" + none (RubyCore.Expr.seq [RubyCore.Expr.casgn "SEPARATOR" (RubyCore.Expr.str "/"), RubyCore.Expr.defs diff --git a/ruby-lean/RubyCore/Generated/PreludeJson.lean b/ruby-lean/RubyCore/Generated/PreludeJson.lean index a21046a1..60bf2088 100644 --- a/ruby-lean/RubyCore/Generated/PreludeJson.lean +++ b/ruby-lean/RubyCore/Generated/PreludeJson.lean @@ -1248,325 +1248,325 @@ def json : String := String.join [ "name\"],[\"popt\",\"include_private\",[\"false\"]]],[\"true\"]]]],[\"module\",\"Kernel\",[\"def\"", ",\"Pathname\",[[\"preq\",\"arg\"]],[\"if\",[\"send\",[\"var\",\"local\",\"arg\"],\"is_a?\",[[\"c", "onst\",\"Pathname\"]],null],[\"var\",\"local\",\"arg\"],[\"send\",[\"const\",\"Pathname\"],\"new", - "\",[[\"var\",\"local\",\"arg\"]],null]]]],[\"module\",\"File\",[\"seq\",[\"casgn\",\"SEPARATOR\"", - ",[\"str\",\"/\"]],[\"defs\",[\"self\"],\"basename\",[[\"preq\",\"path\"],[\"popt\",\"suffix\",[\"", - "nil\"]]],[\"seq\",[\"vasgn\",\"local\",\"s\",[\"send\",[\"var\",\"local\",\"path\"],\"to_s\",[],", - "null]],[\"vasgn\",\"local\",\"parts\",[\"send\",[\"var\",\"local\",\"s\"],\"split\",[[\"str\",\"", - "/\"]],null]],[\"vasgn\",\"local\",\"base\",[\"if\",[\"send\",[\"var\",\"local\",\"parts\"],\"emp", - "ty?\",[],null],[\"if\",[\"send\",[\"var\",\"local\",\"s\"],\"empty?\",[],null],[\"str\",\"\"],[\"", - "str\",\"/\"]],[\"send\",[\"var\",\"local\",\"parts\"],\"[]\",[[\"send\",[\"send\",[\"var\",\"loc", - "al\",\"parts\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],null]]],[\"if\",[\"send\",[\"var\"", - ",\"local\",\"suffix\"],\"nil?\",[],null],[\"return\",[\"var\",\"local\",\"base\"]],null],[\"if\"", - ",[\"send\",[\"var\",\"local\",\"suffix\"],\"==\",[[\"var\",\"local\",\"base\"]],null],[\"return\"", - ",[\"var\",\"local\",\"base\"]],null],[\"if\",[\"send\",[\"var\",\"local\",\"suffix\"],\"==\",[[\"", - "str\",\".*\"]],null],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",[\"send\",[\"var\",\"local\",", - "\"base\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],[\"while\",[\"send\",[\"var\",\"local\"", - ",\"i\"],\">\",[[\"int\",0]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"base", - "\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],\"==\",[[\"str\",\".\"]],null],[\"return\",[\"send\"", - ",[\"var\",\"local\",\"base\"],\"[]\",[[\"int\",0],[\"var\",\"local\",\"i\"]],null]],null],[\"vas", - "gn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"-\",[[\"int\",1]],null]]]],[\"var\",\"", - "local\",\"base\"]],[\"if\",[\"send\",[\"var\",\"local\",\"base\"],\"end_with?\",[[\"var\",\"loca", - "l\",\"suffix\"]],null],[\"send\",[\"var\",\"local\",\"base\"],\"[]\",[[\"int\",0],[\"send\",[\"s", - "end\",[\"var\",\"local\",\"base\"],\"length\",[],null],\"-\",[[\"send\",[\"var\",\"local\",\"suf", - "fix\"],\"length\",[],null]],null]],null],[\"var\",\"local\",\"base\"]]]]],[\"defs\",[\"self\"],\"", - "extname\",[[\"preq\",\"path\"]],[\"seq\",[\"vasgn\",\"local\",\"b\",[\"send\",null,\"basename\",", - "[[\"var\",\"local\",\"path\"]],null]],[\"vasgn\",\"local\",\"i\",[\"send\",[\"send\",[\"var\",\"", - "local\",\"b\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],[\"while\",[\"send\",[\"var\",\"lo", + "\",[[\"var\",\"local\",\"arg\"]],null]]]],[\"class\",\"File\",null,[\"seq\",[\"casgn\",\"SEPARAT", + "OR\",[\"str\",\"/\"]],[\"defs\",[\"self\"],\"basename\",[[\"preq\",\"path\"],[\"popt\",\"suffix\"", + ",[\"nil\"]]],[\"seq\",[\"vasgn\",\"local\",\"s\",[\"send\",[\"var\",\"local\",\"path\"],\"to_s\"", + ",[],null]],[\"vasgn\",\"local\",\"parts\",[\"send\",[\"var\",\"local\",\"s\"],\"split\",[[\"str\"", + ",\"/\"]],null]],[\"vasgn\",\"local\",\"base\",[\"if\",[\"send\",[\"var\",\"local\",\"parts\"],\"", + "empty?\",[],null],[\"if\",[\"send\",[\"var\",\"local\",\"s\"],\"empty?\",[],null],[\"str\",\"\"]", + ",[\"str\",\"/\"]],[\"send\",[\"var\",\"local\",\"parts\"],\"[]\",[[\"send\",[\"send\",[\"var\",\"", + "local\",\"parts\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],null]]],[\"if\",[\"send\",[\"v", + "ar\",\"local\",\"suffix\"],\"nil?\",[],null],[\"return\",[\"var\",\"local\",\"base\"]],null],[\"", + "if\",[\"send\",[\"var\",\"local\",\"suffix\"],\"==\",[[\"var\",\"local\",\"base\"]],null],[\"ret", + "urn\",[\"var\",\"local\",\"base\"]],null],[\"if\",[\"send\",[\"var\",\"local\",\"suffix\"],\"==\"", + ",[[\"str\",\".*\"]],null],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",[\"send\",[\"var\",\"loc", + "al\",\"base\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],[\"while\",[\"send\",[\"var\",\"lo", "cal\",\"i\"],\">\",[[\"int\",0]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"", - "b\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],\"==\",[[\"str\",\".\"]],null],[\"return\",[\"send", - "\",[\"var\",\"local\",\"b\"],\"[]\",[[\"var\",\"local\",\"i\"],[\"send\",[\"send\",[\"var\",\"lo", - "cal\",\"b\"],\"length\",[],null],\"-\",[[\"var\",\"local\",\"i\"]],null]],null]],null],[\"vasgn\"", - ",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"-\",[[\"int\",1]],null]]]],[\"str\",\"\"]", - "]],[\"defs\",[\"self\"],\"dirname\",[[\"preq\",\"path\"]],[\"seq\",[\"vasgn\",\"local\",\"s\",[\"", - "send\",[\"var\",\"local\",\"path\"],\"to_s\",[],null]],[\"vasgn\",\"local\",\"i\",[\"send\",[\"s", - "end\",[\"var\",\"local\",\"s\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],[\"while\",[\"sen", - "d\",[\"var\",\"local\",\"i\"],\">=\",[[\"int\",0]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"", - "var\",\"local\",\"s\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],\"==\",[[\"str\",\"/\"]],null],[", - "\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"zero?\",[],null],[\"return\",[\"str\",\"/\"", - "]],null],[\"return\",[\"send\",[\"var\",\"local\",\"s\"],\"[]\",[[\"int\",0],[\"var\",\"local\",", - "\"i\"]],null]]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"-\",[[\"i", - "nt\",1]],null]]]],[\"str\",\".\"]]],[\"defs\",[\"self\"],\"join\",[[\"prest\",\"parts\"]],[\"sen", - "d\",[\"send\",[\"var\",\"local\",\"parts\"],\"map\",[],[\"block\",[[\"preq\",\"x\"]],[],[],[\"se", - "nd\",[\"var\",\"local\",\"x\"],\"to_s\",[],null]]],\"join\",[[\"str\",\"/\"]],null]],[\"defs\",[", - "\"self\"],\"method_missing\",[[\"preq\",\"name\"],[\"prest\",\"args\"],[\"pkwrest\",\"kw\"],[\"p", - "block\",\"blk\"]],[\"send\",null,\"__unsupported__\",[[\"send\",[\"send\",[\"str\",\"File.\"],\"", - "+\",[[\"send\",[\"var\",\"local\",\"name\"],\"to_s\",[],null]],null],\"+\",[[\"str\",\" (only th", - "e pure path operations are modeled)\"]],null]],null]],[\"defs\",[\"self\"],\"respond_to_missing?", - "\",[[\"preq\",\"name\"],[\"popt\",\"include_private\",[\"false\"]]],[\"true\"]]]],[\"class\",\"S", - "tring\",null,[\"seq\",[\"def\",\"sub\",[[\"preq\",\"pat\"],[\"popt\",\"rep\",[\"nil\"]],[\"pbloc", - "k\",\"blk\"]],[\"seq\",[\"vcall\",\"__match_to_caller\"],[\"if\",[\"send\",[\"send\",[\"var\",\"", - "local\",\"rep\"],\"nil?\",[],null],\"!\",[],null],[\"return\",[\"send\",null,\"__sub_rep\",[[\"v", - "ar\",\"local\",\"pat\"],[\"var\",\"local\",\"rep\"]],null]],null],[\"if\",[\"send\",[\"var\",\"l", - "ocal\",\"blk\"],\"nil?\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"Str", - "ing#sub with neither a replacement nor a block\"]],null]],null],[\"vasgn\",\"local\",\"re\",[\"i", - "f\",[\"send\",[\"var\",\"local\",\"pat\"],\"is_a?\",[[\"const\",\"Regexp\"]],null],[\"var\",\"lo", - "cal\",\"pat\"],[\"send\",[\"const\",\"Regexp\"],\"new\",[[\"send\",[\"const\",\"Regexp\"],\"esca", - "pe\",[[\"var\",\"local\",\"pat\"]],null]],null]]],[\"vasgn\",\"local\",\"m\",[\"send\",null,\"__", - "search_at\",[[\"var\",\"local\",\"re\"],[\"int\",0]],null]],[\"if\",[\"send\",[\"var\",\"local\"", - ",\"m\"],\"nil?\",[],null],[\"return\",[\"self\"]],null],[\"vasgn\",\"local\",\"b\",[\"send\",[\"", - "var\",\"local\",\"m\"],\"begin\",[[\"int\",0]],null]],[\"vasgn\",\"local\",\"e\",[\"send\",[\"va", - "r\",\"local\",\"m\"],\"end\",[[\"int\",0]],null]],[\"send\",[\"send\",[\"send\",[\"send\",[\"sel", - "f\"],\"[]\",[[\"int\",0],[\"var\",\"local\",\"b\"]],null],\"to_s\",[],null],\"+\",[[\"send\",[\"", - "send\",[\"var\",\"local\",\"blk\"],\"call\",[[\"send\",[\"var\",\"local\",\"m\"],\"[]\",[[\"int\"", - ",0]],null]],null],\"to_s\",[],null]],null],\"+\",[[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\"", - ",\"local\",\"e\"],[\"send\",[\"vcall\",\"length\"],\"-\",[[\"var\",\"local\",\"e\"]],null]],null", - "],\"to_s\",[],null]],null]]],[\"def\",\"gsub\",[[\"preq\",\"pat\"],[\"popt\",\"rep\",[\"nil\"]],", + "base\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],\"==\",[[\"str\",\".\"]],null],[\"return\",[\"s", + "end\",[\"var\",\"local\",\"base\"],\"[]\",[[\"int\",0],[\"var\",\"local\",\"i\"]],null]],null],[", + "\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"-\",[[\"int\",1]],null]]]],[\"va", + "r\",\"local\",\"base\"]],[\"if\",[\"send\",[\"var\",\"local\",\"base\"],\"end_with?\",[[\"var\",", + "\"local\",\"suffix\"]],null],[\"send\",[\"var\",\"local\",\"base\"],\"[]\",[[\"int\",0],[\"send\"", + ",[\"send\",[\"var\",\"local\",\"base\"],\"length\",[],null],\"-\",[[\"send\",[\"var\",\"local\",", + "\"suffix\"],\"length\",[],null]],null]],null],[\"var\",\"local\",\"base\"]]]]],[\"defs\",[\"self", + "\"],\"extname\",[[\"preq\",\"path\"]],[\"seq\",[\"vasgn\",\"local\",\"b\",[\"send\",null,\"basen", + "ame\",[[\"var\",\"local\",\"path\"]],null]],[\"vasgn\",\"local\",\"i\",[\"send\",[\"send\",[\"va", + "r\",\"local\",\"b\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],[\"while\",[\"send\",[\"var\"", + ",\"local\",\"i\"],\">\",[[\"int\",0]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"var\",\"loca", + "l\",\"b\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],\"==\",[[\"str\",\".\"]],null],[\"return\",[", + "\"send\",[\"var\",\"local\",\"b\"],\"[]\",[[\"var\",\"local\",\"i\"],[\"send\",[\"send\",[\"var\"", + ",\"local\",\"b\"],\"length\",[],null],\"-\",[[\"var\",\"local\",\"i\"]],null]],null]],null],[\"v", + "asgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"-\",[[\"int\",1]],null]]]],[\"str\"", + ",\"\"]]],[\"defs\",[\"self\"],\"dirname\",[[\"preq\",\"path\"]],[\"seq\",[\"vasgn\",\"local\",\"", + "s\",[\"send\",[\"var\",\"local\",\"path\"],\"to_s\",[],null]],[\"vasgn\",\"local\",\"i\",[\"send", + "\",[\"send\",[\"var\",\"local\",\"s\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],[\"while\"", + ",[\"send\",[\"var\",\"local\",\"i\"],\">=\",[[\"int\",0]],null],[\"seq\",[\"if\",[\"send\",[\"se", + "nd\",[\"var\",\"local\",\"s\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],\"==\",[[\"str\",\"/\"]]", + ",null],[\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"zero?\",[],null],[\"return\",[\"st", + "r\",\"/\"]],null],[\"return\",[\"send\",[\"var\",\"local\",\"s\"],\"[]\",[[\"int\",0],[\"var\",\"", + "local\",\"i\"]],null]]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"-", + "\",[[\"int\",1]],null]]]],[\"str\",\".\"]]],[\"defs\",[\"self\"],\"join\",[[\"prest\",\"parts\"]", + "],[\"send\",[\"send\",[\"var\",\"local\",\"parts\"],\"map\",[],[\"block\",[[\"preq\",\"x\"]],[],", + "[],[\"send\",[\"var\",\"local\",\"x\"],\"to_s\",[],null]]],\"join\",[[\"str\",\"/\"]],null]],[\"", + "defs\",[\"self\"],\"method_missing\",[[\"preq\",\"name\"],[\"prest\",\"args\"],[\"pkwrest\",\"kw", + "\"],[\"pblock\",\"blk\"]],[\"send\",null,\"__unsupported__\",[[\"send\",[\"send\",[\"str\",\"Fil", + "e.\"],\"+\",[[\"send\",[\"var\",\"local\",\"name\"],\"to_s\",[],null]],null],\"+\",[[\"str\",\" ", + "(only the pure path operations are modeled)\"]],null]],null]],[\"defs\",[\"self\"],\"respond_to_", + "missing?\",[[\"preq\",\"name\"],[\"popt\",\"include_private\",[\"false\"]]],[\"true\"]]]],[\"cla", + "ss\",\"String\",null,[\"seq\",[\"def\",\"sub\",[[\"preq\",\"pat\"],[\"popt\",\"rep\",[\"nil\"]],", "[\"pblock\",\"blk\"]],[\"seq\",[\"vcall\",\"__match_to_caller\"],[\"if\",[\"send\",[\"send\",[\"", - "var\",\"local\",\"rep\"],\"nil?\",[],null],\"!\",[],null],[\"return\",[\"send\",null,\"__gsub_re", - "p\",[[\"var\",\"local\",\"pat\"],[\"var\",\"local\",\"rep\"]],null]],null],[\"if\",[\"send\",[\"", - "var\",\"local\",\"blk\"],\"nil?\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"st", - "r\",\"String#gsub with neither a replacement nor a block\"]],null]],null],[\"vasgn\",\"local\",\"", - "re\",[\"if\",[\"send\",[\"var\",\"local\",\"pat\"],\"is_a?\",[[\"const\",\"Regexp\"]],null],[\"v", - "ar\",\"local\",\"pat\"],[\"send\",[\"const\",\"Regexp\"],\"new\",[[\"send\",[\"const\",\"Regexp\"", - "],\"escape\",[[\"var\",\"local\",\"pat\"]],null]],null]]],[\"vasgn\",\"local\",\"out\",[\"str\",", - "\"\"]],[\"vasgn\",\"local\",\"cur\",[\"int\",0]],[\"vasgn\",\"local\",\"last\",[\"nil\"]],[\"vas", - "gn\",\"local\",\"guard\",[\"int\",0]],[\"while\",[\"send\",[\"var\",\"local\",\"guard\"],\"<=\",", - "[[\"send\",[\"vcall\",\"length\"],\"+\",[[\"int\",1]],null]],null],[\"seq\",[\"vasgn\",\"local\"", - ",\"guard\",[\"send\",[\"var\",\"local\",\"guard\"],\"+\",[[\"int\",1]],null]],[\"vasgn\",\"local", - "\",\"m\",[\"send\",null,\"__search_at\",[[\"var\",\"local\",\"re\"],[\"var\",\"local\",\"cur\"]]", - ",null]],[\"if\",[\"send\",[\"var\",\"local\",\"m\"],\"nil?\",[],null],[\"break\",null],null],[\"", - "vasgn\",\"local\",\"b\",[\"send\",[\"var\",\"local\",\"m\"],\"begin\",[[\"int\",0]],null]],[\"va", - "sgn\",\"local\",\"e\",[\"send\",[\"var\",\"local\",\"m\"],\"end\",[[\"int\",0]],null]],[\"vasgn\"", - ",\"local\",\"last\",[\"var\",\"local\",\"b\"]],[\"vasgn\",\"local\",\"out\",[\"send\",[\"var\",\"", - "local\",\"out\"],\"+\",[[\"send\",[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"local\",\"cu", - "r\"],[\"send\",[\"var\",\"local\",\"b\"],\"-\",[[\"var\",\"local\",\"cur\"]],null]],null],\"to_s", - "\",[],null],\"+\",[[\"send\",[\"send\",[\"var\",\"local\",\"blk\"],\"call\",[[\"send\",[\"var\",", - "\"local\",\"m\"],\"[]\",[[\"int\",0]],null]],null],\"to_s\",[],null]],null]],null]],[\"if\",[\"s", - "end\",[\"var\",\"local\",\"e\"],\"==\",[[\"var\",\"local\",\"b\"]],null],[\"seq\",[\"vasgn\",\"l", - "ocal\",\"out\",[\"send\",[\"var\",\"local\",\"out\"],\"+\",[[\"send\",[\"send\",[\"self\"],\"[]\"", - ",[[\"var\",\"local\",\"e\"],[\"int\",1]],null],\"to_s\",[],null]],null]],[\"vasgn\",\"local\",\"", - "cur\",[\"send\",[\"var\",\"local\",\"e\"],\"+\",[[\"int\",1]],null]]],[\"vasgn\",\"local\",\"cur", - "\",[\"var\",\"local\",\"e\"]]],[\"if\",[\"send\",[\"var\",\"local\",\"cur\"],\">\",[[\"vcall\",\"", - "length\"]],null],[\"break\",null],null]]],[\"if\",[\"send\",[\"var\",\"local\",\"cur\"],\"<=\",[", - "[\"vcall\",\"length\"]],null],[\"vasgn\",\"local\",\"out\",[\"send\",[\"var\",\"local\",\"out\"]", - ",\"+\",[[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"local\",\"cur\"],[\"send\",[\"vcall\",", - "\"length\"],\"-\",[[\"var\",\"local\",\"cur\"]],null]],null],\"to_s\",[],null]],null]],null],[\"", - "if\",[\"send\",[\"send\",[\"var\",\"local\",\"last\"],\"nil?\",[],null],\"!\",[],null],[\"send\"", - ",null,\"__search_at\",[[\"var\",\"local\",\"re\"],[\"var\",\"local\",\"last\"]],null],null],[\"v", - "ar\",\"local\",\"out\"]]],[\"def\",\"index\",[[\"preq\",\"needle\"],[\"popt\",\"start\",[\"int\"", - ",0]]],[\"seq\",[\"vcall\",\"__match_to_caller\"],[\"vasgn\",\"local\",\"i\",[\"if\",[\"send\",[\"", - "var\",\"local\",\"start\"],\"<\",[[\"int\",0]],null],[\"send\",[\"vcall\",\"length\"],\"+\",[[\"", - "var\",\"local\",\"start\"]],null],[\"var\",\"local\",\"start\"]]],[\"if\",[\"send\",[\"var\",\"l", - "ocal\",\"i\"],\"<\",[[\"int\",0]],null],[\"vasgn\",\"local\",\"i\",[\"int\",0]],null],[\"if\",[\"", - "send\",[\"var\",\"local\",\"needle\"],\"is_a?\",[[\"const\",\"Regexp\"]],null],[\"seq\",[\"vasgn", - "\",\"local\",\"m\",[\"send\",null,\"__search_at\",[[\"var\",\"local\",\"needle\"],[\"var\",\"loc", - "al\",\"i\"]],null]],[\"return\",[\"if\",[\"send\",[\"var\",\"local\",\"m\"],\"nil?\",[],null],[\"", - "nil\"],[\"send\",[\"var\",\"local\",\"m\"],\"begin\",[[\"int\",0]],null]]]],null],[\"vasgn\",\"l", - "ocal\",\"n\",[\"send\",[\"var\",\"local\",\"needle\"],\"length\",[],null]],[\"while\",[\"send\",", - "[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"var\",\"local\",\"n\"]],null],\"<=\",[[\"vcall\",\"", - "length\"]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"local\",\"i\"", - "],[\"var\",\"local\",\"n\"]],null],\"==\",[[\"var\",\"local\",\"needle\"]],null],[\"return\",[\"", - "var\",\"local\",\"i\"]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"+", - "\",[[\"int\",1]],null]]]],[\"nil\"]]],[\"def\",\"rindex\",[[\"preq\",\"needle\"],[\"popt\",\"sta", - "rt\",[\"nil\"]]],[\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"needle\"],\"is_a?\",[[\"const\"", - ",\"Regexp\"]],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"String#rindex wit", - "h a Regexp needle\"]],null]],null],[\"vasgn\",\"local\",\"n\",[\"send\",[\"var\",\"local\",\"nee", - "dle\"],\"length\",[],null]],[\"vasgn\",\"local\",\"i\",[\"if\",[\"send\",[\"var\",\"local\",\"st", - "art\"],\"nil?\",[],null],[\"send\",[\"vcall\",\"length\"],\"-\",[[\"var\",\"local\",\"n\"]],null", - "],[\"if\",[\"send\",[\"var\",\"local\",\"start\"],\"<\",[[\"int\",0]],null],[\"send\",[\"vcall\"", - ",\"length\"],\"+\",[[\"var\",\"local\",\"start\"]],null],[\"var\",\"local\",\"start\"]]]],[\"if\"", - ",[\"send\",[\"var\",\"local\",\"i\"],\">\",[[\"send\",[\"vcall\",\"length\"],\"-\",[[\"var\",\"l", - "ocal\",\"n\"]],null]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"vcall\",\"length\"],\"-\",[[", - "\"var\",\"local\",\"n\"]],null]],null],[\"while\",[\"send\",[\"var\",\"local\",\"i\"],\">=\",[[\"", - "int\",0]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"local\",\"i\"", - "],[\"var\",\"local\",\"n\"]],null],\"==\",[[\"var\",\"local\",\"needle\"]],null],[\"return\",[\"", - "var\",\"local\",\"i\"]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"-", - "\",[[\"int\",1]],null]]]],[\"nil\"]]],[\"def\",\"each_char\",[],[\"seq\",[\"if\",[\"send\",[\"se", - "nd\",null,\"block_given?\",[],null],\"!\",[],null],[\"return\",[\"vcall\",\"to_enum_chars\"]],nu", - "ll],[\"send\",null,\"__each_char_blk\",[],[\"block\",[[\"preq\",\"c\"]],[],[],[\"yield\",[[\"var", - "\",\"local\",\"c\"]]]]]]],[\"def\",\"to_enum_chars\",[],[\"vcall\",\"chars\"]],[\"def\",\"__each", - "_char_blk\",[],[\"seq\",[\"if\",[\"send\",[\"send\",null,\"block_given?\",[],null],\"!\",[],null", - "],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"Enumerator: String#each_char withou", - "t a block\"]],null]],null],[\"vasgn\",\"local\",\"i\",[\"int\",0]],[\"while\",[\"send\",[\"var\"", - ",\"local\",\"i\"],\"<\",[[\"vcall\",\"length\"]],null],[\"seq\",[\"yield\",[[\"send\",[\"self\"]", - ",\"[]\",[[\"var\",\"local\",\"i\"],[\"int\",1]],null]]],[\"vasgn\",\"local\",\"i\",[\"send\",[\"", - "var\",\"local\",\"i\"],\"+\",[[\"int\",1]],null]]]],[\"self\"]]],[\"def\",\"partition\",[[\"preq", - "\",\"sep\"]],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",null,\"index\",[[\"var\",\"local\",\"", - "sep\"]],null]],[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"nil?\",[],null],[\"return\",[\"arra", - "y\",[[\"self\"],[\"str\",\"\"],[\"str\",\"\"]]]],null],[\"array\",[[\"send\",[\"self\"],\"[]\",[", - "[\"int\",0],[\"var\",\"local\",\"i\"]],null],[\"var\",\"local\",\"sep\"],[\"send\",[\"self\"],\"", - "[]\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"send\",[\"var\",\"local\",\"sep\"],\"length\"", - ",[],null]],null],[\"send\",[\"send\",[\"vcall\",\"length\"],\"-\",[[\"var\",\"local\",\"i\"]],nu", - "ll],\"-\",[[\"send\",[\"var\",\"local\",\"sep\"],\"length\",[],null]],null]],null]]]]],[\"def\",", - "\"rpartition\",[[\"preq\",\"sep\"]],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",null,\"rindex\"", - ",[[\"var\",\"local\",\"sep\"]],null]],[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"nil?\",[],nu", - "ll],[\"return\",[\"array\",[[\"str\",\"\"],[\"str\",\"\"],[\"self\"]]]],null],[\"array\",[[\"sen", - "d\",[\"self\"],\"[]\",[[\"int\",0],[\"var\",\"local\",\"i\"]],null],[\"var\",\"local\",\"sep\"],", - "[\"send\",[\"self\"],\"[]\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"send\",[\"var\",\"loc", - "al\",\"sep\"],\"length\",[],null]],null],[\"send\",[\"send\",[\"vcall\",\"length\"],\"-\",[[\"va", - "r\",\"local\",\"i\"]],null],\"-\",[[\"send\",[\"var\",\"local\",\"sep\"],\"length\",[],null]],nu", - "ll]],null]]]]],[\"def\",\"tr\",[[\"preq\",\"from\"],[\"preq\",\"to\"]],[\"seq\",[\"vasgn\",\"loc", - "al\",\"neg\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t88\",[\"send\",[\"var\",\"local\",\"from\"],\"", - "start_with?\",[[\"str\",\"^\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t88\"],[\"send\",[\"sen", - "d\",[\"var\",\"local\",\"from\"],\"length\",[],null],\">\",[[\"int\",1]],null],[\"var\",\"local\"", - ",\"__dt_t88\"]]]],[\"vasgn\",\"local\",\"src\",[\"send\",null,\"__tr_expand\",[[\"if\",[\"var\",", - "\"local\",\"neg\"],[\"send\",[\"var\",\"local\",\"from\"],\"[]\",[[\"int\",1],[\"send\",[\"send\"", - ",[\"var\",\"local\",\"from\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],null],[\"var\",\"lo", - "cal\",\"from\"]]],null]],[\"vasgn\",\"local\",\"dst\",[\"send\",null,\"__tr_expand\",[[\"var\",\"", - "local\",\"to\"]],null]],[\"vasgn\",\"local\",\"out\",[\"str\",\"\"]],[\"send\",null,\"each_char\"", - ",[],[\"block\",[[\"preq\",\"c\"]],[],[\"hit\",\"i\"],[\"seq\",[\"vasgn\",\"local\",\"hit\",[\"se", - "nd\",[\"var\",\"local\",\"src\"],\"include?\",[[\"var\",\"local\",\"c\"]],null]],[\"if\",[\"var\"", - ",\"local\",\"neg\"],[\"vasgn\",\"local\",\"hit\",[\"send\",[\"var\",\"local\",\"hit\"],\"!\",[],", - "null]],null],[\"if\",[\"send\",[\"var\",\"local\",\"hit\"],\"!\",[],null],[\"vasgn\",\"local\",\"", - "out\",[\"send\",[\"var\",\"local\",\"out\"],\"+\",[[\"var\",\"local\",\"c\"]],null]],[\"if\",[\"", - "send\",[\"var\",\"local\",\"dst\"],\"empty?\",[],null],[\"nil\"],[\"if\",[\"var\",\"local\",\"ne", - "g\"],[\"vasgn\",\"local\",\"out\",[\"send\",[\"var\",\"local\",\"out\"],\"+\",[[\"send\",[\"var\"", - ",\"local\",\"dst\"],\"[]\",[[\"send\",[\"send\",[\"var\",\"local\",\"dst\"],\"length\",[],null],", - "\"-\",[[\"int\",1]],null]],null]],null]],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",", - "\"local\",\"src\"],\"index\",[[\"var\",\"local\",\"c\"]],null]],[\"vasgn\",\"local\",\"out\",[\"", - "send\",[\"var\",\"local\",\"out\"],\"+\",[[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"<\",[[\"", - "send\",[\"var\",\"local\",\"dst\"],\"length\",[],null]],null],[\"send\",[\"var\",\"local\",\"dst", - "\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],[\"send\",[\"var\",\"local\",\"dst\"],\"[]\",[[\"se", - "nd\",[\"send\",[\"var\",\"local\",\"dst\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],null]]", - "],null]]]]]]]]],[\"var\",\"local\",\"out\"]]],[\"def\",\"__tr_expand\",[[\"preq\",\"spec\"]],[\"", - "seq\",[\"vasgn\",\"local\",\"out\",[\"array\",[]]],[\"vasgn\",\"local\",\"i\",[\"int\",0]],[\"wh", - "ile\",[\"send\",[\"var\",\"local\",\"i\"],\"<\",[[\"send\",[\"var\",\"local\",\"spec\"],\"length", - "\",[],null]],null],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t89\",[\"send\",[\"send\",[\"var", - "\",\"local\",\"i\"],\"+\",[[\"int\",2]],null],\"<\",[[\"send\",[\"var\",\"local\",\"spec\"],\"le", - "ngth\",[],null]],null]],[\"if\",[\"var\",\"local\",\"__dt_t89\"],[\"send\",[\"send\",[\"var\",\"", - "local\",\"spec\"],\"[]\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",1]],null]],null],\"", - "==\",[[\"str\",\"-\"]],null],[\"var\",\"local\",\"__dt_t89\"]]],[\"seq\",[\"vasgn\",\"local\",\"", - "a\",[\"send\",[\"send\",[\"var\",\"local\",\"spec\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],\"", - "ord\",[],null]],[\"vasgn\",\"local\",\"b\",[\"send\",[\"send\",[\"var\",\"local\",\"spec\"],\"[]", - "\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",2]],null]],null],\"ord\",[],null]],[\"wh", - "ile\",[\"send\",[\"var\",\"local\",\"a\"],\"<=\",[[\"var\",\"local\",\"b\"]],null],[\"seq\",[\"s", - "end\",[\"var\",\"local\",\"out\"],\"push\",[[\"send\",[\"var\",\"local\",\"a\"],\"chr\",[],null]", - "],null],[\"vasgn\",\"local\",\"a\",[\"send\",[\"var\",\"local\",\"a\"],\"+\",[[\"int\",1]],null]", - "]]],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",3]],null]]],[", - "\"seq\",[\"send\",[\"var\",\"local\",\"out\"],\"push\",[[\"send\",[\"var\",\"local\",\"spec\"],\"", - "[]\",[[\"var\",\"local\",\"i\"]],null]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"lo", - "cal\",\"i\"],\"+\",[[\"int\",1]],null]]]]],[\"var\",\"local\",\"out\"]]],[\"def\",\"encoding\",[", - "],[\"seq\",[\"if\",[\"send\",null,\"__binary?\",[],null],[\"return\",[\"cpath\",[\"const\",\"Enc", - "oding\"],\"BINARY\"]],null],[\"if\",[\"send\",[\"send\",[\"vcall\",\"__bytes\"],\"all?\",[],[\"b", - "lock\",[[\"preq\",\"x\"]],[],[],[\"send\",[\"var\",\"local\",\"x\"],\"<\",[[\"int\",128]],null]]", - "],\"!\",[],null],[\"return\",[\"cpath\",[\"const\",\"Encoding\"],\"UTF_8\"]],null],[\"send\",[\"", - "const\",\"Encoding\"],\"__undetermined\",[],null]]],[\"def\",\"force_encoding\",[[\"preq\",\"enc", - "\"]],[\"seq\",[\"vasgn\",\"local\",\"n\",[\"if\",[\"send\",[\"var\",\"local\",\"enc\"],\"is_a?\"", - ",[[\"const\",\"Encoding\"]],null],[\"seq\",[\"vasgn\",\"local\",\"__dt_t90\",[\"send\",[\"var\",", - "\"local\",\"enc\"],\"__name_raw\",[],null]],[\"if\",[\"var\",\"local\",\"__dt_t90\"],[\"var\",\"", - "local\",\"__dt_t90\"],[\"str\",\"UTF-8\"]]],[\"send\",[\"var\",\"local\",\"enc\"],\"to_s\",[],nu", - "ll]]],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t94\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t9", - "3\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t92\",[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"st", - "r\",\"ASCII-8BIT\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t92\"],[\"var\",\"local\",\"__dt_t", - "92\"],[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"str\",\"BINARY\"]],null]]]],[\"if\",[\"var\"", - ",\"local\",\"__dt_t93\"],[\"var\",\"local\",\"__dt_t93\"],[\"send\",[\"var\",\"local\",\"n\"],\"", - "==\",[[\"str\",\"ascii-8bit\"]],null]]]],[\"if\",[\"var\",\"local\",\"__dt_t94\"],[\"var\",\"loc", - "al\",\"__dt_t94\"],[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"str\",\"binary\"]],null]]],[\"", - "vcall\",\"__force_binary\"],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t91\",[\"send\",[\"var\"", - ",\"local\",\"n\"],\"==\",[[\"str\",\"UTF-8\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t91\"],[", - "\"var\",\"local\",\"__dt_t91\"],[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"str\",\"utf-8\"]]", - ",null]]],[\"vcall\",\"__force_utf8\"],[\"send\",null,\"__unsupported__\",[[\"send\",[\"str\",\"S", - "tring#force_encoding to \"],\"+\",[[\"var\",\"local\",\"n\"]],null]],null]]]]],[\"def\",\"bytes\"", - ",[],[\"vcall\",\"__bytes\"]],[\"def\",\"each_byte\",[],[\"seq\",[\"if\",[\"send\",[\"send\",null", - ",\"block_given?\",[],null],\"!\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str", - "\",\"Enumerator: String#each_byte without a block\"]],null]],null],[\"send\",[\"vcall\",\"__byte", - "s\"],\"each\",[],[\"block\",[[\"preq\",\"x\"]],[],[],[\"yield\",[[\"var\",\"local\",\"x\"]]]]],[", - "\"self\"]]]]],[\"class\",\"Encoding\",null,[\"seq\",[\"def\",\"initialize\",[[\"preq\",\"name\"]", - "],[\"vasgn\",\"ivar\",\"@name\",[\"var\",\"local\",\"name\"]]],[\"def\",\"__name_raw\",[],[\"var", - "\",\"ivar\",\"@name\"]],[\"def\",\"__gate\",[],[\"send\",null,\"__unsupported__\",[[\"str\",\"En", - "coding of an ASCII-only String (US-ASCII vs UTF-8 is not tracked)\"]],null]],[\"def\",\"name\",[", - "],[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"nil?\",[],null],[\"vcall\",\"__gate\"],[\"var", - "\",\"ivar\",\"@name\"]]],[\"def\",\"to_s\",[],[\"vcall\",\"name\"]],[\"def\",\"inspect\",[],[\"s", - "eq\",[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"nil?\",[],null],[\"return\",[\"vcall\",\"_", - "_gate\"]],null],[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"==\",[[\"str\",\"UTF-8\"]],null", - "],[\"str\",\"#\"],[\"str\",\"#\"]]]],[\"def\",\"==", - "\",[[\"preq\",\"other\"]],[\"seq\",[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"nil?\",[],nu", - "ll],[\"return\",[\"vcall\",\"__gate\"]],null],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"o", - "ther\"],\"is_a?\",[[\"const\",\"Encoding\"]],null],\"!\",[],null],[\"return\",[\"false\"]],null]", - ",[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"other\"],\"__name_raw\",[],null],\"nil?\",[],n", - "ull],[\"return\",[\"send\",[\"var\",\"local\",\"other\"],\"__gate\",[],null]],null],[\"send\",[\"", - "send\",[\"var\",\"local\",\"other\"],\"__name_raw\",[],null],\"==\",[[\"var\",\"ivar\",\"@name\"", - "]],null]]],[\"def\",\"eql?\",[[\"preq\",\"other\"]],[\"send\",[\"self\"],\"==\",[[\"var\",\"loca", - "l\",\"other\"]],null]],[\"casgn\",\"UTF_8\",[\"send\",null,\"new\",[[\"str\",\"UTF-8\"]],null]],", - "[\"casgn\",\"BINARY\",[\"send\",null,\"new\",[[\"str\",\"ASCII-8BIT\"]],null]],[\"casgn\",\"ASCI", - "I_8BIT\",[\"const\",\"BINARY\"]],[\"casgn\",\"UNDETERMINED\",[\"send\",null,\"new\",[[\"nil\"]],", - "null]],[\"defs\",[\"self\"],\"__undetermined\",[],[\"const\",\"UNDETERMINED\"]]]],[\"class\",\"S", - "truct\",null,[\"defs\",[\"self\"],\"new\",[[\"prest\",\"names\"],[\"pkey\",\"keyword_init\",[\"n", - "il\"]],[\"pblock\",\"body\"]],[\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"names\"],\"empty?\"", - ",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"Struct.new with no members\"", - "]],null]],null],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"names\"],\"[]\",[[\"int\",0]],n", - "ull],\"is_a?\",[[\"const\",\"String\"]],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"", - "str\",\"Struct.new(\\\"Name\\\") (named struct constant)\"]],null]],null],[\"vasgn\",\"local\",\"", - "syms\",[\"send\",[\"var\",\"local\",\"names\"],\"map\",[],[\"block\",[[\"preq\",\"n\"]],[],[],[\"", - "send\",[\"var\",\"local\",\"n\"],\"to_sym\",[],null]]]],[\"vasgn\",\"local\",\"kwi\",[\"var\",\"", - "local\",\"keyword_init\"]],[\"vasgn\",\"local\",\"cls\",[\"send\",[\"const\",\"Class\"],\"new\",", - "[],null]],[\"send\",[\"var\",\"local\",\"cls\"],\"class_eval\",[],[\"block\",[],[],[],[\"seq\",[", - "\"send\",null,\"define_singleton_method\",[[\"sym\",\"members\"]],[\"block\",[],[],[],[\"send\",", - "[\"var\",\"local\",\"syms\"],\"dup\",[],null]]],[\"send\",null,\"define_method\",[[\"sym\",\"mem", - "bers\"]],[\"block\",[],[],[],[\"send\",[\"var\",\"local\",\"syms\"],\"dup\",[],null]]],[\"send\"", - ",null,\"define_method\",[[\"sym\",\"initialize\"]],[\"block\",[[\"prest\",\"a\"],[\"pkwrest\",\"", - "kw\"]],[],[\"bad\",\"i\"],[\"seq\",[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t97\",[\"send\",", - "[\"var\",\"local\",\"kwi\"],\"==\",[[\"true\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t97\"],", - "[\"var\",\"local\",\"__dt_t97\"],[\"seq\",[\"vasgn\",\"local\",\"__dt_t96\",[\"seq\",[\"vasgn\",", - "\"local\",\"__dt_t95\",[\"send\",[\"var\",\"local\",\"kwi\"],\"nil?\",[],null]],[\"if\",[\"var\"", - ",\"local\",\"__dt_t95\"],[\"send\",[\"var\",\"local\",\"a\"],\"empty?\",[],null],[\"var\",\"loca", - "l\",\"__dt_t95\"]]]],[\"if\",[\"var\",\"local\",\"__dt_t96\"],[\"send\",[\"send\",[\"var\",\"loc", - "al\",\"kw\"],\"empty?\",[],null],\"!\",[],null],[\"var\",\"local\",\"__dt_t96\"]]]]],[\"seq\",[\"", - "vasgn\",\"local\",\"bad\",[\"send\",[\"send\",[\"var\",\"local\",\"kw\"],\"keys\",[],null],\"rej", - "ect\",[],[\"block\",[[\"preq\",\"k\"]],[],[],[\"send\",[\"var\",\"local\",\"syms\"],\"include?\"", - ",[[\"var\",\"local\",\"k\"]],null]]]],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"bad\"],\"", - "empty?\",[],null],\"!\",[],null],[\"send\",null,\"raise\",[[\"const\",\"ArgumentError\"],[\"send", - "\",[\"str\",\"unknown keywords: \"],\"+\",[[\"send\",[\"send\",[\"var\",\"local\",\"bad\"],\"map", - "\",[],[\"block\",[[\"preq\",\"k\"]],[],[],[\"send\",[\"var\",\"local\",\"k\"],\"inspect\",[],nul", - "l]]],\"join\",[[\"str\",\", \"]],null]],null]],null],null],[\"send\",[\"var\",\"local\",\"syms\"", - "],\"each\",[],[\"block\",[[\"preq\",\"s\"]],[],[],[\"send\",null,\"instance_variable_set\",[[\"s", - "end\",[\"str\",\"@\"],\"+\",[[\"send\",[\"var\",\"local\",\"s\"],\"to_s\",[],null]],null],[\"sen", - "d\",[\"var\",\"local\",\"kw\"],\"[]\",[[\"var\",\"local\",\"s\"]],null]],null]]]],[\"seq\",[\"if", - "\",[\"send\",[\"send\",[\"var\",\"local\",\"a\"],\"length\",[],null],\">\",[[\"send\",[\"var\",\"", - "local\",\"syms\"],\"length\",[],null]],null],[\"send\",null,\"raise\",[[\"const\",\"ArgumentErro", - "r\"],[\"str\",\"struct size differs\"]],null],null],[\"vasgn\",\"local\",\"i\",[\"int\",0]],[\"w", - "hile\",[\"send\",[\"var\",\"local\",\"i\"],\"<\",[[\"send\",[\"var\",\"local\",\"syms\"],\"lengt", - "h\",[],null]],null],[\"seq\",[\"send\",null,\"instance_variable_set\",[[\"send\",[\"str\",\"@\"]", - ",\"+\",[[\"send\",[\"send\",[\"var\",\"local\",\"syms\"],\"[]\",[[\"var\",\"local\",\"i\"]],null", - "],\"to_s\",[],null]],null],[\"send\",[\"var\",\"local\",\"a\"],\"[]\",[[\"var\",\"local\",\"i\"]", - "],null]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",1]", - "],null]]]]]],[\"nil\"]]]],[\"send\",[\"var\",\"local\",\"syms\"],\"each\",[],[\"block\",[[\"preq", - "\",\"s\"]],[],[],[\"seq\",[\"send\",null,\"define_method\",[[\"var\",\"local\",\"s\"]],[\"block\"", - ",[],[],[],[\"send\",null,\"instance_variable_get\",[[\"send\",[\"str\",\"@\"],\"+\",[[\"send\",[", - "\"var\",\"local\",\"s\"],\"to_s\",[],null]],null]],null]]],[\"send\",null,\"define_method\",[[\"", - "send\",[\"send\",[\"var\",\"local\",\"s\"],\"to_s\",[],null],\"+\",[[\"str\",\"=\"]],null]],[\"b", - "lock\",[[\"preq\",\"v\"]],[],[],[\"send\",null,\"instance_variable_set\",[[\"send\",[\"str\",\"@", - "\"],\"+\",[[\"send\",[\"var\",\"local\",\"s\"],\"to_s\",[],null]],null],[\"var\",\"local\",\"v\"", - "]],null]]]]]],[\"send\",null,\"define_method\",[[\"sym\",\"to_a\"]],[\"block\",[],[],[],[\"send\"", - ",[\"var\",\"local\",\"syms\"],\"map\",[],[\"block\",[[\"preq\",\"s\"]],[],[],[\"send\",null,\"se", - "nd\",[[\"var\",\"local\",\"s\"]],null]]]]],[\"send\",null,\"define_method\",[[\"sym\",\"deconstr", - "uct\"]],[\"block\",[],[],[],[\"send\",[\"var\",\"local\",\"syms\"],\"map\",[],[\"block\",[[\"pre", - "q\",\"s\"]],[],[],[\"send\",null,\"send\",[[\"var\",\"local\",\"s\"]],null]]]]],[\"send\",null,\"", - "define_method\",[[\"sym\",\"to_h\"]],[\"block\",[],[],[\"h\"],[\"seq\",[\"vasgn\",\"local\",\"h\"", - ",[\"hash\",[]]],[\"send\",[\"var\",\"local\",\"syms\"],\"each\",[],[\"block\",[[\"preq\",\"s\"]]", - ",[],[],[\"seq\",[\"send\",[\"var\",\"local\",\"h\"],\"[]=\",[[\"var\",\"local\",\"s\"],[\"vasgn\"", - ",\"local\",\"__dt_t98\",[\"send\",null,\"send\",[[\"var\",\"local\",\"s\"]],null]]],null],[\"var", - "\",\"local\",\"__dt_t98\"]]]],[\"var\",\"local\",\"h\"]]]],[\"send\",null,\"define_method\",[[\"", - "sym\",\"[]\"]],[\"block\",[[\"preq\",\"k\"]],[],[\"i\",\"key\"],[\"if\",[\"send\",[\"var\",\"loc", - "al\",\"k\"],\"is_a?\",[[\"const\",\"Integer\"]],null],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"if\"", - ",[\"send\",[\"var\",\"local\",\"k\"],\"<\",[[\"int\",0]],null],[\"send\",[\"send\",[\"var\",\"lo", - "cal\",\"syms\"],\"length\",[],null],\"+\",[[\"var\",\"local\",\"k\"]],null],[\"var\",\"local\",\"", - "k\"]]],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t99\",[\"send\",[\"var\",\"local\",\"i\"],\"", - "<\",[[\"int\",0]],null]],[\"if\",[\"var\",\"local\",\"__dt_t99\"],[\"var\",\"local\",\"__dt_t99\"", - "],[\"send\",[\"var\",\"local\",\"i\"],\">=\",[[\"send\",[\"var\",\"local\",\"syms\"],\"length\",", - "[],null]],null]]],[\"send\",null,\"raise\",[[\"const\",\"IndexError\"],[\"send\",[\"send\",[\"se", - "nd\",[\"send\",[\"str\",\"offset \"],\"+\",[[\"send\",[\"var\",\"local\",\"k\"],\"to_s\",[],null", - "]],null],\"+\",[[\"str\",\" too large for struct(size:\"]],null],\"+\",[[\"send\",[\"send\",[\"v", - "ar\",\"local\",\"syms\"],\"length\",[],null],\"to_s\",[],null]],null],\"+\",[[\"str\",\")\"]],nu", - "ll]],null],null],[\"send\",null,\"send\",[[\"send\",[\"var\",\"local\",\"syms\"],\"[]\",[[\"var\"", - ",\"local\",\"i\"]],null]],null]],[\"seq\",[\"vasgn\",\"local\",\"key\",[\"send\",[\"var\",\"loca", - "l\",\"k\"],\"to_sym\",[],null]],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"syms\"],\"inclu", - "de?\",[[\"var\",\"local\",\"key\"]],null],\"!\",[],null],[\"send\",null,\"raise\",[[\"const\",\"", - "NameError\"],[\"send\",[\"send\",[\"str\",\"no member '\"],\"+\",[[\"send\",[\"var\",\"local\",\"", - "k\"],\"to_s\",[],null]],null],\"+\",[[\"str\",\"' in struct\"]],null]],null],null],[\"send\",nul", - "l,\"send\",[[\"var\",\"local\",\"key\"]],null]]]]],[\"send\",null,\"define_method\",[[\"sym\",\"", - "==\"]],[\"block\",[[\"preq\",\"other\"]],[],[],[\"seq\",[\"vasgn\",\"local\",\"__dt_t100\",[\"se", - "nd\",[\"send\",[\"var\",\"local\",\"other\"],\"class\",[],null],\"==\",[[\"send\",[\"self\"],\"c", - "lass\",[],null]],null]],[\"if\",[\"var\",\"local\",\"__dt_t100\"],[\"send\",[\"var\",\"local\",\"", - "syms\"],\"all?\",[],[\"block\",[[\"preq\",\"s\"]],[],[],[\"send\",[\"send\",null,\"send\",[[\"va", - "r\",\"local\",\"s\"]],null],\"==\",[[\"send\",[\"var\",\"local\",\"other\"],\"send\",[[\"var\",\"", - "local\",\"s\"]],null]],null]]],[\"var\",\"local\",\"__dt_t100\"]]]]],[\"send\",null,\"define_met", - "hod\",[[\"sym\",\"eql?\"]],[\"block\",[[\"preq\",\"other\"]],[],[],[\"send\",[\"self\"],\"==\",[", - "[\"var\",\"local\",\"other\"]],null]]],[\"send\",null,\"define_method\",[[\"sym\",\"each\"]],[\"", - "block\",[[\"pblock\",\"blk\"]],[],[],[\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"blk\"],\"ni", - "l?\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"Enumerator: Struct#each", - " without a block\"]],null]],null],[\"send\",[\"var\",\"local\",\"syms\"],\"each\",[],[\"block\",", - "[[\"preq\",\"s\"]],[],[],[\"send\",[\"var\",\"local\",\"blk\"],\"call\",[[\"send\",null,\"send\"", + "var\",\"local\",\"rep\"],\"nil?\",[],null],\"!\",[],null],[\"return\",[\"send\",null,\"__sub_rep", + "\",[[\"var\",\"local\",\"pat\"],[\"var\",\"local\",\"rep\"]],null]],null],[\"if\",[\"send\",[\"v", + "ar\",\"local\",\"blk\"],\"nil?\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str", + "\",\"String#sub with neither a replacement nor a block\"]],null]],null],[\"vasgn\",\"local\",\"r", + "e\",[\"if\",[\"send\",[\"var\",\"local\",\"pat\"],\"is_a?\",[[\"const\",\"Regexp\"]],null],[\"va", + "r\",\"local\",\"pat\"],[\"send\",[\"const\",\"Regexp\"],\"new\",[[\"send\",[\"const\",\"Regexp\"", + "],\"escape\",[[\"var\",\"local\",\"pat\"]],null]],null]]],[\"vasgn\",\"local\",\"m\",[\"send\",n", + "ull,\"__search_at\",[[\"var\",\"local\",\"re\"],[\"int\",0]],null]],[\"if\",[\"send\",[\"var\",\"", + "local\",\"m\"],\"nil?\",[],null],[\"return\",[\"self\"]],null],[\"vasgn\",\"local\",\"b\",[\"sen", + "d\",[\"var\",\"local\",\"m\"],\"begin\",[[\"int\",0]],null]],[\"vasgn\",\"local\",\"e\",[\"send\"", + ",[\"var\",\"local\",\"m\"],\"end\",[[\"int\",0]],null]],[\"send\",[\"send\",[\"send\",[\"send\",", + "[\"self\"],\"[]\",[[\"int\",0],[\"var\",\"local\",\"b\"]],null],\"to_s\",[],null],\"+\",[[\"send", + "\",[\"send\",[\"var\",\"local\",\"blk\"],\"call\",[[\"send\",[\"var\",\"local\",\"m\"],\"[]\",[[", + "\"int\",0]],null]],null],\"to_s\",[],null]],null],\"+\",[[\"send\",[\"send\",[\"self\"],\"[]\",[", + "[\"var\",\"local\",\"e\"],[\"send\",[\"vcall\",\"length\"],\"-\",[[\"var\",\"local\",\"e\"]],nul", + "l]],null],\"to_s\",[],null]],null]]],[\"def\",\"gsub\",[[\"preq\",\"pat\"],[\"popt\",\"rep\",[\"", + "nil\"]],[\"pblock\",\"blk\"]],[\"seq\",[\"vcall\",\"__match_to_caller\"],[\"if\",[\"send\",[\"se", + "nd\",[\"var\",\"local\",\"rep\"],\"nil?\",[],null],\"!\",[],null],[\"return\",[\"send\",null,\"_", + "_gsub_rep\",[[\"var\",\"local\",\"pat\"],[\"var\",\"local\",\"rep\"]],null]],null],[\"if\",[\"se", + "nd\",[\"var\",\"local\",\"blk\"],\"nil?\",[],null],[\"return\",[\"send\",null,\"__unsupported__\"", + ",[[\"str\",\"String#gsub with neither a replacement nor a block\"]],null]],null],[\"vasgn\",\"lo", + "cal\",\"re\",[\"if\",[\"send\",[\"var\",\"local\",\"pat\"],\"is_a?\",[[\"const\",\"Regexp\"]],nu", + "ll],[\"var\",\"local\",\"pat\"],[\"send\",[\"const\",\"Regexp\"],\"new\",[[\"send\",[\"const\",\"", + "Regexp\"],\"escape\",[[\"var\",\"local\",\"pat\"]],null]],null]]],[\"vasgn\",\"local\",\"out\",[", + "\"str\",\"\"]],[\"vasgn\",\"local\",\"cur\",[\"int\",0]],[\"vasgn\",\"local\",\"last\",[\"nil\"]", + "],[\"vasgn\",\"local\",\"guard\",[\"int\",0]],[\"while\",[\"send\",[\"var\",\"local\",\"guard\"]", + ",\"<=\",[[\"send\",[\"vcall\",\"length\"],\"+\",[[\"int\",1]],null]],null],[\"seq\",[\"vasgn\",\"", + "local\",\"guard\",[\"send\",[\"var\",\"local\",\"guard\"],\"+\",[[\"int\",1]],null]],[\"vasgn\",", + "\"local\",\"m\",[\"send\",null,\"__search_at\",[[\"var\",\"local\",\"re\"],[\"var\",\"local\",\"", + "cur\"]],null]],[\"if\",[\"send\",[\"var\",\"local\",\"m\"],\"nil?\",[],null],[\"break\",null],nu", + "ll],[\"vasgn\",\"local\",\"b\",[\"send\",[\"var\",\"local\",\"m\"],\"begin\",[[\"int\",0]],null]", + "],[\"vasgn\",\"local\",\"e\",[\"send\",[\"var\",\"local\",\"m\"],\"end\",[[\"int\",0]],null]],[\"", + "vasgn\",\"local\",\"last\",[\"var\",\"local\",\"b\"]],[\"vasgn\",\"local\",\"out\",[\"send\",[\"", + "var\",\"local\",\"out\"],\"+\",[[\"send\",[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"loca", + "l\",\"cur\"],[\"send\",[\"var\",\"local\",\"b\"],\"-\",[[\"var\",\"local\",\"cur\"]],null]],null", + "],\"to_s\",[],null],\"+\",[[\"send\",[\"send\",[\"var\",\"local\",\"blk\"],\"call\",[[\"send\",[", + "\"var\",\"local\",\"m\"],\"[]\",[[\"int\",0]],null]],null],\"to_s\",[],null]],null]],null]],[\"i", + "f\",[\"send\",[\"var\",\"local\",\"e\"],\"==\",[[\"var\",\"local\",\"b\"]],null],[\"seq\",[\"vas", + "gn\",\"local\",\"out\",[\"send\",[\"var\",\"local\",\"out\"],\"+\",[[\"send\",[\"send\",[\"self\"", + "],\"[]\",[[\"var\",\"local\",\"e\"],[\"int\",1]],null],\"to_s\",[],null]],null]],[\"vasgn\",\"lo", + "cal\",\"cur\",[\"send\",[\"var\",\"local\",\"e\"],\"+\",[[\"int\",1]],null]]],[\"vasgn\",\"local", + "\",\"cur\",[\"var\",\"local\",\"e\"]]],[\"if\",[\"send\",[\"var\",\"local\",\"cur\"],\">\",[[\"v", + "call\",\"length\"]],null],[\"break\",null],null]]],[\"if\",[\"send\",[\"var\",\"local\",\"cur\"]", + ",\"<=\",[[\"vcall\",\"length\"]],null],[\"vasgn\",\"local\",\"out\",[\"send\",[\"var\",\"local\"", + ",\"out\"],\"+\",[[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"local\",\"cur\"],[\"send\",[\"", + "vcall\",\"length\"],\"-\",[[\"var\",\"local\",\"cur\"]],null]],null],\"to_s\",[],null]],null]],n", + "ull],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"last\"],\"nil?\",[],null],\"!\",[],null],[", + "\"send\",null,\"__search_at\",[[\"var\",\"local\",\"re\"],[\"var\",\"local\",\"last\"]],null],nu", + "ll],[\"var\",\"local\",\"out\"]]],[\"def\",\"index\",[[\"preq\",\"needle\"],[\"popt\",\"start\",", + "[\"int\",0]]],[\"seq\",[\"vcall\",\"__match_to_caller\"],[\"vasgn\",\"local\",\"i\",[\"if\",[\"s", + "end\",[\"var\",\"local\",\"start\"],\"<\",[[\"int\",0]],null],[\"send\",[\"vcall\",\"length\"],\"", + "+\",[[\"var\",\"local\",\"start\"]],null],[\"var\",\"local\",\"start\"]]],[\"if\",[\"send\",[\"v", + "ar\",\"local\",\"i\"],\"<\",[[\"int\",0]],null],[\"vasgn\",\"local\",\"i\",[\"int\",0]],null],[\"", + "if\",[\"send\",[\"var\",\"local\",\"needle\"],\"is_a?\",[[\"const\",\"Regexp\"]],null],[\"seq\",", + "[\"vasgn\",\"local\",\"m\",[\"send\",null,\"__search_at\",[[\"var\",\"local\",\"needle\"],[\"var", + "\",\"local\",\"i\"]],null]],[\"return\",[\"if\",[\"send\",[\"var\",\"local\",\"m\"],\"nil?\",[],", + "null],[\"nil\"],[\"send\",[\"var\",\"local\",\"m\"],\"begin\",[[\"int\",0]],null]]]],null],[\"va", + "sgn\",\"local\",\"n\",[\"send\",[\"var\",\"local\",\"needle\"],\"length\",[],null]],[\"while\",[", + "\"send\",[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"var\",\"local\",\"n\"]],null],\"<=\",[[\"", + "vcall\",\"length\"]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"lo", + "cal\",\"i\"],[\"var\",\"local\",\"n\"]],null],\"==\",[[\"var\",\"local\",\"needle\"]],null],[\"r", + "eturn\",[\"var\",\"local\",\"i\"]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\"", + ",\"i\"],\"+\",[[\"int\",1]],null]]]],[\"nil\"]]],[\"def\",\"rindex\",[[\"preq\",\"needle\"],[\"p", + "opt\",\"start\",[\"nil\"]]],[\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"needle\"],\"is_a?\",", + "[[\"const\",\"Regexp\"]],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"String", + "#rindex with a Regexp needle\"]],null]],null],[\"vasgn\",\"local\",\"n\",[\"send\",[\"var\",\"lo", + "cal\",\"needle\"],\"length\",[],null]],[\"vasgn\",\"local\",\"i\",[\"if\",[\"send\",[\"var\",\"l", + "ocal\",\"start\"],\"nil?\",[],null],[\"send\",[\"vcall\",\"length\"],\"-\",[[\"var\",\"local\",\"", + "n\"]],null],[\"if\",[\"send\",[\"var\",\"local\",\"start\"],\"<\",[[\"int\",0]],null],[\"send\",", + "[\"vcall\",\"length\"],\"+\",[[\"var\",\"local\",\"start\"]],null],[\"var\",\"local\",\"start\"]", + "]]],[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\">\",[[\"send\",[\"vcall\",\"length\"],\"-\",[[", + "\"var\",\"local\",\"n\"]],null]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"vcall\",\"length\"", + "],\"-\",[[\"var\",\"local\",\"n\"]],null]],null],[\"while\",[\"send\",[\"var\",\"local\",\"i\"],", + "\">=\",[[\"int\",0]],null],[\"seq\",[\"if\",[\"send\",[\"send\",[\"self\"],\"[]\",[[\"var\",\"lo", + "cal\",\"i\"],[\"var\",\"local\",\"n\"]],null],\"==\",[[\"var\",\"local\",\"needle\"]],null],[\"r", + "eturn\",[\"var\",\"local\",\"i\"]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\"", + ",\"i\"],\"-\",[[\"int\",1]],null]]]],[\"nil\"]]],[\"def\",\"each_char\",[],[\"seq\",[\"if\",[\"s", + "end\",[\"send\",null,\"block_given?\",[],null],\"!\",[],null],[\"return\",[\"vcall\",\"to_enum_c", + "hars\"]],null],[\"send\",null,\"__each_char_blk\",[],[\"block\",[[\"preq\",\"c\"]],[],[],[\"yiel", + "d\",[[\"var\",\"local\",\"c\"]]]]]]],[\"def\",\"to_enum_chars\",[],[\"vcall\",\"chars\"]],[\"def", + "\",\"__each_char_blk\",[],[\"seq\",[\"if\",[\"send\",[\"send\",null,\"block_given?\",[],null],\"", + "!\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"Enumerator: String#each_", + "char without a block\"]],null]],null],[\"vasgn\",\"local\",\"i\",[\"int\",0]],[\"while\",[\"send", + "\",[\"var\",\"local\",\"i\"],\"<\",[[\"vcall\",\"length\"]],null],[\"seq\",[\"yield\",[[\"send\"", + ",[\"self\"],\"[]\",[[\"var\",\"local\",\"i\"],[\"int\",1]],null]]],[\"vasgn\",\"local\",\"i\",[\"", + "send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",1]],null]]]],[\"self\"]]],[\"def\",\"partition\"", + ",[[\"preq\",\"sep\"]],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",null,\"index\",[[\"var\",\"l", + "ocal\",\"sep\"]],null]],[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"nil?\",[],null],[\"return\"", + ",[\"array\",[[\"self\"],[\"str\",\"\"],[\"str\",\"\"]]]],null],[\"array\",[[\"send\",[\"self\"],", + "\"[]\",[[\"int\",0],[\"var\",\"local\",\"i\"]],null],[\"var\",\"local\",\"sep\"],[\"send\",[\"se", + "lf\"],\"[]\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"send\",[\"var\",\"local\",\"sep\"],\"", + "length\",[],null]],null],[\"send\",[\"send\",[\"vcall\",\"length\"],\"-\",[[\"var\",\"local\",\"", + "i\"]],null],\"-\",[[\"send\",[\"var\",\"local\",\"sep\"],\"length\",[],null]],null]],null]]]]],[", + "\"def\",\"rpartition\",[[\"preq\",\"sep\"]],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",null,\"", + "rindex\",[[\"var\",\"local\",\"sep\"]],null]],[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"nil?", + "\",[],null],[\"return\",[\"array\",[[\"str\",\"\"],[\"str\",\"\"],[\"self\"]]]],null],[\"array\"", + ",[[\"send\",[\"self\"],\"[]\",[[\"int\",0],[\"var\",\"local\",\"i\"]],null],[\"var\",\"local\",\"", + "sep\"],[\"send\",[\"self\"],\"[]\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"send\",[\"var\"", + ",\"local\",\"sep\"],\"length\",[],null]],null],[\"send\",[\"send\",[\"vcall\",\"length\"],\"-\",", + "[[\"var\",\"local\",\"i\"]],null],\"-\",[[\"send\",[\"var\",\"local\",\"sep\"],\"length\",[],nul", + "l]],null]],null]]]]],[\"def\",\"tr\",[[\"preq\",\"from\"],[\"preq\",\"to\"]],[\"seq\",[\"vasgn\"", + ",\"local\",\"neg\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t88\",[\"send\",[\"var\",\"local\",\"fro", + "m\"],\"start_with?\",[[\"str\",\"^\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t88\"],[\"send\"", + ",[\"send\",[\"var\",\"local\",\"from\"],\"length\",[],null],\">\",[[\"int\",1]],null],[\"var\",\"", + "local\",\"__dt_t88\"]]]],[\"vasgn\",\"local\",\"src\",[\"send\",null,\"__tr_expand\",[[\"if\",[\"", + "var\",\"local\",\"neg\"],[\"send\",[\"var\",\"local\",\"from\"],\"[]\",[[\"int\",1],[\"send\",[\"", + "send\",[\"var\",\"local\",\"from\"],\"length\",[],null],\"-\",[[\"int\",1]],null]],null],[\"var\"", + ",\"local\",\"from\"]]],null]],[\"vasgn\",\"local\",\"dst\",[\"send\",null,\"__tr_expand\",[[\"va", + "r\",\"local\",\"to\"]],null]],[\"vasgn\",\"local\",\"out\",[\"str\",\"\"]],[\"send\",null,\"each", + "_char\",[],[\"block\",[[\"preq\",\"c\"]],[],[\"hit\",\"i\"],[\"seq\",[\"vasgn\",\"local\",\"hit\"", + ",[\"send\",[\"var\",\"local\",\"src\"],\"include?\",[[\"var\",\"local\",\"c\"]],null]],[\"if\",[", + "\"var\",\"local\",\"neg\"],[\"vasgn\",\"local\",\"hit\",[\"send\",[\"var\",\"local\",\"hit\"],\"", + "!\",[],null]],null],[\"if\",[\"send\",[\"var\",\"local\",\"hit\"],\"!\",[],null],[\"vasgn\",\"lo", + "cal\",\"out\",[\"send\",[\"var\",\"local\",\"out\"],\"+\",[[\"var\",\"local\",\"c\"]],null]],[\"", + "if\",[\"send\",[\"var\",\"local\",\"dst\"],\"empty?\",[],null],[\"nil\"],[\"if\",[\"var\",\"loca", + "l\",\"neg\"],[\"vasgn\",\"local\",\"out\",[\"send\",[\"var\",\"local\",\"out\"],\"+\",[[\"send\"", + ",[\"var\",\"local\",\"dst\"],\"[]\",[[\"send\",[\"send\",[\"var\",\"local\",\"dst\"],\"length\",", + "[],null],\"-\",[[\"int\",1]],null]],null]],null]],[\"seq\",[\"vasgn\",\"local\",\"i\",[\"send\",", + "[\"var\",\"local\",\"src\"],\"index\",[[\"var\",\"local\",\"c\"]],null]],[\"vasgn\",\"local\",\"", + "out\",[\"send\",[\"var\",\"local\",\"out\"],\"+\",[[\"if\",[\"send\",[\"var\",\"local\",\"i\"],\"", + "<\",[[\"send\",[\"var\",\"local\",\"dst\"],\"length\",[],null]],null],[\"send\",[\"var\",\"local", + "\",\"dst\"],\"[]\",[[\"var\",\"local\",\"i\"]],null],[\"send\",[\"var\",\"local\",\"dst\"],\"[]\"", + ",[[\"send\",[\"send\",[\"var\",\"local\",\"dst\"],\"length\",[],null],\"-\",[[\"int\",1]],null]]", + ",null]]],null]]]]]]]]],[\"var\",\"local\",\"out\"]]],[\"def\",\"__tr_expand\",[[\"preq\",\"spec\"", + "]],[\"seq\",[\"vasgn\",\"local\",\"out\",[\"array\",[]]],[\"vasgn\",\"local\",\"i\",[\"int\",0]]", + ",[\"while\",[\"send\",[\"var\",\"local\",\"i\"],\"<\",[[\"send\",[\"var\",\"local\",\"spec\"],\"", + "length\",[],null]],null],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t89\",[\"send\",[\"send\",", + "[\"var\",\"local\",\"i\"],\"+\",[[\"int\",2]],null],\"<\",[[\"send\",[\"var\",\"local\",\"spec\"", + "],\"length\",[],null]],null]],[\"if\",[\"var\",\"local\",\"__dt_t89\"],[\"send\",[\"send\",[\"va", + "r\",\"local\",\"spec\"],\"[]\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",1]],null]],n", + "ull],\"==\",[[\"str\",\"-\"]],null],[\"var\",\"local\",\"__dt_t89\"]]],[\"seq\",[\"vasgn\",\"loc", + "al\",\"a\",[\"send\",[\"send\",[\"var\",\"local\",\"spec\"],\"[]\",[[\"var\",\"local\",\"i\"]],n", + "ull],\"ord\",[],null]],[\"vasgn\",\"local\",\"b\",[\"send\",[\"send\",[\"var\",\"local\",\"spec\"", + "],\"[]\",[[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",2]],null]],null],\"ord\",[],null]]", + ",[\"while\",[\"send\",[\"var\",\"local\",\"a\"],\"<=\",[[\"var\",\"local\",\"b\"]],null],[\"seq\"", + ",[\"send\",[\"var\",\"local\",\"out\"],\"push\",[[\"send\",[\"var\",\"local\",\"a\"],\"chr\",[],", + "null]],null],[\"vasgn\",\"local\",\"a\",[\"send\",[\"var\",\"local\",\"a\"],\"+\",[[\"int\",1]],", + "null]]]],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\",3]],null", + "]]],[\"seq\",[\"send\",[\"var\",\"local\",\"out\"],\"push\",[[\"send\",[\"var\",\"local\",\"spec", + "\"],\"[]\",[[\"var\",\"local\",\"i\"]],null]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\"", + ",\"local\",\"i\"],\"+\",[[\"int\",1]],null]]]]],[\"var\",\"local\",\"out\"]]],[\"def\",\"encodin", + "g\",[],[\"seq\",[\"if\",[\"send\",null,\"__binary?\",[],null],[\"return\",[\"cpath\",[\"const\",", + "\"Encoding\"],\"BINARY\"]],null],[\"if\",[\"send\",[\"send\",[\"vcall\",\"__bytes\"],\"all?\",[]", + ",[\"block\",[[\"preq\",\"x\"]],[],[],[\"send\",[\"var\",\"local\",\"x\"],\"<\",[[\"int\",128]],n", + "ull]]],\"!\",[],null],[\"return\",[\"cpath\",[\"const\",\"Encoding\"],\"UTF_8\"]],null],[\"send\"", + ",[\"const\",\"Encoding\"],\"__undetermined\",[],null]]],[\"def\",\"force_encoding\",[[\"preq\",\"", + "enc\"]],[\"seq\",[\"vasgn\",\"local\",\"n\",[\"if\",[\"send\",[\"var\",\"local\",\"enc\"],\"is_a", + "?\",[[\"const\",\"Encoding\"]],null],[\"seq\",[\"vasgn\",\"local\",\"__dt_t90\",[\"send\",[\"var", + "\",\"local\",\"enc\"],\"__name_raw\",[],null]],[\"if\",[\"var\",\"local\",\"__dt_t90\"],[\"var\"", + ",\"local\",\"__dt_t90\"],[\"str\",\"UTF-8\"]]],[\"send\",[\"var\",\"local\",\"enc\"],\"to_s\",[]", + ",null]]],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t94\",[\"seq\",[\"vasgn\",\"local\",\"__dt", + "_t93\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t92\",[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"", + "str\",\"ASCII-8BIT\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t92\"],[\"var\",\"local\",\"__dt", + "_t92\"],[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"str\",\"BINARY\"]],null]]]],[\"if\",[\"va", + "r\",\"local\",\"__dt_t93\"],[\"var\",\"local\",\"__dt_t93\"],[\"send\",[\"var\",\"local\",\"n\"]", + ",\"==\",[[\"str\",\"ascii-8bit\"]],null]]]],[\"if\",[\"var\",\"local\",\"__dt_t94\"],[\"var\",\"", + "local\",\"__dt_t94\"],[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"str\",\"binary\"]],null]]],", + "[\"vcall\",\"__force_binary\"],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t91\",[\"send\",[\"v", + "ar\",\"local\",\"n\"],\"==\",[[\"str\",\"UTF-8\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t91\"", + "],[\"var\",\"local\",\"__dt_t91\"],[\"send\",[\"var\",\"local\",\"n\"],\"==\",[[\"str\",\"utf-8\"", + "]],null]]],[\"vcall\",\"__force_utf8\"],[\"send\",null,\"__unsupported__\",[[\"send\",[\"str\",\"", + "String#force_encoding to \"],\"+\",[[\"var\",\"local\",\"n\"]],null]],null]]]]],[\"def\",\"bytes", + "\",[],[\"vcall\",\"__bytes\"]],[\"def\",\"each_byte\",[],[\"seq\",[\"if\",[\"send\",[\"send\",nu", + "ll,\"block_given?\",[],null],\"!\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"s", + "tr\",\"Enumerator: String#each_byte without a block\"]],null]],null],[\"send\",[\"vcall\",\"__by", + "tes\"],\"each\",[],[\"block\",[[\"preq\",\"x\"]],[],[],[\"yield\",[[\"var\",\"local\",\"x\"]]]]]", + ",[\"self\"]]]]],[\"class\",\"Encoding\",null,[\"seq\",[\"def\",\"initialize\",[[\"preq\",\"name\"", + "]],[\"vasgn\",\"ivar\",\"@name\",[\"var\",\"local\",\"name\"]]],[\"def\",\"__name_raw\",[],[\"va", + "r\",\"ivar\",\"@name\"]],[\"def\",\"__gate\",[],[\"send\",null,\"__unsupported__\",[[\"str\",\"E", + "ncoding of an ASCII-only String (US-ASCII vs UTF-8 is not tracked)\"]],null]],[\"def\",\"name\",", + "[],[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"nil?\",[],null],[\"vcall\",\"__gate\"],[\"va", + "r\",\"ivar\",\"@name\"]]],[\"def\",\"to_s\",[],[\"vcall\",\"name\"]],[\"def\",\"inspect\",[],[\"", + "seq\",[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"nil?\",[],null],[\"return\",[\"vcall\",\"", + "__gate\"]],null],[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"==\",[[\"str\",\"UTF-8\"]],nul", + "l],[\"str\",\"#\"],[\"str\",\"#\"]]]],[\"def\",\"=", + "=\",[[\"preq\",\"other\"]],[\"seq\",[\"if\",[\"send\",[\"var\",\"ivar\",\"@name\"],\"nil?\",[],n", + "ull],[\"return\",[\"vcall\",\"__gate\"]],null],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"", + "other\"],\"is_a?\",[[\"const\",\"Encoding\"]],null],\"!\",[],null],[\"return\",[\"false\"]],null", + "],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"other\"],\"__name_raw\",[],null],\"nil?\",[],", + "null],[\"return\",[\"send\",[\"var\",\"local\",\"other\"],\"__gate\",[],null]],null],[\"send\",[", + "\"send\",[\"var\",\"local\",\"other\"],\"__name_raw\",[],null],\"==\",[[\"var\",\"ivar\",\"@name", + "\"]],null]]],[\"def\",\"eql?\",[[\"preq\",\"other\"]],[\"send\",[\"self\"],\"==\",[[\"var\",\"lo", + "cal\",\"other\"]],null]],[\"casgn\",\"UTF_8\",[\"send\",null,\"new\",[[\"str\",\"UTF-8\"]],null]", + "],[\"casgn\",\"BINARY\",[\"send\",null,\"new\",[[\"str\",\"ASCII-8BIT\"]],null]],[\"casgn\",\"AS", + "CII_8BIT\",[\"const\",\"BINARY\"]],[\"casgn\",\"UNDETERMINED\",[\"send\",null,\"new\",[[\"nil\"]", + "],null]],[\"defs\",[\"self\"],\"__undetermined\",[],[\"const\",\"UNDETERMINED\"]]]],[\"class\",\"", + "Struct\",null,[\"defs\",[\"self\"],\"new\",[[\"prest\",\"names\"],[\"pkey\",\"keyword_init\",[\"", + "nil\"]],[\"pblock\",\"body\"]],[\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"names\"],\"empty?", + "\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"Struct.new with no member", + "s\"]],null]],null],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"names\"],\"[]\",[[\"int\",0]", + "],null],\"is_a?\",[[\"const\",\"String\"]],null],[\"return\",[\"send\",null,\"__unsupported__\",", + "[[\"str\",\"Struct.new(\\\"Name\\\") (named struct constant)\"]],null]],null],[\"vasgn\",\"local", + "\",\"syms\",[\"send\",[\"var\",\"local\",\"names\"],\"map\",[],[\"block\",[[\"preq\",\"n\"]],[],", + "[],[\"send\",[\"var\",\"local\",\"n\"],\"to_sym\",[],null]]]],[\"vasgn\",\"local\",\"kwi\",[\"va", + "r\",\"local\",\"keyword_init\"]],[\"vasgn\",\"local\",\"cls\",[\"send\",[\"const\",\"Class\"],\"", + "new\",[],null]],[\"send\",[\"var\",\"local\",\"cls\"],\"class_eval\",[],[\"block\",[],[],[],[\"s", + "eq\",[\"send\",null,\"define_singleton_method\",[[\"sym\",\"members\"]],[\"block\",[],[],[],[\"s", + "end\",[\"var\",\"local\",\"syms\"],\"dup\",[],null]]],[\"send\",null,\"define_method\",[[\"sym\"", + ",\"members\"]],[\"block\",[],[],[],[\"send\",[\"var\",\"local\",\"syms\"],\"dup\",[],null]]],[\"", + "send\",null,\"define_method\",[[\"sym\",\"initialize\"]],[\"block\",[[\"prest\",\"a\"],[\"pkwres", + "t\",\"kw\"]],[],[\"bad\",\"i\"],[\"seq\",[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t97\",[\"s", + "end\",[\"var\",\"local\",\"kwi\"],\"==\",[[\"true\"]],null]],[\"if\",[\"var\",\"local\",\"__dt_t", + "97\"],[\"var\",\"local\",\"__dt_t97\"],[\"seq\",[\"vasgn\",\"local\",\"__dt_t96\",[\"seq\",[\"va", + "sgn\",\"local\",\"__dt_t95\",[\"send\",[\"var\",\"local\",\"kwi\"],\"nil?\",[],null]],[\"if\",[\"", + "var\",\"local\",\"__dt_t95\"],[\"send\",[\"var\",\"local\",\"a\"],\"empty?\",[],null],[\"var\",\"", + "local\",\"__dt_t95\"]]]],[\"if\",[\"var\",\"local\",\"__dt_t96\"],[\"send\",[\"send\",[\"var\",\"", + "local\",\"kw\"],\"empty?\",[],null],\"!\",[],null],[\"var\",\"local\",\"__dt_t96\"]]]]],[\"seq\"", + ",[\"vasgn\",\"local\",\"bad\",[\"send\",[\"send\",[\"var\",\"local\",\"kw\"],\"keys\",[],null],\"", + "reject\",[],[\"block\",[[\"preq\",\"k\"]],[],[],[\"send\",[\"var\",\"local\",\"syms\"],\"include", + "?\",[[\"var\",\"local\",\"k\"]],null]]]],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"bad\"]", + ",\"empty?\",[],null],\"!\",[],null],[\"send\",null,\"raise\",[[\"const\",\"ArgumentError\"],[\"s", + "end\",[\"str\",\"unknown keywords: \"],\"+\",[[\"send\",[\"send\",[\"var\",\"local\",\"bad\"],\"", + "map\",[],[\"block\",[[\"preq\",\"k\"]],[],[],[\"send\",[\"var\",\"local\",\"k\"],\"inspect\",[],", + "null]]],\"join\",[[\"str\",\", \"]],null]],null]],null],null],[\"send\",[\"var\",\"local\",\"sym", + "s\"],\"each\",[],[\"block\",[[\"preq\",\"s\"]],[],[],[\"send\",null,\"instance_variable_set\",[[", + "\"send\",[\"str\",\"@\"],\"+\",[[\"send\",[\"var\",\"local\",\"s\"],\"to_s\",[],null]],null],[\"", + "send\",[\"var\",\"local\",\"kw\"],\"[]\",[[\"var\",\"local\",\"s\"]],null]],null]]]],[\"seq\",[\"", + "if\",[\"send\",[\"send\",[\"var\",\"local\",\"a\"],\"length\",[],null],\">\",[[\"send\",[\"var\"", + ",\"local\",\"syms\"],\"length\",[],null]],null],[\"send\",null,\"raise\",[[\"const\",\"ArgumentE", + "rror\"],[\"str\",\"struct size differs\"]],null],null],[\"vasgn\",\"local\",\"i\",[\"int\",0]],[", + "\"while\",[\"send\",[\"var\",\"local\",\"i\"],\"<\",[[\"send\",[\"var\",\"local\",\"syms\"],\"le", + "ngth\",[],null]],null],[\"seq\",[\"send\",null,\"instance_variable_set\",[[\"send\",[\"str\",\"@", + "\"],\"+\",[[\"send\",[\"send\",[\"var\",\"local\",\"syms\"],\"[]\",[[\"var\",\"local\",\"i\"]],n", + "ull],\"to_s\",[],null]],null],[\"send\",[\"var\",\"local\",\"a\"],\"[]\",[[\"var\",\"local\",\"i", + "\"]],null]],null],[\"vasgn\",\"local\",\"i\",[\"send\",[\"var\",\"local\",\"i\"],\"+\",[[\"int\"", + ",1]],null]]]]]],[\"nil\"]]]],[\"send\",[\"var\",\"local\",\"syms\"],\"each\",[],[\"block\",[[\"p", + "req\",\"s\"]],[],[],[\"seq\",[\"send\",null,\"define_method\",[[\"var\",\"local\",\"s\"]],[\"blo", + "ck\",[],[],[],[\"send\",null,\"instance_variable_get\",[[\"send\",[\"str\",\"@\"],\"+\",[[\"send", + "\",[\"var\",\"local\",\"s\"],\"to_s\",[],null]],null]],null]]],[\"send\",null,\"define_method\",", + "[[\"send\",[\"send\",[\"var\",\"local\",\"s\"],\"to_s\",[],null],\"+\",[[\"str\",\"=\"]],null]],", + "[\"block\",[[\"preq\",\"v\"]],[],[],[\"send\",null,\"instance_variable_set\",[[\"send\",[\"str\"", + ",\"@\"],\"+\",[[\"send\",[\"var\",\"local\",\"s\"],\"to_s\",[],null]],null],[\"var\",\"local\",\"", + "v\"]],null]]]]]],[\"send\",null,\"define_method\",[[\"sym\",\"to_a\"]],[\"block\",[],[],[],[\"se", + "nd\",[\"var\",\"local\",\"syms\"],\"map\",[],[\"block\",[[\"preq\",\"s\"]],[],[],[\"send\",null,", + "\"send\",[[\"var\",\"local\",\"s\"]],null]]]]],[\"send\",null,\"define_method\",[[\"sym\",\"deco", + "nstruct\"]],[\"block\",[],[],[],[\"send\",[\"var\",\"local\",\"syms\"],\"map\",[],[\"block\",[[\"", + "preq\",\"s\"]],[],[],[\"send\",null,\"send\",[[\"var\",\"local\",\"s\"]],null]]]]],[\"send\",nul", + "l,\"define_method\",[[\"sym\",\"to_h\"]],[\"block\",[],[],[\"h\"],[\"seq\",[\"vasgn\",\"local\",", + "\"h\",[\"hash\",[]]],[\"send\",[\"var\",\"local\",\"syms\"],\"each\",[],[\"block\",[[\"preq\",\"", + "s\"]],[],[],[\"seq\",[\"send\",[\"var\",\"local\",\"h\"],\"[]=\",[[\"var\",\"local\",\"s\"],[\"v", + "asgn\",\"local\",\"__dt_t98\",[\"send\",null,\"send\",[[\"var\",\"local\",\"s\"]],null]]],null],", + "[\"var\",\"local\",\"__dt_t98\"]]]],[\"var\",\"local\",\"h\"]]]],[\"send\",null,\"define_method\"", + ",[[\"sym\",\"[]\"]],[\"block\",[[\"preq\",\"k\"]],[],[\"i\",\"key\"],[\"if\",[\"send\",[\"var\",", + "\"local\",\"k\"],\"is_a?\",[[\"const\",\"Integer\"]],null],[\"seq\",[\"vasgn\",\"local\",\"i\",[", + "\"if\",[\"send\",[\"var\",\"local\",\"k\"],\"<\",[[\"int\",0]],null],[\"send\",[\"send\",[\"var\"", + ",\"local\",\"syms\"],\"length\",[],null],\"+\",[[\"var\",\"local\",\"k\"]],null],[\"var\",\"loca", + "l\",\"k\"]]],[\"if\",[\"seq\",[\"vasgn\",\"local\",\"__dt_t99\",[\"send\",[\"var\",\"local\",\"i", + "\"],\"<\",[[\"int\",0]],null]],[\"if\",[\"var\",\"local\",\"__dt_t99\"],[\"var\",\"local\",\"__d", + "t_t99\"],[\"send\",[\"var\",\"local\",\"i\"],\">=\",[[\"send\",[\"var\",\"local\",\"syms\"],\"le", + "ngth\",[],null]],null]]],[\"send\",null,\"raise\",[[\"const\",\"IndexError\"],[\"send\",[\"send\"", + ",[\"send\",[\"send\",[\"str\",\"offset \"],\"+\",[[\"send\",[\"var\",\"local\",\"k\"],\"to_s\",[", + "],null]],null],\"+\",[[\"str\",\" too large for struct(size:\"]],null],\"+\",[[\"send\",[\"send\"", + ",[\"var\",\"local\",\"syms\"],\"length\",[],null],\"to_s\",[],null]],null],\"+\",[[\"str\",\")\"", + "]],null]],null],null],[\"send\",null,\"send\",[[\"send\",[\"var\",\"local\",\"syms\"],\"[]\",[[\"", + "var\",\"local\",\"i\"]],null]],null]],[\"seq\",[\"vasgn\",\"local\",\"key\",[\"send\",[\"var\",\"", + "local\",\"k\"],\"to_sym\",[],null]],[\"if\",[\"send\",[\"send\",[\"var\",\"local\",\"syms\"],\"i", + "nclude?\",[[\"var\",\"local\",\"key\"]],null],\"!\",[],null],[\"send\",null,\"raise\",[[\"const\"", + ",\"NameError\"],[\"send\",[\"send\",[\"str\",\"no member '\"],\"+\",[[\"send\",[\"var\",\"local\"", + ",\"k\"],\"to_s\",[],null]],null],\"+\",[[\"str\",\"' in struct\"]],null]],null],null],[\"send\",", + "null,\"send\",[[\"var\",\"local\",\"key\"]],null]]]]],[\"send\",null,\"define_method\",[[\"sym\"", + ",\"==\"]],[\"block\",[[\"preq\",\"other\"]],[],[],[\"seq\",[\"vasgn\",\"local\",\"__dt_t100\",[\"", + "send\",[\"send\",[\"var\",\"local\",\"other\"],\"class\",[],null],\"==\",[[\"send\",[\"self\"],\"", + "class\",[],null]],null]],[\"if\",[\"var\",\"local\",\"__dt_t100\"],[\"send\",[\"var\",\"local\",", + "\"syms\"],\"all?\",[],[\"block\",[[\"preq\",\"s\"]],[],[],[\"send\",[\"send\",null,\"send\",[[\"", + "var\",\"local\",\"s\"]],null],\"==\",[[\"send\",[\"var\",\"local\",\"other\"],\"send\",[[\"var\"", + ",\"local\",\"s\"]],null]],null]]],[\"var\",\"local\",\"__dt_t100\"]]]]],[\"send\",null,\"define_", + "method\",[[\"sym\",\"eql?\"]],[\"block\",[[\"preq\",\"other\"]],[],[],[\"send\",[\"self\"],\"==\"", + ",[[\"var\",\"local\",\"other\"]],null]]],[\"send\",null,\"define_method\",[[\"sym\",\"each\"]],[", + "\"block\",[[\"pblock\",\"blk\"]],[],[],[\"seq\",[\"if\",[\"send\",[\"var\",\"local\",\"blk\"],\"", + "nil?\",[],null],[\"return\",[\"send\",null,\"__unsupported__\",[[\"str\",\"Enumerator: Struct#ea", + "ch without a block\"]],null]],null],[\"send\",[\"var\",\"local\",\"syms\"],\"each\",[],[\"block\"", + ",[[\"preq\",\"s\"]],[],[],[\"send\",[\"var\",\"local\",\"blk\"],\"call\",[[\"send\",null,\"send\"", ",[[\"var\",\"local\",\"s\"]],null]],null]]],[\"self\"]]]],[\"send\",null,\"define_method\",[[\"s", "ym\",\"size\"]],[\"block\",[],[],[],[\"send\",[\"var\",\"local\",\"syms\"],\"length\",[],null]]]", ",[\"send\",null,\"define_method\",[[\"sym\",\"length\"]],[\"block\",[],[],[],[\"send\",[\"var\",", diff --git a/ruby-lean/RubyCore/Heap.lean b/ruby-lean/RubyCore/Heap.lean index 1fc97025..0c32782b 100644 --- a/ruby-lean/RubyCore/Heap.lean +++ b/ruby-lean/RubyCore/Heap.lean @@ -240,6 +240,19 @@ inductive Payload where offsets throughout, matching Ruby. -/ | mdata (subject : String) (caps : Array (Option (Nat × Nat))) (names : List (String × Nat)) + /-- A **regular file** in the virtual filesystem (issue #7, step 1). `bytes` + are the file's contents; a non-UTF-8 file reproduces CRuby's `inspect` + through the same `binary` tag a String uses, or gates under the L118 net. + Files are ordinary heap objects so `frozen`, `dup`, `inspect` and `is_a?` + apply to them for free (artifact 01). Descriptors arrive in step 2; at + step 1 the payload is pure data. -/ + | file (bytes : String) + /-- A **directory** in the virtual filesystem (issue #7, step 1). `entries` + maps a child's basename to its `ObjId`, in the boot-sorted order CRuby's + `Dir.entries` reports; `parent` gives `..` one definition (the root's is + `none`) rather than a textual collapse. A directory and a file are + distinguished by payload, never by a string convention. -/ + | dir (entries : List (String × ObjId)) (parent : Option ObjId) deriving Inhabited /-- A Hash's default for missing keys: `Hash.new(v)` stores a static value `val v`; @@ -370,10 +383,21 @@ def complexId : ObjId := 40 def enumeratorId : ObjId := 41 def generatorId : ObjId := 42 def yielderId : ObjId := 43 +/-- `IO` — base class of file-like objects (issue #7 step 1). Registered so the + lookup trichotomy stays accurate: a class that exists but whose descriptors + are unmodeled must *gate* on the operation, not answer `NoMethodError`. + (`File < IO`; descriptors themselves land in step 2.) -/ +def ioId : ObjId := 44 +/-- `File < IO` (issue #7 step 1) — where `File.read/write/exist?/file?/ + directory?/size` are installed. -/ +def fileId : ObjId := 45 +/-- `Dir` (issue #7 step 1) — the directory-listing class. `Dir.entries` is + step 3; the class exists now so `Dir` in program text resolves to it. -/ +def dirId : ObjId := 46 /-- Toplevel self (`main`), an ordinary Object instance. **Must stay last**: `initHeap` allocates every `classTable` entry densely and then `main`, so `mainId = classTable.length`. Adding a bootstrap class means bumping this. -/ -def mainId : ObjId := 44 +def mainId : ObjId := 47 /-- (id, name, superclass) for every bootstrap class, in id order. -/ def classTable : List (ObjId × String × Option ObjId) := [ @@ -420,9 +444,39 @@ def classTable : List (ObjId × String × Option ObjId) := [ (complexId, "Complex", some numericId), (enumeratorId, "Enumerator", some objectId), (generatorId, "Enumerator::Generator", some objectId), - (yielderId, "Enumerator::Yielder", some objectId) + (yielderId, "Enumerator::Yielder", some objectId), + (ioId, "IO", some objectId), + (fileId, "File", some ioId), + (dirId, "Dir", some objectId) ] +/-! ### The virtual filesystem fixture (issue #7 step 1) + +The symbolic filesystem is **initial heap data H₀′**, not ambient OS state: a +small directory tree allocated at boot, exactly like the metaclass knot. The +interpreter never reaches outside the pure machine to read a file — it walks +this tree. Whether the tree would instead come from a directory snapshot is a +boot parameter (issue #7), not a runtime effect. + +The fixture is allocated **after** main and the two realized eigenclasses, so +every fixed id (`classTable`, `mainId`) is unmoved. Its base is derived from the +class count rather than pinned: `classTable.length` classes, then `main`, then +the two eigenclasses of `BasicObject`/`Object` that `initHeap` realizes. A new +bootstrap class therefore shifts the fixture ids automatically and keeps +`resolve` pointing at the tree `initHeap` actually built. -/ +def vfsBase : ObjId := classTable.length + 3 +/-- `/tmp/readme.txt` — a regular file. -/ +def vfsReadmeId : ObjId := vfsBase +/-- `/tmp/vfsdata/nums.txt` — a regular file in a subdirectory. -/ +def vfsNumsId : ObjId := vfsBase + 1 +/-- `/tmp/vfsdata` — a directory. -/ +def vfsDataId : ObjId := vfsBase + 2 +/-- `/tmp` — a directory under the root. A real, writable absolute path, so a + differential harness can materialize the identical tree for CRuby. -/ +def vfsTmpId : ObjId := vfsBase + 3 +/-- `/` — the fixture root. Absolute paths resolve from here. -/ +def vfsRootId : ObjId := vfsBase + 4 + /-- Builtin method table: class id → method names given by primitive rules. Builtin bid = "ClassName#name". Registered into each class's `methods` so lookup (incl. inheritance) is uniform. -/ @@ -504,7 +558,10 @@ def builtinMethods : List (ObjId × List String) := [ "to_s", "names", "==", "eql?", "hash"]), (matchDataId, ["[]", "captures", "named_captures", "names", "begin", "end", "pre_match", "post_match", "to_a", "size", "length", "to_s", - "inspect", "values_at"]) + "inspect", "values_at"]), + (ioId, ["read", "write", "closed?", "close", "flush", "each_line", "gets"]), + (fileId, ["read", "write", "exist?", "file?", "directory?", "size", "open"]), + (dirId, ["exist?", "entries", "children", "mkdir"]) ] def mkClassObj (name : String) (sup : Option ObjId) : Object := @@ -611,8 +668,27 @@ def initHeap : Heap := { klass := classId, payload := .cls { superclass := some eB, name := "", attached := some objectId, isModule := false } }).2 - hE.set objectId { hE.get objectId with eigen := some eO } - + let hE := hE.set objectId { hE.get objectId with eigen := some eO } + -- The VFS fixture, allocated in the order `vfsReadmeId`, `vfsNumsId`, + -- `vfsDataId`, `vfsTmpId`, `vfsRootId` name, children before parents. Parents + -- are patched in where the id is already known. + let hV := (hE.alloc { klass := fileId, payload := .file "hello\n" }).2 + let hV := (hV.alloc + { klass := fileId, payload := .file "1\n2\n3\n" }).2 + let hV := (hV.alloc + { klass := dirId, payload := .dir [("nums.txt", vfsNumsId)] (some vfsTmpId) }).2 + let hV := (hV.alloc + { klass := dirId, + payload := .dir [("readme.txt", vfsReadmeId), ("vfsdata", vfsDataId)] (some vfsRootId) }).2 + (hV.alloc + { klass := dirId, payload := .dir [("tmp", vfsTmpId)] none }).2 + +/- Drift guard: `vfsBase` is derived from `classTable.length`, so a new bootstrap + class shifts the fixture ids automatically. The one remaining way to break + resolution is to reorder the fixture allocations above without updating the + `vfs*Id` names; `resolve` would then walk the wrong object. The differential + fixtures exercise each path, so that shows up as a disagreement rather than + silently. -/ end Boot /-! ## Pure object-model operations (Semantics 01 §4, 02 §1–2) -/ @@ -635,6 +711,54 @@ def realClassOf (h : Heap) : Value → ObjId | .ref o => (h.get o).klass | v => classOf h v +/-! ## Virtual filesystem (issue #7 step 1) + +One definition of path resolution, walked from a `cwd`. At step 1 the `cwd` is +fixed at the fixture root, so only absolute paths are resolved; relative paths +and `Dir.chdir` arrive with the per-execution `cwd` (issue #7 open question 2). +The walk splits on `/`, ignores empty components and `.`, and treats `..` by the +stored tree — so `.`/`..`/trailing slashes have exactly one rule. + +Resolution is pure and total: it returns `Option ObjId`, and the builtins turn a +missing path into a named `Unsupported` (an unimplemented operation is never a +guessed answer or a fake `Errno`). -/ + +namespace VFS + +/-- Normalize an absolute path into its non-empty, non-`.` components. `..` + is kept and resolved during the walk (there is no textual collapse, so a + symlink-free tree resolves it exactly). -/ +def components (s : String) : List String := + (s.splitOn "/").filter (fun c => c != "" && c != ".") + +/-- Resolve `comps` from directory `dir`. A `dir` payload is the only thing that + can hold children; anything else stops the walk (`none`). `..` climbs to the + stored parent (staying put at the root, whose parent is `none`). -/ +def walk (h : Heap) (dir : ObjId) : List String → Option ObjId + | [] => some dir + | c :: rest => + match (h.get dir).payload with + | .dir entries parent => + if c == ".." then + match parent with + | some p => walk h p rest + | none => walk h dir rest + else match entries.find? (fun p => p.1 == c) with + | some (_, child) => walk h child rest + | none => none + | _ => none + +/-- Resolve an absolute path from the fixture root. A path that is not absolute + (`""` or not starting with `/`) resolves to `none`: relative paths are not + in the step-1 fragment. -/ +def resolve (h : Heap) (path : String) : Option ObjId := + if path.startsWith "/" then walk h Boot.vfsRootId (components path) else none + +/-- The `ObjId` a path names, if it exists. -/ +def lookup (h : Heap) (path : String) : Option ObjId := resolve h path + +end VFS + /-- A module's own ancestor list: itself, then its `include`d modules (most-recent first), recursively. diff --git a/ruby-lean/RubyCore/Repr.lean b/ruby-lean/RubyCore/Repr.lean index 3b0e74f7..6e919e3e 100644 --- a/ruby-lean/RubyCore/Repr.lean +++ b/ruby-lean/RubyCore/Repr.lean @@ -298,6 +298,12 @@ def inspectFuel : Nat → Heap → Value → Except String String | none => "nil") return "#" + | .file _ | .dir _ _ => + -- A VFS file/directory object never reaches `inspect` at step 1 (the + -- `File.*`/`Dir.*` singleton methods return String/Integer/Bool, never the + -- object itself), and CRuby's rendering carries the path, which the + -- payload deliberately does not. Gate rather than guess. + throw "inspect of a VFS file/directory object (issue #7 step 1)" | .none | .rng _ | .generator _ | .yielder .. => let cname := className h (h.get o).klass let ivars := (h.get o).ivars.reverse @@ -346,6 +352,8 @@ def toSFuel : Nat → Heap → Value → Except String String if (h.get o).binary && hasHighByte whole then throw "MatchData#to_s over a byte-string subject with a byte ≥ 0x80" else return whole + | .file _ | .dir _ _ => + throw "to_s of a VFS file/directory object (issue #7 step 1)" | .none | .rng _ => let cname := className h (h.get o).klass return s!"#<{cname}:{fakeAddr o}>" diff --git a/ruby-lean/RubyCore/Trace.lean b/ruby-lean/RubyCore/Trace.lean index 89563ce9..0e147eec 100644 --- a/ruby-lean/RubyCore/Trace.lean +++ b/ruby-lean/RubyCore/Trace.lean @@ -43,6 +43,8 @@ partial def valBrief (h : Heap) : Nat → Value → String | .chain _ => "#" | .generator _ => "#" | .yielder .. => "#" + | .file b => s!"#" + | .dir es _ => s!"#" /-- One-line head label for the expression about to be evaluated. -/ def exprBrief : Expr → String diff --git a/ruby-lean/prelude/prelude.rb b/ruby-lean/prelude/prelude.rb index fafa3f75..567903e8 100644 --- a/ruby-lean/prelude/prelude.rb +++ b/ruby-lean/prelude/prelude.rb @@ -2078,7 +2078,7 @@ def Pathname(arg) # and gates by name. Defining the constant without that guard would turn # `File.read` from an honest Unsupported into a NoMethodError, which is a wrong # answer rather than a refusal. -module File +class File SEPARATOR = "/" def self.basename(path, suffix = nil)