add pow operator, fix test script, add new build flag

This commit is contained in:
Qrakhen 2026-05-08 12:22:36 +02:00
parent 5ad65da6da
commit e4a9361e90
7 changed files with 93 additions and 16 deletions

View File

@ -55,6 +55,9 @@ public static class ExpressionParser
case TokenType.Star: case TokenType.Star:
digester.Emit(OpCode.Multiply); digester.Emit(OpCode.Multiply);
break; break;
case TokenType.Pow:
digester.Emit(OpCode.Pow);
break;
case TokenType.Slash: case TokenType.Slash:
digester.Emit(OpCode.Divide); digester.Emit(OpCode.Divide);
break; break;
@ -336,6 +339,7 @@ public static class ExpressionParser
_rules[TokenType.Semicolon] = new Rule(null, null, Weight.None); _rules[TokenType.Semicolon] = new Rule(null, null, Weight.None);
_rules[TokenType.Slash] = new Rule(null, Binary, Weight.Factor); _rules[TokenType.Slash] = new Rule(null, Binary, Weight.Factor);
_rules[TokenType.Star] = 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.Bang] = new Rule(Modifier, null, Weight.None);
_rules[TokenType.BangEqual] = new Rule(null, Binary, Weight.Equal); _rules[TokenType.BangEqual] = new Rule(null, Binary, Weight.Equal);
_rules[TokenType.Equal] = new Rule(null, null, Weight.None); _rules[TokenType.Equal] = new Rule(null, null, Weight.None);

View File

