Skip to content

Commit 2656442

Browse files
committed
Bitwise operators and floor division operator
1 parent 533e8b0 commit 2656442

File tree

10 files changed

+366
-10
lines changed

10 files changed

+366
-10
lines changed

src/MoonSharp.Interpreter/Execution/InstructionFieldUsage.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,20 @@ internal static InstructionFieldUsage GetFieldUsage(this OpCode op)
3535
case OpCode.Sub:
3636
case OpCode.Mul:
3737
case OpCode.Div:
38+
case OpCode.FloorDiv:
3839
case OpCode.Mod:
3940
case OpCode.Not:
4041
case OpCode.Len:
4142
case OpCode.Neg:
4243
case OpCode.Power:
4344
case OpCode.CNot:
4445
case OpCode.ToBool:
46+
case OpCode.BitwiseAnd:
47+
case OpCode.BitwiseOr:
48+
case OpCode.BitwiseXor:
49+
case OpCode.BitwiseLShift:
50+
case OpCode.BitwiseRShift:
51+
case OpCode.BitwiseNot:
4552
return InstructionFieldUsage.None;
4653
case OpCode.Pop:
4754
case OpCode.Copy:

src/MoonSharp.Interpreter/Execution/VM/OpCode.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,19 @@ internal enum OpCode
5050
Sub, // Subtraction of the two topmost operands on the v-stack
5151
Mul, // Multiplication of the two topmost operands on the v-stack
5252
Div, // Division of the two topmost operands on the v-stack
53+
FloorDiv, // Floor Division of the two topmost operands on the v-stack
5354
Mod, // Modulus of the two topmost operands on the v-stack
5455
Not, // Logical inversion of the topmost operand on the v-stack
5556
Len, // Size operator of the topmost operand on the v-stack
5657
Neg, // Negation (unary minus) operator of the topmost operand on the v-stack
5758
Power, // Power of the two topmost operands on the v-stack
5859
CNot, // Conditional NOT - takes second operand from the v-stack (must be bool), if true execs a NOT otherwise execs a TOBOOL
60+
BitwiseAnd, // Bitwise AND of the two topmost operands on the v-stack
61+
BitwiseOr, // Bitwise OR of the two topmost operands on the v-stack
62+
BitwiseXor, // Bitwise XOR of the two topmost operands on the v-stack
63+
BitwiseLShift, // Bitwise Left Shift of the two topmost operands on the v-stack
64+
BitwiseRShift, // Bitwise Right Shift of the two topmost operands on the v-stack
65+
BitwiseNot, // Unary Bitwise NOT of the topmost operand on the v-stack
5966

6067

6168
// Type conversions and manipulations

src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ private DynValue Processing_Loop(int instructionPtr)
7474
instructionPtr = ExecNeg(i, instructionPtr);
7575
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
7676
break;
77+
case OpCode.BitwiseNot:
78+
instructionPtr = ExecBitwiseNot(i, instructionPtr);
79+
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
80+
break;
7781
case OpCode.Sub:
7882
instructionPtr = ExecSub(i, instructionPtr);
7983
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
@@ -86,6 +90,10 @@ private DynValue Processing_Loop(int instructionPtr)
8690
instructionPtr = ExecDiv(i, instructionPtr);
8791
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
8892
break;
93+
case OpCode.FloorDiv:
94+
instructionPtr = ExecFloorDiv(i, instructionPtr);
95+
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
96+
break;
8997
case OpCode.Mod:
9098
instructionPtr = ExecMod(i, instructionPtr);
9199
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
@@ -94,6 +102,26 @@ private DynValue Processing_Loop(int instructionPtr)
94102
instructionPtr = ExecPower(i, instructionPtr);
95103
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
96104
break;
105+
case OpCode.BitwiseAnd:
106+
instructionPtr = ExecBitwiseAnd(i, instructionPtr);
107+
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
108+
break;
109+
case OpCode.BitwiseOr:
110+
instructionPtr = ExecBitwiseOr(i, instructionPtr);
111+
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
112+
break;
113+
case OpCode.BitwiseXor:
114+
instructionPtr = ExecBitwiseXor(i, instructionPtr);
115+
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
116+
break;
117+
case OpCode.BitwiseLShift:
118+
instructionPtr = ExecBitwiseLShift(i, instructionPtr);
119+
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
120+
break;
121+
case OpCode.BitwiseRShift:
122+
instructionPtr = ExecBitwiseRShift(i, instructionPtr);
123+
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
124+
break;
97125
case OpCode.Eq:
98126
instructionPtr = ExecEq(i, instructionPtr);
99127
if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine;
@@ -993,6 +1021,28 @@ private int ExecDiv(Instruction i, int instructionPtr)
9931021
else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
9941022
}
9951023
}
1024+
1025+
private int ExecFloorDiv(Instruction i, int instructionPtr)
1026+
{
1027+
DynValue r = m_ValueStack.Pop().ToScalar();
1028+
DynValue l = m_ValueStack.Pop().ToScalar();
1029+
1030+
double? rn = r.CastToNumber();
1031+
double? ln = l.CastToNumber();
1032+
1033+
if (ln.HasValue && rn.HasValue)
1034+
{
1035+
m_ValueStack.Push(DynValue.NewNumber(Math.Floor(ln.Value / rn.Value)));
1036+
return instructionPtr;
1037+
}
1038+
else
1039+
{
1040+
int ip = Internal_InvokeBinaryMetaMethod(l, r, "__idiv", instructionPtr);
1041+
if (ip >= 0) return ip;
1042+
else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
1043+
}
1044+
}
1045+
9961046
private int ExecPower(Instruction i, int instructionPtr)
9971047
{
9981048
DynValue r = m_ValueStack.Pop().ToScalar();
@@ -1015,6 +1065,126 @@ private int ExecPower(Instruction i, int instructionPtr)
10151065

10161066
}
10171067

