mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-13 01:28:40 +00:00
73 lines
2.9 KiB
Forth
73 lines
2.9 KiB
Forth
namespace WoofWare.PawPrint
|
|
|
|
open System.Reflection
|
|
|
|
[<RequireQualifiedAccess>]
|
|
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
|
module internal UnaryStringTokenIlOp =
|
|
let execute
|
|
(baseClassTypes : BaseClassTypes<'a>)
|
|
(op : UnaryStringTokenIlOp)
|
|
(sh : StringToken)
|
|
(state : IlMachineState)
|
|
(thread : ThreadId)
|
|
: IlMachineState * WhatWeDid
|
|
=
|
|
match op with
|
|
| UnaryStringTokenIlOp.Ldstr ->
|
|
let addressToLoad, state =
|
|
match state.InternedStrings.TryGetValue sh with
|
|
| false, _ ->
|
|
let stringToAllocate = state.ActiveAssembly(thread).Strings sh
|
|
|
|
let dataAddr, state =
|
|
IlMachineState.allocateStringData stringToAllocate.Length state
|
|
|
|
let state = state |> IlMachineState.setStringData dataAddr stringToAllocate
|
|
|
|
let stringInstanceFields =
|
|
baseClassTypes.String.Fields
|
|
|> List.choose (fun field ->
|
|
if int (field.Attributes &&& FieldAttributes.Static) = 0 then
|
|
Some (field.Name, field.Signature)
|
|
else
|
|
None
|
|
)
|
|
|> List.sortBy fst
|
|
// Assert that the string type has the fields we expect
|
|
if
|
|
stringInstanceFields
|
|
<> [
|
|
("_firstChar", TypeDefn.PrimitiveType PrimitiveType.Char)
|
|
("_stringLength", TypeDefn.PrimitiveType PrimitiveType.Int32)
|
|
]
|
|
then
|
|
failwith
|
|
$"unexpectedly don't know how to initialise a string: got fields %O{stringInstanceFields}"
|
|
|
|
let fields =
|
|
[
|
|
"_firstChar", CliType.OfChar state.ManagedHeap.StringArrayData.[dataAddr]
|
|
"_stringLength", CliType.Numeric (CliNumericType.Int32 stringToAllocate.Length)
|
|
]
|
|
|
|
let addr, state =
|
|
IlMachineState.allocateManagedObject
|
|
(baseClassTypes.String
|
|
|> TypeInfo.mapGeneric (fun _ _ -> failwith<unit> "string is not generic"))
|
|
fields
|
|
state
|
|
|
|
addr,
|
|
{ state with
|
|
InternedStrings = state.InternedStrings.Add (sh, addr)
|
|
}
|
|
| true, v -> v, state
|
|
|
|
let state =
|
|
IlMachineState.pushToEvalStack (CliType.ObjectRef (Some addressToLoad)) thread state
|
|
|
|
state
|
|
|> IlMachineState.advanceProgramCounter thread
|
|
|> Tuple.withRight WhatWeDid.Executed
|