fork download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. using System.Linq;
  5.  
  6.  
  7. namespace Assembler
  8. {
  9. internal class State
  10. {
  11. public readonly IDictionary<string, ulong> SymbolTable = new Dictionary<string, ulong>();
  12.  
  13. public void Clear()
  14. {
  15. SymbolTable.Clear();
  16. }
  17. }
  18.  
  19. internal interface IReference
  20. {
  21. ulong EvalAddress(State s); // evaluate reference to address
  22. }
  23.  
  24. internal abstract class ReferenceBase : IReference
  25. {
  26. public static IndexedReference operator+(long directOffset, ReferenceBase baseRef) { return new IndexedReference(baseRef, directOffset); }
  27. public static IndexedReference operator+(ReferenceBase baseRef, long directOffset) { return new IndexedReference(baseRef, directOffset); }
  28.  
  29. public abstract ulong EvalAddress(State s);
  30. }
  31.  
  32. internal class SymbolicReference : ReferenceBase
  33. {
  34. public static explicit operator SymbolicReference(string symbol) { return new SymbolicReference(symbol); }
  35. public SymbolicReference(string symbol) { _symbol = symbol; }
  36.  
  37. private readonly string _symbol;
  38.  
  39. public override ulong EvalAddress(State s)
  40. {
  41. return s.SymbolTable[_symbol];
  42. }
  43.  
  44. public override string ToString() { return string.Format("Sym({0})", _symbol); }
  45. }
  46.  
  47. internal class IndexedReference : ReferenceBase
  48. {
  49. public IndexedReference(IReference baseRef, long directOffset)
  50. {
  51. _baseRef = baseRef;
  52. _directOffset = directOffset;
  53. }
  54.  
  55. private readonly IReference _baseRef;
  56. private readonly long _directOffset;
  57.  
  58. public override ulong EvalAddress(State s)
  59. {
  60. return (_directOffset<0)
  61. ? _baseRef.EvalAddress(s) - (ulong) Math.Abs(_directOffset)
  62. : _baseRef.EvalAddress(s) + (ulong) Math.Abs(_directOffset);
  63. }
  64.  
  65. public override string ToString() { return string.Format("{0} + {1}", _directOffset, _baseRef); }
  66. }
  67. }
  68.  
  69. namespace Program
  70. {
  71. using Assembler;
  72.  
  73. public static class Program
  74. {
  75. public static void Main(string[] args)
  76. {
  77. var myBaseRef1 = new SymbolicReference("mystring1");
  78.  
  79. Expression<Func<IReference>> anyRefExpr = () => 64 + myBaseRef1;
  80. Console.WriteLine(anyRefExpr);
  81.  
  82. var myBaseRef2 = (SymbolicReference) "mystring2"; // uses explicit conversion operator
  83.  
  84. Expression<Func<IndexedReference>> indexedRefExpr = () => 64 + myBaseRef2;
  85. Console.WriteLine(indexedRefExpr);
  86.  
  87. Console.WriteLine(Console.Out.NewLine + "=== show compiletime types of returned values:");
  88. Console.WriteLine("myBaseRef1 -> {0}", myBaseRef1);
  89. Console.WriteLine("myBaseRef2 -> {0}", myBaseRef2);
  90. Console.WriteLine("anyRefExpr -> {0}", anyRefExpr.Compile().Method.ReturnType);
  91. Console.WriteLine("indexedRefExpr -> {0}", indexedRefExpr.Compile().Method.ReturnType);
  92.  
  93. Console.WriteLine(Console.Out.NewLine + "=== show runtime types of returned values:");
  94. Console.WriteLine("myBaseRef1 -> {0}", myBaseRef1);
  95. Console.WriteLine("myBaseRef2 -> {0}", myBaseRef2);
  96. Console.WriteLine("anyRefExpr -> {0}", anyRefExpr.Compile()()); // compile() returns Func<...>
  97. Console.WriteLine("indexedRefExpr -> {0}", indexedRefExpr.Compile()());
  98.  
  99. Console.WriteLine(Console.Out.NewLine + "=== observe how you could add an evaluation model using some kind of symbol table:");
  100. var compilerState = new State();
  101. compilerState.SymbolTable.Add("mystring1", 0xdeadbeef); // raw addresses
  102. compilerState.SymbolTable.Add("mystring2", 0xfeedface);
  103.  
  104. Console.WriteLine("myBaseRef1 evaluates to 0x{0:x8}", myBaseRef1.EvalAddress(compilerState));
  105. Console.WriteLine("myBaseRef2 evaluates to 0x{0:x8}", myBaseRef2.EvalAddress(compilerState));
  106. Console.WriteLine("anyRefExpr displays as {0:x8}", anyRefExpr.Compile()());
  107. Console.WriteLine("indexedRefExpr displays as {0:x8}", indexedRefExpr.Compile()());
  108. Console.WriteLine("anyRefExpr evaluates to 0x{0:x8}", anyRefExpr.Compile()().EvalAddress(compilerState));
  109. Console.WriteLine("indexedRefExpr evaluates to 0x{0:x8}", indexedRefExpr.Compile()().EvalAddress(compilerState));
  110. }
  111. }
  112. }
  113.  
Success #stdin #stdout 0.05s 38688KB
stdin
Standard input is empty
stdout
() => (64 + value(Program.Program+<Main>c__AnonStorey0).myBaseRef1)
() => (64 + value(Program.Program+<Main>c__AnonStorey0).myBaseRef2)

=== show compiletime types of returned values:
myBaseRef1     -> Sym(mystring1)
myBaseRef2     -> Sym(mystring2)
anyRefExpr     -> Assembler.IReference
indexedRefExpr -> Assembler.IndexedReference

=== show runtime types of returned values:
myBaseRef1     -> Sym(mystring1)
myBaseRef2     -> Sym(mystring2)
anyRefExpr     -> 64 + Sym(mystring1)
indexedRefExpr -> 64 + Sym(mystring2)

=== observe how you could add an evaluation model using some kind of symbol table:
myBaseRef1 evaluates to     0xdeadbeef
myBaseRef2 evaluates to     0xfeedface
anyRefExpr displays as      64 + Sym(mystring1)
indexedRefExpr displays as  64 + Sym(mystring2)
anyRefExpr evaluates to     0xdeadbf2f
indexedRefExpr evaluates to 0xfeedfb0e