Skip to content

Commit e278277

Browse files
committed
Add the bitwise operators
1 parent 0a49595 commit e278277

File tree

6 files changed

+86
-22
lines changed

6 files changed

+86
-22
lines changed

src/main/java/org/meteordev/starscript/Instruction.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ public enum Instruction {
1414
Modulo,
1515
Power,
1616

17+
BitwiseAnd,
18+
BitwiseOr,
19+
BitwiseXor,
20+
BitwiseNot,
21+
LeftShift,
22+
RightShift,
23+
UnsignedRightShift,
24+
1725
AddConstant,
1826

1927
Pop,

src/main/java/org/meteordev/starscript/Starscript.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,26 @@ public Section run(Script script, StringBuilder sb) {
5050
case Modulo: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(a.getNumber() % b.getNumber())); else error("Can only modulo 2 numbers."); break; }
5151
case Power: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(Math.pow(a.getNumber(), b.getNumber()))); else error("Can only power 2 numbers."); break; }
5252

53+
case BitwiseAnd: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(((int) a.getNumber()) & ((int) b.getNumber()))); else error("This operation requires 2 numbers."); break; }
54+
case BitwiseOr: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(((int) a.getNumber()) | ((int) b.getNumber()))); else error("This operation requires 2 numbers."); break; }
55+
case BitwiseXor: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(((int) a.getNumber()) ^ ((int) b.getNumber()))); else error("This operation requires 2 numbers."); break; }
56+
case LeftShift: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(((int) a.getNumber()) << ((int) b.getNumber()))); else error("This operation requires 2 numbers."); break; }
57+
case RightShift: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(((int) a.getNumber()) >> ((int) b.getNumber()))); else error("This operation requires 2 numbers."); break; }
58+
case UnsignedRightShift: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(((int) a.getNumber()) >>> ((int) b.getNumber()))); else error("This operation requires 2 numbers."); break; }
59+
5360
case AddConstant: { Value b = script.constants.get(script.code[ip++] & 0xFF); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.number(a.getNumber() + b.getNumber())); else if (a.isString()) push(Value.string(a.getString() + b.toString())); else error("Can only add 2 numbers or 1 string and other value."); break; }
5461

5562
case Pop: pop(); break;
5663
case Not: push(Value.bool(!pop().isTruthy())); break;
5764
case Negate: { Value a = pop(); if (a.isNumber()) push(Value.number(-a.getNumber())); else error("This operation requires a number."); break; }
65+
case BitwiseNot: { Value a = pop(); if (a.isNumber()) push(Value.number(~((int) a.getNumber()))); else error("This operation requires a number."); break; }
5866

5967
case Equals: push(Value.bool(pop().equals(pop()))); break;
6068
case NotEquals: push(Value.bool(!pop().equals(pop()))); break;
61-
case Greater: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() > b.getNumber())); else error("This operation requires 2 number."); break; }
62-
case GreaterEqual: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() >= b.getNumber())); else error("This operation requires 2 number."); break; }
63-
case Less: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() < b.getNumber())); else error("This operation requires 2 number."); break; }
64-
case LessEqual: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() <= b.getNumber())); else error("This operation requires 2 number."); break; }
69+
case Greater: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() > b.getNumber())); else error("This operation requires 2 numbers."); break; }
70+
case GreaterEqual: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() >= b.getNumber())); else error("This operation requires 2 numbers."); break; }
71+
case Less: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() < b.getNumber())); else error("This operation requires 2 numbers."); break; }
72+
case LessEqual: { Value b = pop(); Value a = pop(); if (a.isNumber() && b.isNumber()) push(Value.bool(a.getNumber() <= b.getNumber())); else error("This operation requires 2 numbers."); break; }
6573

6674
case Variable: { String name = script.constants.get(script.code[ip++] & 0xFF).getString(); Supplier<Value> s = globals.getRaw(name); push(s != null ? s.get() : Value.null_()); break; }
6775
case Get: { String name = script.constants.get(script.code[ip++] & 0xFF).getString(); Value v = pop(); if (!v.isMap()) { push(Value.null_()); break; } Supplier<Value> s = v.getMap().getRaw(name); push(s != null ? s.get() : Value.null_()); break; }

