From e4a9361e90d6c1ca65a869c72a559d604005ccb4 Mon Sep 17 00:00:00 2001 From: Qrakhen Date: Fri, 8 May 2026 12:22:36 +0200 Subject: [PATCH] add pow operator, fix test script, add new build flag --- .../Compilation/ExpressionParser.cs | 4 ++ .../Execution/ArithmeticResolver.cs | 47 +++++++++++++++++++ Qrakhen.Qamp.Core/Execution/OpCode.cs | 5 +- Qrakhen.Qamp.Core/Qrakhen.Qamp.Core.csproj | 2 +- Qrakhen.Qamp.Core/Tokenization/Reader.cs | 21 +++++++-- Qrakhen.Qamp.Core/Tokenization/TokenType.cs | 15 +++--- Static/test.qp | 15 +++++- 7 files changed, 93 insertions(+), 16 deletions(-) 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.";