@ -47,6 +47,7 @@ public class ArithmeticResolver : IOperationResolver
OpCode.Divide => Divide(operation), OpCode.Divide => Divide(operation),
OpCode.Modulo => Modulo(operation), OpCode.Modulo => Modulo(operation),
OpCode.Multiply => Multiply(operation), OpCode.Multiply => Multiply(operation),
OpCode.Pow => Pow(operation),
OpCode.Negate => Negate(operation), OpCode.Negate => Negate(operation),
OpCode.BitwiseOr => BitwiseOr(operation), OpCode.BitwiseOr => BitwiseOr(operation),
OpCode.BitwiseAnd => BitwiseAnd(operation), OpCode.BitwiseAnd => BitwiseAnd(operation),
@ -77,6 +78,7 @@ public class ArithmeticResolver : IOperationResolver
{ OpCode.Divide, Divide }, { OpCode.Divide, Divide },
{ OpCode.Modulo, Modulo }, { OpCode.Modulo, Modulo },
{ OpCode.Multiply, Multiply }, { OpCode.Multiply, Multiply },
{ OpCode.Pow, Pow },
{ OpCode.Negate, Negate }, { OpCode.Negate, Negate },
{ OpCode.BitwiseOr, BitwiseOr }, { OpCode.BitwiseOr, BitwiseOr },
{ OpCode.BitwiseAnd, BitwiseAnd }, { OpCode.BitwiseAnd, BitwiseAnd },
@ -91,8 +93,10 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
#endif
return new Value(a.Dynamic == b.Dynamic); return new Value(a.Dynamic == b.Dynamic);
} }
@ -100,8 +104,10 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
#endif
return new Value(a.Dynamic > b.Dynamic); return new Value(a.Dynamic > b.Dynamic);
} }
@ -109,15 +115,19 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
#endif
return new Value(a.Dynamic < b.Dynamic); return new Value(a.Dynamic < b.Dynamic);
} }
public static Value Not(Operation operation) public static Value Not(Operation operation)
{ {
Value value = operation.Left; Value value = operation.Left;
#if SAFE_OPERATIONS
Assert.NotVoid(value); Assert.NotVoid(value);
#endif
ulong inner = value.Unsigned; ulong inner = value.Unsigned;
return new Value(inner == 0); return new Value(inner == 0);
} }
@ -126,10 +136,14 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
#endif
if (a.IsString) if (a.IsString)
return Values.Objects.String.Make($"{a}{b}"); return Values.Objects.String.Make($"{a}{b}");
#if SAFE_OPERATIONS
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
#endif
bool convert = a.Type != b.Type; bool convert = a.Type != b.Type;
return new Value(a.Dynamic + b.Dynamic); return new Value(a.Dynamic + b.Dynamic);
} }
@ -138,8 +152,10 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
#endif
return new Value(a.Dynamic - b.Dynamic); return new Value(a.Dynamic - b.Dynamic);
} }
@ -147,9 +163,11 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
Assert.NotZero(b); Assert.NotZero(b);
#endif
return new Value(a.Dynamic / b.Dynamic); return new Value(a.Dynamic / b.Dynamic);
} }
@ -157,9 +175,11 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
Assert.NotZero(b); Assert.NotZero(b);
#endif
return new Value(a.Dynamic % b.Dynamic); return new Value(a.Dynamic % b.Dynamic);
} }
@ -167,16 +187,31 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
#endif
return new Value(a.Dynamic * b.Dynamic); 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) public static Value Negate(Operation operation)
{ {
Value value = operation.Left; Value value = operation.Left;
#if SAFE_OPERATIONS
Assert.NotVoid(value); Assert.NotVoid(value);
Assert.IsPrimitive(value); Assert.IsPrimitive(value);
#endif
return new Value(-value.Dynamic); return new Value(-value.Dynamic);
} }
@ -184,9 +219,11 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b); Assert.IsInteger(a, b);
#endif
return new Value(a.Dynamic | b.Dynamic); return new Value(a.Dynamic | b.Dynamic);
} }
@ -194,9 +231,11 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b); Assert.IsInteger(a, b);
#endif
return new Value(a.Dynamic & b.Dynamic); return new Value(a.Dynamic & b.Dynamic);
} }
@ -204,9 +243,11 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b); Assert.IsInteger(a, b);
#endif
return new Value(a.Dynamic ^ b.Dynamic); return new Value(a.Dynamic ^ b.Dynamic);
} }
@ -214,9 +255,11 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b); Assert.IsInteger(a, b);
#endif
return new Value(a.Dynamic << (int)(b.Dynamic ?? 0)); return new Value(a.Dynamic << (int)(b.Dynamic ?? 0));
} }
@ -224,18 +267,22 @@ public class ArithmeticResolver : IOperationResolver
{ {
Value a = operation.Left; Value a = operation.Left;
Value b = operation.Right; Value b = operation.Right;
#if SAFE_OPERATIONS
Assert.NotVoid(a, b); Assert.NotVoid(a, b);
Assert.IsPrimitive(a, b); Assert.IsPrimitive(a, b);
Assert.IsInteger(a, b); Assert.IsInteger(a, b);
#endif
return new Value(a.Dynamic >> (int)(b.Dynamic ?? 0)); return new Value(a.Dynamic >> (int)(b.Dynamic ?? 0));
} }
public static Value BitwiseInvert(Operation operation) public static Value BitwiseInvert(Operation operation)
{ {
Value a = operation.Left; Value a = operation.Left;
#if SAFE_OPERATIONS
Assert.NotVoid(a); Assert.NotVoid(a);
Assert.IsPrimitive(a); Assert.IsPrimitive(a);
Assert.IsInteger(a); Assert.IsInteger(a);
#endif
return new Value(~a.Dynamic); return new Value(~a.Dynamic);
} }
} }

View File

@ -61,8 +61,9 @@ public enum OpCode
Add = F_Arithmetic | 1, Add = F_Arithmetic | 1,
Subtract = F_Arithmetic | 2, Subtract = F_Arithmetic | 2,
Multiply = F_Arithmetic | 3, Multiply = F_Arithmetic | 3,
Divide = F_Arithmetic | 4, Pow = F_Arithmetic | 4,
Modulo = F_Arithmetic | 5, Divide = F_Arithmetic | 5,
Modulo = F_Arithmetic | 6,
Negate = F_Arithmetic | 7, Negate = F_Arithmetic | 7,
F_Bitwise = 0x50, F_Bitwise = 0x50,

View File

