-
Notifications
You must be signed in to change notification settings - Fork 1
/
ArithmeticOperations.tt
150 lines (135 loc) · 6.11 KB
/
ArithmeticOperations.tt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".codegen.cs" #>
<#
var ops = new []
{
new Operation("Add", "Add", "To", true, true, "adds them together", "add the evaluation stack value to"),
new Operation("Divide", "Div", "By", false, true, "divides the first by the second", "divide the evaluation stack value by"),
new Operation("Multiply", "Mul", "By", true, true, "multiples them together", "multiply with the evaluation stack value"),
new Operation("Remainder", "Rem", "From", false, true, "finds the remainder when the first is divided by the second", "divide the evaluation stack value by"),
new Operation("Subtract", "Sub", "", true, true, "subtracts the second from the first", "subtract from the evaluation stack value")
};
var numericTypes = new [] { typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double) };
#>
using System;
using System.Reflection.Emit;
using JetBrains.Annotations;
namespace ILGeneratorExtensions
{
[PublicAPI]
public static partial class ArithmeticOperations
{
<# foreach (var op in ops) { #>
#region <#= op.Name #>
/// <summary>
/// Pops two values from the top of the evaluation stack and <#= op.Description #>
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator <#= op.Name #>(this ILGenerator generator) => generator.FluentEmit(OpCodes.<#= op.Op #>);
<# if (op.Overflow) { #>
/// <summary>
/// Pops two values from the top of the evaluation stack and <#= op.Description #> with a check for overflow
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator <#= op.Name #>WithOverflowCheck(this ILGenerator generator) => generator.FluentEmit(OpCodes.<#= op.Op #>_Ovf);
<# } #>
<# if (op.Signed && !op.Overflow) { #>
/// <summary>
/// Pops two values from the top of the evaluation stack and <#= op.Description #> without regard for sign
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator <#= op.Name #>Unsigned(this ILGenerator generator) => generator.FluentEmit(OpCodes.<#= op.Op #>_Un);
<# } #>
<# if (op.Signed && op.Overflow) { #>
/// <summary>
/// Pops two values from the top of the evaluation stack and <#= op.Description #> without regard for sign, and a check for overflow
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
[PublicAPI]
public static ILGenerator <#= op.Name #>UnsignedWithOverflowCheck(this ILGenerator generator) => generator.FluentEmit(OpCodes.<#= op.Op #>_Ovf_Un);
<# } #>
<# foreach (var type in numericTypes) { #>
/// <summary>
/// Pops a value from the top of the evaluation stack, and with the given value <#= op.Description #>
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="value">The value to <#= op.ValueDescription #></param>
[PublicAPI]
public static ILGenerator <#= op.Name #><#= op.Suffix #>(this ILGenerator generator, <#= type.Name #> value)
{
return generator.LoadConstant(value)
.<#= op.Name #>();
}
<# if (op.Overflow) { #>
/// <summary>
/// Pops a value from the top of the evaluation stack, and with the given value <#= op.Description #> with a check for overflow
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="value">The value to <#= op.ValueDescription #></param>
[PublicAPI]
public static ILGenerator <#= op.Name #><#= op.Suffix #>WithOverflowCheck(this ILGenerator generator, <#= type.Name #> value)
{
return generator.LoadConstant(value)
.<#= op.Name #>WithOverflowCheck();
}
<# } #>
<# if (op.Signed && !op.Overflow) { #>
/// <summary>
/// Pops a value from the top of the evaluation stack, and with the given value <#= op.Description #> without regard for sign
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="value">The value to <#= op.ValueDescription #></param>
[PublicAPI]
public static ILGenerator <#= op.Name #><#= op.Suffix #>Unsigned(this ILGenerator generator, <#= type.Name #> value)
{
return generator.LoadConstant(value)
.<#= op.Name #>Unsigned();
}
<# } #>
<# if (op.Signed && op.Overflow) { #>
/// <summary>
/// Pop a value from the top of the evaluation stack, and with the given value <#= op.Description #> without regard for sign, and a check for overflow
/// </summary>
/// <param name="generator">The <see cref="T:System.Reflection.Emit.ILGenerator" /> to emit instructions from</param>
/// <param name="value">The value to <#= op.ValueDescription #></param>
[PublicAPI]
public static ILGenerator <#= op.Name #><#= op.Suffix #>UnsignedWithOverflowCheck(this ILGenerator generator, <#= type.Name #> value)
{
return generator.LoadConstant(value)
.<#= op.Name #>UnsignedWithOverflowCheck();
}
<# } #>
<# } // foreach #>
#endregion
<# } //foreach #>
}
}
<#+
public class Operation
{
public string Name;
public string Op;
public string Suffix;
public bool Overflow;
public bool Signed;
public string Description;
public string ValueDescription;
public Operation(string name, string op, string suffix, bool overflow, bool signed, string description, string valueDescription)
{
Name = name;
Op = op;
Suffix = suffix;
Overflow = overflow;
Signed = signed;
Description = description;
ValueDescription = valueDescription;
}
}
#>