diff --git a/Qrakhen.Qamp.Core/Compilation/ExpressionParser.cs b/Qrakhen.Qamp.Core/Compilation/ExpressionParser.cs
index 64c3547..f8ea2e9 100644
--- a/Qrakhen.Qamp.Core/Compilation/ExpressionParser.cs
+++ b/Qrakhen.Qamp.Core/Compilation/ExpressionParser.cs
@@ -55,6 +55,9 @@ public static class ExpressionParser
case TokenType.Star:
digester.Emit(OpCode.Multiply);
break;
+ case TokenType.Pow:
+ digester.Emit(OpCode.Pow);
+ break;
case TokenType.Slash:
digester.Emit(OpCode.Divide);
break;
@@ -336,6 +339,7 @@ public static class ExpressionParser
_rules[TokenType.Semicolon] = new Rule(null, null, Weight.None);
_rules[TokenType.Slash] = new Rule(null, Binary, Weight.Factor);
_rules[TokenType.Star] = new Rule(null, Binary, Weight.Factor);
+ _rules[TokenType.Pow] = new Rule(null, Binary, Weight.Factor);
_rules[TokenType.Bang] = new Rule(Modifier, null, Weight.None);
_rules[TokenType.BangEqual] = new Rule(null, Binary, Weight.Equal);
_rules[TokenType.Equal] = new Rule(null, null, Weight.None);
diff --git a/Qrakhen.Qamp.Core/Execution/ArithmeticResolver.cs b/Qrakhen.Qamp.Core/Execution/ArithmeticResolver.cs
index 6e0345f..1194a34 100644
--- a/Qrakhen.Qamp.Core/Execution/ArithmeticResolver.cs
+++ b/Qrakhen.Qamp.Core/Execution/ArithmeticResolver.cs
@@ -47,6 +47,7 @@ public class ArithmeticResolver : IOperationResolver
OpCode.Divide => Divide(operation),
OpCode.Modulo => Modulo(operation),
OpCode.Multiply => Multiply(operation),
+ OpCode.Pow => Pow(operation),
OpCode.Negate => Negate(operation),
OpCode.BitwiseOr => BitwiseOr(operation),
OpCode.BitwiseAnd => BitwiseAnd(operation),
@@ -77,6 +78,7 @@ public class ArithmeticResolver : IOperationResolver
{ OpCode.Divide, Divide },
{ OpCode.Modulo, Modulo },
{ OpCode.Multiply, Multiply },
+ { OpCode.Pow, Pow },
{ OpCode.Negate, Negate },
{ OpCode.BitwiseOr, BitwiseOr },
{ OpCode.BitwiseAnd, BitwiseAnd },
@@ -91,8 +93,10 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
+#endif
return new Value(a.Dynamic == b.Dynamic);
}
@@ -100,8 +104,10 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
+#endif
return new Value(a.Dynamic > b.Dynamic);
}
@@ -109,15 +115,19 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
+#endif
return new Value(a.Dynamic < b.Dynamic);
}
public static Value Not(Operation operation)
{
Value value = operation.Left;
+#if SAFE_OPERATIONS
Assert.NotVoid(value);
+#endif
ulong inner = value.Unsigned;
return new Value(inner == 0);
}
@@ -126,10 +136,14 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
+#endif
if (a.IsString)
return Values.Objects.String.Make($"{a}{b}");
+#if SAFE_OPERATIONS
Assert.IsPrimitive(a, b);
+#endif
bool convert = a.Type != b.Type;
return new Value(a.Dynamic + b.Dynamic);
}
@@ -138,8 +152,10 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
+#endif
return new Value(a.Dynamic - b.Dynamic);
}
@@ -147,9 +163,11 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
Assert.NotZero(b);
+#endif
return new Value(a.Dynamic / b.Dynamic);
}
@@ -157,9 +175,11 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
Assert.NotZero(b);
+#endif
return new Value(a.Dynamic % b.Dynamic);
}
@@ -167,16 +187,31 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
+#endif
return new Value(a.Dynamic * b.Dynamic);
}
+ public static Value Pow(Operation operation)
+ {
+ Value a = operation.Left;
+ Value b = operation.Right;
+#if SAFE_OPERATIONS
+ Assert.NotVoid(a, b);
+ Assert.IsPrimitive(a, b);
+#endif
+ return new Value(Math.Pow(a.GetDecimal(), b.GetDecimal()));
+ }
+
public static Value Negate(Operation operation)
{
Value value = operation.Left;
+#if SAFE_OPERATIONS
Assert.NotVoid(value);
Assert.IsPrimitive(value);
+#endif
return new Value(-value.Dynamic);
}
@@ -184,9 +219,11 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b);
+#endif
return new Value(a.Dynamic | b.Dynamic);
}
@@ -194,9 +231,11 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b);
+#endif
return new Value(a.Dynamic & b.Dynamic);
}
@@ -204,9 +243,11 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b);
+#endif
return new Value(a.Dynamic ^ b.Dynamic);
}
@@ -214,9 +255,11 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b);
+#endif
return new Value(a.Dynamic << (int)(b.Dynamic ?? 0));
}
@@ -224,18 +267,22 @@ public class ArithmeticResolver : IOperationResolver
{
Value a = operation.Left;
Value b = operation.Right;
+#if SAFE_OPERATIONS
Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b);
+#endif
return new Value(a.Dynamic >> (int)(b.Dynamic ?? 0));
}
public static Value BitwiseInvert(Operation operation)
{
Value a = operation.Left;
+#if SAFE_OPERATIONS
Assert.NotVoid(a);
Assert.IsPrimitive(a);
Assert.IsInteger(a);
+#endif
return new Value(~a.Dynamic);
}
}
\ No newline at end of file
diff --git a/Qrakhen.Qamp.Core/Execution/OpCode.cs b/Qrakhen.Qamp.Core/Execution/OpCode.cs
index bee8f53..32b0d1b 100644
--- a/Qrakhen.Qamp.Core/Execution/OpCode.cs
+++ b/Qrakhen.Qamp.Core/Execution/OpCode.cs
@@ -61,8 +61,9 @@ public enum OpCode
Add = F_Arithmetic | 1,
Subtract = F_Arithmetic | 2,
Multiply = F_Arithmetic | 3,
- Divide = F_Arithmetic | 4,
- Modulo = F_Arithmetic | 5,
+ Pow = F_Arithmetic | 4,
+ Divide = F_Arithmetic | 5,
+ Modulo = F_Arithmetic | 6,
Negate = F_Arithmetic | 7,
F_Bitwise = 0x50,
diff --git a/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj b/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj
index e4a9773..5ddfe96 100644
--- a/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj
+++ b/Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj
@@ -8,6 +8,6 @@
true
..\Build\
AnyCPU;x64
- LOG;DEV;XD
+ LOG;DEV;XD;SAFE_OPERATIONS
diff --git a/Qrakhen.Qamp.Core/Tokenization/Reader.cs b/Qrakhen.Qamp.Core/Tokenization/Reader.cs
index 6c32a5e..bbc9bc1 100644
--- a/Qrakhen.Qamp.Core/Tokenization/Reader.cs
+++ b/Qrakhen.Qamp.Core/Tokenization/Reader.cs
@@ -32,33 +32,45 @@ internal static partial class ReaderPatterns
{
Define("false", False);
Define("true", True);
+
Define("null", Null);
Define("void", Null);
+
Define("and", And);
Define("else", Else);
Define("for", For);
Define("if", If);
Define("or", Or);
+
Define("this", This);
Define(".~", This);
+
Define("var", Var);
Define("*~", Var);
+
Define("while", While);
Define("do", Do);
Define("ref", Ref);
+
Define("function", Function);
Define("funqtion", Function);
Define("fq", Function);
Define("funq", Function);
+
Define("return", Return);
Define("<:", Return);
+
Define("class", Class);
+
Define("base", Base);
Define("^~", Base);
+
Define("typeof", TypeOf);
Define("?:", TypeOf);
+
Define("print", Print);
Define("::", Print);
+
Define("globals", PrintGlobals);
Define("stack", PrintStack);
Define("expr", PrintExpr);
@@ -312,11 +324,12 @@ public class Reader : IReader, IDisposable
'/' => Check('=') ?
MakeToken(SlashEqual, buffer + Next()) :
MakeToken(Slash, buffer),
- '*' => Check('=') ?
+ '*' => Check('~') ?
+ MakeToken(Var, buffer + Next()) :Check('=') ?
MakeToken(StarEqual, buffer + Next()) :
- Check('~') ?
- MakeToken(Var, buffer + Next()) :
- MakeToken(Star, buffer),
+ Check('*') ?
+ MakeToken(Pow, buffer + Next()) :
+ MakeToken(Star, buffer),
'=' => Check('=') ?
MakeToken(EqualEqual, buffer + Next()) :
MakeToken(Equal, buffer),
diff --git a/Qrakhen.Qamp.Core/Tokenization/TokenType.cs b/Qrakhen.Qamp.Core/Tokenization/TokenType.cs
index 85d0937..08ccd23 100644
--- a/Qrakhen.Qamp.Core/Tokenization/TokenType.cs
+++ b/Qrakhen.Qamp.Core/Tokenization/TokenType.cs
@@ -41,13 +41,14 @@ public enum TokenType
Slash = Operator | 3,
Star = Operator | 4,
Modulo = Operator | 5,
- BitwiseAnd = Operator | 6,
- BitwiseOr = Operator | 7,
- BitwiseXor = Operator | 8,
- BitwiseNot = Operator | 9,
- BitwiseLeft = Operator | 10,
- BitwiseRight = Operator | 11,
- AddressOf = Operator | 12, // returns the address of a ptr/object as a value
+ Pow = Operator | 6,
+ BitwiseAnd = Operator | 7,
+ BitwiseOr = Operator | 8,
+ BitwiseXor = Operator | 9,
+ BitwiseNot = Operator | 10,
+ BitwiseLeft = Operator | 11,
+ BitwiseRight = Operator | 12,
+ AddressOf = Operator | 13, // returns the address of a ptr/object as a value
Assignment = 1 << 9,
Equal = Assignment | 1,
diff --git a/Static/test.qp b/Static/test.qp
index 62557a8..81fd950 100644
--- a/Static/test.qp
+++ b/Static/test.qp
@@ -32,12 +32,23 @@ for (*~i<~0;i<16;i++) {
class Vector {
Vector(x, y, z) {
- .~:x <~ x;
+ this.x <~ x;
this.y = y;
- this:z <~ z;
+ this.z <~ z;
+ }
+
+ length() {
+ return sqrt(this.x**2 + this.y**2 + this.z**2);
}
}
+*~ pos <~ Vector(4.3, 3.141, 7.2);
+:: pos;
+:: pos.length();
+
+# "do string concatination like {this}, {nice}"
+# 'single quotes {are literal, but}' "double quotes can be {substitued}"
+
var delta = time() - now;
:: "this took " + delta + " microseconds. which are ~" + (delta / 1000) + " milliseconds.";