1068+
private int ExecBitwiseAnd(Instruction i, int instructionPtr)
1069+
{
1070+
DynValue r = m_ValueStack.Pop().ToScalar();
1071+
DynValue l = m_ValueStack.Pop().ToScalar();
1072+
1073+
double? rn = r.CastToNumber();
1074+
double? ln = l.CastToNumber();
1075+
1076+
if (ln.HasValue && rn.HasValue)
1077+
{
1078+
uint uln = (uint)Math.IEEERemainder(ln.Value, Math.Pow(2.0, 32.0));
1079+
uint urn = (uint)Math.IEEERemainder(rn.Value, Math.Pow(2.0, 32.0));
1080+
1081+
m_ValueStack.Push(DynValue.NewNumber(uln & urn));
1082+
return instructionPtr;
1083+
}
1084+
else
1085+
{
1086+
int ip = Internal_InvokeBinaryMetaMethod(l, r, "__band", instructionPtr);
1087+
if (ip >= 0) return ip;
1088+
else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
1089+
}
1090+
}
1091+
1092+
private int ExecBitwiseOr(Instruction i, int instructionPtr)
1093+
{
1094+
DynValue r = m_ValueStack.Pop().ToScalar();
1095+
DynValue l = m_ValueStack.Pop().ToScalar();
1096+
1097+
double? rn = r.CastToNumber();
1098+
double? ln = l.CastToNumber();
1099+
1100+
if (ln.HasValue && rn.HasValue)
1101+
{
1102+
uint uln = (uint)Math.IEEERemainder(ln.Value, Math.Pow(2.0, 32.0));
1103+
uint urn = (uint)Math.IEEERemainder(rn.Value, Math.Pow(2.0, 32.0));
1104+
1105+
m_ValueStack.Push(DynValue.NewNumber(uln | urn));
1106+
return instructionPtr;
1107+
}
1108+
else
1109+
{
1110+
int ip = Internal_InvokeBinaryMetaMethod(l, r, "__bor", instructionPtr);
1111+
if (ip >= 0) return ip;
1112+
else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
1113+
}
1114+
}
1115+
1116+
private int ExecBitwiseXor(Instruction i, int instructionPtr)
1117+
{
1118+
DynValue r = m_ValueStack.Pop().ToScalar();
1119+
DynValue l = m_ValueStack.Pop().ToScalar();
1120+
1121+
double? rn = r.CastToNumber();
1122+
double? ln = l.CastToNumber();
1123+
1124+
if (ln.HasValue && rn.HasValue)
1125+
{
1126+
uint uln = (uint)Math.IEEERemainder(ln.Value, Math.Pow(2.0, 32.0));
1127+
uint urn = (uint)Math.IEEERemainder(rn.Value, Math.Pow(2.0, 32.0));
1128+
1129+
m_ValueStack.Push(DynValue.NewNumber(uln ^ urn));
1130+
return instructionPtr;
1131+
}
1132+
else
1133+
{
1134+
int ip = Internal_InvokeBinaryMetaMethod(l, r, "__bxor", instructionPtr);
1135+
if (ip >= 0) return ip;
1136+
else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
1137+
}
1138+
}
1139+
1140+
private int ExecBitwiseLShift(Instruction i, int instructionPtr)
1141+
{
1142+
DynValue r = m_ValueStack.Pop().ToScalar();
1143+
DynValue l = m_ValueStack.Pop().ToScalar();
1144+
1145+
double? rn = r.CastToNumber();
1146+
double? ln = l.CastToNumber();
1147+
1148+
if (ln.HasValue && rn.HasValue)
1149+
{
1150+
int iln = (int)Math.IEEERemainder(ln.Value, Math.Pow(2.0, 32.0));
1151+
int irn = (int)Math.IEEERemainder(rn.Value, Math.Pow(2.0, 32.0));
1152+
1153+
m_ValueStack.Push(DynValue.NewNumber(irn < 0 ? iln >> -irn : iln << irn));
1154+
return instructionPtr;
1155+
}
1156+
else
1157+
{
1158+
int ip = Internal_InvokeBinaryMetaMethod(l, r, "__shl", instructionPtr);
1159+
if (ip >= 0) return ip;
1160+
else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
1161+
}
1162+
}
1163+
1164+
private int ExecBitwiseRShift(Instruction i, int instructionPtr)
1165+
{
1166+
DynValue r = m_ValueStack.Pop().ToScalar();
1167+
DynValue l = m_ValueStack.Pop().ToScalar();
1168+
1169+
double? rn = r.CastToNumber();
1170+
double? ln = l.CastToNumber();
1171+
1172+
if (ln.HasValue && rn.HasValue)
1173+
{
1174+
int iln = (int)Math.IEEERemainder(ln.Value, Math.Pow(2.0, 32.0));
1175+
int irn = (int)Math.IEEERemainder(rn.Value, Math.Pow(2.0, 32.0));
1176+
1177+
m_ValueStack.Push(DynValue.NewNumber(irn < 0 ? iln << -irn : iln >> irn));
1178+
return instructionPtr;
1179+
}
1180+
else
1181+
{
1182+
int ip = Internal_InvokeBinaryMetaMethod(l, r, "__shr", instructionPtr);
1183+
if (ip >= 0) return ip;
1184+
else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
1185+
}
1186+
}
1187+
10181188
private int ExecNeg(Instruction i, int instructionPtr)
10191189
{
10201190
DynValue r = m_ValueStack.Pop().ToScalar();
@@ -1033,6 +1203,25 @@ private int ExecNeg(Instruction i, int instructionPtr)
10331203
}
10341204
}
10351205