@ -8,6 +8,6 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<BaseOutputPath>..\Build\</BaseOutputPath> <BaseOutputPath>..\Build\</BaseOutputPath>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<DefineConstants>LOG;DEV;XD</DefineConstants> <DefineConstants>LOG;DEV;XD;SAFE_OPERATIONS</DefineConstants>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -32,33 +32,45 @@ internal static partial class ReaderPatterns
{ {
Define("false", False); Define("false", False);
Define("true", True); Define("true", True);
Define("null", Null); Define("null", Null);
Define("void", Null); Define("void", Null);
Define("and", And); Define("and", And);
Define("else", Else); Define("else", Else);
Define("for", For); Define("for", For);
Define("if", If); Define("if", If);
Define("or", Or); Define("or", Or);
Define("this", This); Define("this", This);
Define(".~", This); Define(".~", This);
Define("var", Var); Define("var", Var);
Define("*~", Var); Define("*~", Var);
Define("while", While); Define("while", While);
Define("do", Do); Define("do", Do);
Define("ref", Ref); Define("ref", Ref);
Define("function", Function); Define("function", Function);
Define("funqtion", Function); Define("funqtion", Function);
Define("fq", Function); Define("fq", Function);
Define("funq", Function); Define("funq", Function);
Define("return", Return); Define("return", Return);
Define("<:", Return); Define("<:", Return);
Define("class", Class); Define("class", Class);
Define("base", Base); Define("base", Base);
Define("^~", Base); Define("^~", Base);
Define("typeof", TypeOf); Define("typeof", TypeOf);
Define("?:", TypeOf); Define("?:", TypeOf);
Define("print", Print); Define("print", Print);
Define("::", Print); Define("::", Print);
Define("globals", PrintGlobals); Define("globals", PrintGlobals);
Define("stack", PrintStack); Define("stack", PrintStack);
Define("expr", PrintExpr); Define("expr", PrintExpr);
@ -312,10 +324,11 @@ public class Reader : IReader<Token>, IDisposable
'/' => Check('=') ? '/' => Check('=') ?
MakeToken(SlashEqual, buffer + Next()) : MakeToken(SlashEqual, buffer + Next()) :
MakeToken(Slash, buffer), MakeToken(Slash, buffer),
'*' => Check('=') ? '*' => Check('~') ?
MakeToken(Var, buffer + Next()) :Check('=') ?
MakeToken(StarEqual, buffer + Next()) : MakeToken(StarEqual, buffer + Next()) :
Check('~') ? Check('*') ?
MakeToken(Var, buffer + Next()) : MakeToken(Pow, buffer + Next()) :
MakeToken(Star, buffer), MakeToken(Star, buffer),
'=' => Check('=') ? '=' => Check('=') ?
MakeToken(EqualEqual, buffer + Next()) : MakeToken(EqualEqual, buffer + Next()) :

View File

@ -41,13 +41,14 @@ public enum TokenType
Slash = Operator | 3, Slash = Operator | 3,
Star = Operator | 4, Star = Operator | 4,
Modulo = Operator | 5, Modulo = Operator | 5,
BitwiseAnd = Operator | 6, Pow = Operator | 6,
BitwiseOr = Operator | 7, BitwiseAnd = Operator | 7,
BitwiseXor = Operator | 8, BitwiseOr = Operator | 8,
BitwiseNot = Operator | 9, BitwiseXor = Operator | 9,
BitwiseLeft = Operator | 10, BitwiseNot = Operator | 10,
BitwiseRight = Operator | 11, BitwiseLeft = Operator | 11,
AddressOf = Operator | 12, // returns the address of a ptr/object as a value BitwiseRight = Operator | 12,
AddressOf = Operator | 13, // returns the address of a ptr/object as a value
Assignment = 1 << 9, Assignment = 1 << 9,
Equal = Assignment | 1, Equal = Assignment | 1,

View File

@ -32,12 +32,23 @@ for (*~i<~0;i<16;i++) {
class Vector { class Vector {
Vector(x, y, z) { Vector(x, y, z) {
.~:x <~ x; this.x <~ x;
this.y = y; 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; var delta = time() - now;
:: "this took " + delta + " microseconds. which are ~" + (delta / 1000) + " milliseconds."; :: "this took " + delta + " microseconds. which are ~" + (delta / 1000) + " milliseconds.";