src/main/java/org/meteordev/starscript/compiler/Compiler.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,26 @@ public void visitBinary(Expr.Binary expr) {
8888
else compile(expr.getRight());
8989

9090
switch (expr.op) {
91-
case Plus: script.write(Instruction.Add); break;
92-
case Minus: script.write(Instruction.Subtract); break;
93-
case Star: script.write(Instruction.Multiply); break;
94-
case Slash: script.write(Instruction.Divide); break;
95-
case Percentage: script.write(Instruction.Modulo); break;
96-
case UpArrow: script.write(Instruction.Power); break;
97-
98-
case EqualEqual: script.write(Instruction.Equals); break;
99-
case BangEqual: script.write(Instruction.NotEquals); break;
100-
case Greater: script.write(Instruction.Greater); break;
101-
case GreaterEqual: script.write(Instruction.GreaterEqual); break;
102-
case Less: script.write(Instruction.Less); break;
103-
case LessEqual: script.write(Instruction.LessEqual); break;
91+
case Plus: script.write(Instruction.Add); break;
92+
case Minus: script.write(Instruction.Subtract); break;
93+
case Star: script.write(Instruction.Multiply); break;
94+
case Slash: script.write(Instruction.Divide); break;
95+
case Percentage: script.write(Instruction.Modulo); break;
96+
case UpArrow: script.write(Instruction.Power); break;
97+
98+
case EqualEqual: script.write(Instruction.Equals); break;
99+
case BangEqual: script.write(Instruction.NotEquals); break;
100+
case Greater: script.write(Instruction.Greater); break;
101+
case GreaterEqual: script.write(Instruction.GreaterEqual); break;
102+
case Less: script.write(Instruction.Less); break;
103+
case LessEqual: script.write(Instruction.LessEqual); break;
104+
105+
case Ampersand: script.write(Instruction.BitwiseAnd); break;
106+
case VBar: script.write(Instruction.BitwiseOr); break;
107+
case VBarUpArrow: script.write(Instruction.BitwiseXor); break;
108+
case DoubleLess: script.write(Instruction.LeftShift); break;
109+
case DoubleGreater: script.write(Instruction.RightShift); break;
110+
case TripleGreater: script.write(Instruction.UnsignedRightShift); break;
104111
}
105112
}
106113

@@ -110,6 +117,7 @@ public void visitUnary(Expr.Unary expr) {
110117

111118
if (expr.op == Token.Bang) script.write(Instruction.Not);
112119
else if (expr.op == Token.Minus) script.write(Instruction.Negate);
120+
else if (expr.op == Token.Tilde) script.write(Instruction.BitwiseNot);
113121
}
114122

115123
@Override

src/main/java/org/meteordev/starscript/compiler/Lexer.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,26 @@ public void next() {
4747

4848
case '=': if (match('=')) createToken(Token.EqualEqual); else unexpected(); break;
4949
case '!': createToken(match('=') ? Token.BangEqual : Token.Bang); break;
50-
case '>': createToken(match('=') ? Token.GreaterEqual : Token.Greater); break;
51-
case '<': createToken(match('=') ? Token.LessEqual : Token.Less); break;
50+
case '>':
51+
if (match('=')) {
52+
createToken(Token.GreaterEqual);
53+
break;
54+
}
55+
if (match('>')) {
56+
createToken(match('>') ? Token.TripleGreater : Token.DoubleGreater);
57+
break;
58+
}
59+
createToken(Token.Greater); break;
60+
case '<':
61+
if (match('=')) {
62+
createToken(Token.LessEqual);
63+
break;
64+
}
65+
if (match('<')) {
66+
createToken(Token.DoubleLess);
67+
break;
68+
}
69+
createToken(Token.Less); break;
5270

5371
case '+': createToken(Token.Plus); break;
5472
case '-': createToken(Token.Minus); break;
@@ -71,6 +89,10 @@ public void next() {
7189
createToken(Token.Section, source.substring(start + 1, current));
7290
break;
7391

92+
case '&': createToken(Token.Ampersand); break;
93+
case '|': createToken(match('^') ? Token.VBarUpArrow : Token.VBar); break;
94+
case '~': createToken(Token.Tilde); break;
95+
7496
default: unexpected();
7597
}
7698
}

src/main/java/org/meteordev/starscript/compiler/Parser.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,22 @@ private Expr term() {
147147

148148
private Expr factor() {
149149
int start = previous.start;
150-
Expr expr = unary();
150+
Expr expr = bitwise();
151151

152152
while (match(Token.Star, Token.Slash, Token.Percentage, Token.UpArrow)) {
153+
Token op = previous.token;
154+
Expr right = bitwise();
155+
expr = new Expr.Binary(start, previous.end, expr, op, right);
156+
}
157+
158+
return expr;
159+
}
160+
161+
private Expr bitwise() {
162+
int start = previous.start;
163+
Expr expr = unary();
164+
165+
while (match(Token.Ampersand, Token.VBar, Token.VBarUpArrow, Token.DoubleLess, Token.DoubleGreater, Token.TripleGreater)) {
153166
Token op = previous.token;
154167
Expr right = unary();
155168
expr = new Expr.Binary(start, previous.end, expr, op, right);
@@ -159,7 +172,7 @@ private Expr factor() {
159172
}
160173

161174
private Expr unary() {
162-
if (match(Token.Bang, Token.Minus)) {
175+
if (match(Token.Bang, Token.Minus, Token.Tilde)) {
163176
int start = previous.start;
164177

165178
Token op = previous.token;
@@ -352,7 +365,7 @@ public static class Result {
352365

353366
/** Helper method that returns true if there was 1 or more errors. */
354367
public boolean hasErrors() {
355-
return errors.size() > 0;
368+
return !errors.isEmpty();
356369
}
357370

358371
public void accept(Expr.Visitor visitor) {

src/main/java/org/meteordev/starscript/compiler/Token.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,10 @@ public enum Token {
2323

2424
Section,
2525

26+
Ampersand, VBar,
27+
Tilde, VBarUpArrow,
28+
DoubleGreater, TripleGreater,
29+
DoubleLess,
30+
2631
Error, EOF
2732
}

0 commit comments

Comments
 (0)