1206+
private int ExecBitwiseNot(Instruction i, int instructionPtr)
1207+
{
1208+
DynValue r = m_ValueStack.Pop().ToScalar();
1209+
double? rn = r.CastToNumber();
1210+
1211+
if (rn.HasValue)
1212+
{
1213+
uint urn = (uint)Math.IEEERemainder(rn.Value, Math.Pow(2.0, 32.0));
1214+
m_ValueStack.Push(DynValue.NewNumber(~urn));
1215+
return instructionPtr;
1216+
}
1217+
else
1218+
{
1219+
int ip = Internal_InvokeUnaryMetaMethod(r, "__bnot", instructionPtr);
1220+
if (ip >= 0) return ip;
1221+
else throw ScriptRuntimeException.ArithmeticOnNonNumber(r);
1222+
}
1223+
}
1224+
10361225

10371226
private int ExecEq(Instruction i, int instructionPtr)
10381227
{

src/MoonSharp.Interpreter/Tree/Expression_.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ internal static Expression SimpleExp(ScriptLoadingContext lcontext)
148148
case TokenType.Function:
149149
lcontext.Lexer.Next();
150150
return new FunctionDefinitionExpression(lcontext, false, false);
151-
case TokenType.Lambda:
151+
case TokenType.Op_BitwiseOr_Or_Lambda:
152152
return new FunctionDefinitionExpression(lcontext, false, true);
153153
default:
154154
return PrimaryExp(lcontext);

0 commit comments

Comments
 (0)