mirror of
https://github.com/Smaug123/WoofWare.PawPrint
synced 2025-10-06 06:28:39 +00:00
Delegates (#50)
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace HelloWorldApp
|
||||
{
|
||||
@@ -8,18 +7,12 @@ namespace HelloWorldApp
|
||||
{
|
||||
static int Main(string[] args)
|
||||
{
|
||||
object locker = new object();
|
||||
bool lockTaken = false;
|
||||
try
|
||||
{
|
||||
Monitor.Enter(locker, ref lockTaken);
|
||||
return 1;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (lockTaken)
|
||||
Monitor.Exit(locker);
|
||||
}
|
||||
var l = new List<int>();
|
||||
l.Add(3);
|
||||
l.Add(100);
|
||||
var m = l.Select(x => x.ToString()).ToList();
|
||||
// 2 + 103 + (1 + 3) = 109
|
||||
return m.Count + l.Sum() + m.Select(x => x.Length).Sum();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -37,8 +37,17 @@ module AbstractMachine =
|
||||
targetAssy.Name
|
||||
targetType.BaseType
|
||||
|
||||
match baseType with
|
||||
| ResolvedBaseType.Delegate -> failwith "TODO: need to generate code for delegates"
|
||||
match baseType, instruction.ReturnState with
|
||||
| ResolvedBaseType.Delegate,
|
||||
Some {
|
||||
WasConstructingObj = Some _
|
||||
} ->
|
||||
IlMachineState.executeDelegateConstructor instruction state
|
||||
// can't advance the program counter here - there's no IL instructions executing!
|
||||
|> IlMachineState.returnStackFrame loggerFactory baseClassTypes thread
|
||||
|> Option.get
|
||||
|> Tuple.withRight WhatWeDid.Executed
|
||||
|> ExecutionResult.Stepped
|
||||
| _ ->
|
||||
|
||||
let outcome =
|
||||
|
@@ -63,7 +63,7 @@ type EvalStackValue =
|
||||
| EvalStackValue.Int64 i -> $"Int64(%i{i})"
|
||||
| EvalStackValue.NativeInt src -> $"NativeInt(%O{src})"
|
||||
| EvalStackValue.Float f -> $"Float(%f{f})"
|
||||
| EvalStackValue.ManagedPointer managedPointerSource -> failwith "todo"
|
||||
| EvalStackValue.ManagedPointer managedPointerSource -> $"Pointer(%O{managedPointerSource})"
|
||||
| EvalStackValue.ObjectRef managedHeapAddress -> $"ObjectRef(%O{managedHeapAddress})"
|
||||
| EvalStackValue.UserDefinedValueType evalStackValues -> failwith "todo"
|
||||
|
||||
|
@@ -1149,3 +1149,46 @@ module IlMachineState =
|
||||
|
||||
let getSyncBlock (addr : ManagedHeapAddress) (state : IlMachineState) : SyncBlock =
|
||||
state.ManagedHeap |> ManagedHeap.GetSyncBlock addr
|
||||
|
||||
let executeDelegateConstructor (instruction : MethodState) (state : IlMachineState) : IlMachineState =
|
||||
// We've been called with arguments already popped from the stack into local arguments.
|
||||
let constructing = instruction.Arguments.[2]
|
||||
let methodPtr = instruction.Arguments.[1]
|
||||
let targetObj = instruction.Arguments.[0]
|
||||
|
||||
let targetObj =
|
||||
match targetObj with
|
||||
| CliType.ObjectRef target -> target
|
||||
| _ -> failwith $"Unexpected target type for delegate: {targetObj}"
|
||||
|
||||
let constructing =
|
||||
match constructing with
|
||||
| CliType.ObjectRef None -> failwith "unexpectedly constructing the null delegate"
|
||||
| CliType.ObjectRef (Some target) -> target
|
||||
| _ -> failwith $"Unexpectedly not constructing a managed object: {constructing}"
|
||||
|
||||
let heapObj =
|
||||
match state.ManagedHeap.NonArrayObjects.TryGetValue constructing with
|
||||
| true, obj -> obj
|
||||
| false, _ -> failwith $"Delegate object {constructing} not found on heap"
|
||||
|
||||
// Standard delegate fields in .NET are _target and _methodPtr
|
||||
// Update the fields with the target object and method pointer
|
||||
let updatedFields =
|
||||
heapObj.Fields
|
||||
|> Map.add "_target" (CliType.ObjectRef targetObj)
|
||||
|> Map.add "_methodPtr" methodPtr
|
||||
|
||||
let updatedObj =
|
||||
{ heapObj with
|
||||
Fields = updatedFields
|
||||
}
|
||||
|
||||
let updatedHeap =
|
||||
{ state.ManagedHeap with
|
||||
NonArrayObjects = state.ManagedHeap.NonArrayObjects |> Map.add constructing updatedObj
|
||||
}
|
||||
|
||||
{ state with
|
||||
ManagedHeap = updatedHeap
|
||||
}
|
||||
|
@@ -52,9 +52,10 @@ and MethodState =
|
||||
MethodState.setProgramCounter (state._IlOpIndex + bytes) state
|
||||
|
||||
static member advanceProgramCounter (state : MethodState) =
|
||||
MethodState.jumpProgramCounter
|
||||
(IlOp.NumberOfBytes state.ExecutingMethod.Instructions.Value.Locations.[state.IlOpIndex])
|
||||
state
|
||||
let instruction =
|
||||
state.ExecutingMethod.Instructions.Value.Locations.[state.IlOpIndex]
|
||||
|
||||
MethodState.jumpProgramCounter (IlOp.NumberOfBytes instruction) state
|
||||
|
||||
static member peekEvalStack (state : MethodState) : EvalStackValue option = EvalStack.Peek state.EvaluationStack
|
||||
|
||||
|
@@ -303,19 +303,38 @@ module internal UnaryMetadataIlOp =
|
||||
| Box -> failwith "TODO: Box unimplemented"
|
||||
| Ldelema -> failwith "TODO: Ldelema unimplemented"
|
||||
| Isinst ->
|
||||
let targetType =
|
||||
match metadataToken with
|
||||
| MetadataToken.TypeDefinition td -> state.ActiveAssembly(thread).TypeDefs.[td]
|
||||
| m -> failwith $"unexpected metadata token {m} in IsInst"
|
||||
|
||||
let actualObj, state = IlMachineState.popEvalStack thread state
|
||||
|
||||
let targetType : TypeDefn =
|
||||
match metadataToken with
|
||||
| MetadataToken.TypeDefinition td ->
|
||||
TypeDefn.FromDefinition (
|
||||
ComparableTypeDefinitionHandle.Make td,
|
||||
state.ActiveAssembly(thread).Name.FullName,
|
||||
failwith "TODO"
|
||||
)
|
||||
| MetadataToken.TypeSpecification handle -> state.ActiveAssembly(thread).TypeSpecs.[handle].Signature
|
||||
| m -> failwith $"unexpected metadata token {m} in IsInst"
|
||||
|
||||
let returnObj =
|
||||
match actualObj with
|
||||
| EvalStackValue.ManagedPointer ManagedPointerSource.Null ->
|
||||
// null IsInstance check always succeeds and results in a null reference
|
||||
EvalStackValue.ManagedPointer ManagedPointerSource.Null
|
||||
| v -> failwith $"TODO: %O{v}"
|
||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.LocalVariable _) -> failwith "TODO"
|
||||
| EvalStackValue.ManagedPointer (ManagedPointerSource.Heap addr) ->
|
||||
match state.ManagedHeap.NonArrayObjects.TryGetValue addr with
|
||||
| true, v ->
|
||||
{ new TypeInfoEval<_> with
|
||||
member _.Eval typeInfo = failwith "TODO"
|
||||
}
|
||||
|> v.Type.Apply
|
||||
| false, _ ->
|
||||
|
||||
match state.ManagedHeap.Arrays.TryGetValue addr with
|
||||
| true, v -> failwith "TODO"
|
||||
| false, _ -> failwith $"could not find managed object with address {addr}"
|
||||
| esv -> failwith $"TODO: {esv}"
|
||||
|
||||
let state =
|
||||
state
|
||||
|
Reference in New Issue
Block a user