Skip to content

Commit 20c3cf0

Browse files
- Add missing assignment operators.
- Add missing power ('**') operator. - Add testcase to test them.
1 parent beb5d76 commit 20c3cf0

File tree

7 files changed

+114
-39
lines changed

7 files changed

+114
-39
lines changed

jsLexer.cpp

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ string getTokenStr(int token)
2424
{
2525
if (token > 32 && token < 128)
2626
{
27-
char buf[4] = "' '";
28-
buf[1] = (char) token;
27+
char buf[2] = "x";
28+
buf[0] = (char)token;
2929
return buf;
3030
}
31+
else if (token > LEX_ASSIGN_BASE && token < LEX_R_WORDS_BASE)
32+
{
33+
return getTokenStr(token - LEX_ASSIGN_BASE) + "=";
34+
}
3135
switch (token)
3236
{
3337
case LEX_EOF: return "EOF";
@@ -41,20 +45,14 @@ string getTokenStr(int token)
4145
case LEX_NTYPEEQUAL: return "!==";
4246
case LEX_LEQUAL: return "<=";
4347
case LEX_LSHIFT: return "<<";
44-
case LEX_LSHIFTEQUAL: return "<<=";
4548
case LEX_GEQUAL: return ">=";
4649
case LEX_RSHIFT: return ">>";
4750
case LEX_RSHIFTUNSIGNED: return ">>";
48-
case LEX_RSHIFTEQUAL: return ">>=";
49-
case LEX_PLUSEQUAL: return "+=";
50-
case LEX_MINUSEQUAL: return "-=";
5151
case LEX_PLUSPLUS: return "++";
5252
case LEX_MINUSMINUS: return "--";
53-
case LEX_ANDEQUAL: return "&=";
5453
case LEX_ANDAND: return "&&";
55-
case LEX_OREQUAL: return "|=";
5654
case LEX_OROR: return "||";
57-
case LEX_XOREQUAL: return "^=";
55+
case LEX_POWER: return "**";
5856
// reserved words
5957
case LEX_R_IF: return "if";
6058
case LEX_R_ELSE: return "else";
@@ -387,7 +385,7 @@ CScriptToken CScriptToken::parseString(const char * code)const
387385
struct SOperatorDef
388386
{
389387
const char * text;
390-
const LEX_TYPES code;
388+
const int code;
391389
const int len;
392390
};
393391

@@ -396,26 +394,29 @@ struct SOperatorDef
396394
* before sorter ones.
397395
*/
398396
const SOperatorDef s_operators [] = {
397+
{">>>=", LEX_ASSIGN_BASE + LEX_RSHIFTUNSIGNED, 4},
399398
{"===", LEX_TYPEEQUAL, 3},
400399
{"!==", LEX_NTYPEEQUAL, 3},
401-
{"<<=", LEX_LSHIFTEQUAL, 3},
402-
{">>=", LEX_RSHIFTEQUAL, 3},
403400
{">>>", LEX_RSHIFTUNSIGNED, 3},
401+
{"<<=", LEX_ASSIGN_BASE + LEX_LSHIFT, 3},
402+
{">>=", LEX_ASSIGN_BASE + LEX_RSHIFT, 3},
403+
{"**=", LEX_ASSIGN_BASE + LEX_POWER, 3},
404404
{"==", LEX_EQUAL, 2},
405405
{"!=", LEX_NEQUAL, 2},
406406
{"<=", LEX_LEQUAL, 2},
407407
{">=", LEX_GEQUAL, 2},
408408
{"<<", LEX_LSHIFT, 2},
409409
{">>", LEX_RSHIFT, 2},
410-
{"+=", LEX_PLUSEQUAL, 2},
411-
{"-=", LEX_MINUSEQUAL, 2},
412-
//{"*=", , 2},
413-
//{"/=", , 2},
414-
//{"%&=", , 2},
415-
{"&=", LEX_ANDEQUAL, 2},
416-
{"|=", LEX_OREQUAL, 2},
410+
{"**", LEX_POWER, 2},
411+
{"+=", LEX_ASSIGN_BASE + '+', 2},
412+
{"-=", LEX_ASSIGN_BASE + '-', 2},
413+
{"*=", LEX_ASSIGN_BASE + '*', 2},
414+
{"/=", LEX_ASSIGN_BASE + '/', 2},
415+
{"%=", LEX_ASSIGN_BASE + '%', 2},
416+
{"&=", LEX_ASSIGN_BASE + '&', 2},
417+
{"|=", LEX_ASSIGN_BASE + '|', 2},
418+
{"^=", LEX_ASSIGN_BASE + '^', 2},
417419
{"||", LEX_OROR, 2},
418-
{"^=", LEX_XOREQUAL, 2},
419420
{"&&", LEX_ANDAND, 2},
420421
{"++", LEX_PLUSPLUS, 2},
421422
{"--", LEX_MINUSMINUS, 2},
@@ -433,7 +434,7 @@ CScriptToken CScriptToken::parseOperator(const char * code)const
433434
for (int i = 0; s_operators[i].len > 0; ++i)
434435
{
435436
if (strncmp(code, s_operators[i].text, s_operators[i].len) == 0)
436-
return buildNextToken(s_operators[i].code, code, s_operators[i].len);
437+
return buildNextToken((LEX_TYPES)s_operators[i].code, code, s_operators[i].len);
437438
}
438439

439440
//Take it as a single char operator

jsLexer.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@ enum LEX_TYPES
1515
LEX_EOF = 0,
1616
LEX_INITIAL,
1717
LEX_COMMENT,
18-
LEX_ASSIGN_BASE = 128,
19-
20-
LEX_LSHIFTEQUAL,
21-
LEX_RSHIFTEQUAL,
22-
LEX_PLUSEQUAL = LEX_ASSIGN_BASE + '+',
23-
LEX_MINUSEQUAL = LEX_ASSIGN_BASE + '-',
24-
LEX_ANDEQUAL = LEX_ASSIGN_BASE + '&',
25-
LEX_OREQUAL = LEX_ASSIGN_BASE + '|',
26-
LEX_XOREQUAL = LEX_ASSIGN_BASE + '^',
2718

2819
LEX_ID = 256,
2920
LEX_INT,
@@ -43,8 +34,21 @@ enum LEX_TYPES
4334
LEX_MINUSMINUS,
4435
LEX_ANDAND,
4536
LEX_OROR,
37+
LEX_POWER,
38+
39+
LEX_ASSIGN_BASE = 512,
40+
41+
// LEX_PLUSEQUAL = LEX_ASSIGN_BASE + '+',
42+
// LEX_MINUSEQUAL = LEX_ASSIGN_BASE + '-',
43+
// LEX_ANDEQUAL = LEX_ASSIGN_BASE + '&',
44+
// LEX_OREQUAL = LEX_ASSIGN_BASE + '|',
45+
// LEX_XOREQUAL = LEX_ASSIGN_BASE + '^',
46+
// LEX_LSHIFTEQUAL,
47+
// LEX_RSHIFTEQUAL,
48+
LEX_ASSIGN_MAX = 1023,
49+
4650
// reserved words
47-
#define LEX_R_LIST_START LEX_R_IF
51+
LEX_R_WORDS_BASE = 1024,
4852
LEX_R_IF,
4953
LEX_R_ELSE,
5054
LEX_R_DO,
@@ -131,11 +135,6 @@ class CScriptToken
131135
return m_type;
132136
}
133137

134-
bool isAssignment()const
135-
{
136-
return m_type == '=' || (m_type > LEX_ASSIGN_BASE && m_type < LEX_ID);
137-
}
138-
139138
bool eof()const
140139
{
141140
return m_type == LEX_EOF;

jsParser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ ExprResult parseBinaryRLOp (CScriptToken token, const int *types, ExprResult::Pa
6363
bool isAssignment(CScriptToken token)
6464
{
6565
const LEX_TYPES t = token.type();
66-
return t == '=' || (t > LEX_ASSIGN_BASE && t < LEX_ID);
66+
return t == '=' || (t > LEX_ASSIGN_BASE && t < LEX_ASSIGN_MAX);
6767
}
6868

6969
bool oneOf (CScriptToken token, const char* chars)

microVM.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ void execCall (const int nArgs, ExecutionContext* ec)
307307
const Ref<JSValue> fnVal = ec->pop();
308308

309309
if (!fnVal->isFunction())
310-
error ("Trying to call a non-funcion value");
310+
error ("Trying to call a non-function value");
311311

312312
const Ref<JSFunction> function = fnVal.staticCast<JSFunction>();
313313

mvmCodegen.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,9 @@ void prefixOpCodegen(Ref<AstNode> statement, CodegenState* pState)
656656
{
657657
//It is translated into a '+=' or '-=' equivalent operation
658658
Ref<AstLiteral> l = AstLiteral::create(op->position(), 1);
659+
const int newOpCode = LEX_ASSIGN_BASE + (op->code == LEX_PLUSPLUS ? '+' : '-');
659660
Ref<AstNode> newOp = astCreateAssignment(op->position(),
660-
op->code == LEX_PLUSPLUS ? LEX_PLUSEQUAL : LEX_MINUSEQUAL,
661+
newOpCode,
661662
op->children()[0],
662663
l);
663664
codegen(newOp, pState);
@@ -952,6 +953,7 @@ void binaryOperatorCode (int tokenCode, CodegenState* pState)
952953
operators['*'] = "@multiply";
953954
operators['/'] = "@divide";
954955
operators['%'] = "@modulus";
956+
operators[LEX_POWER] = "@power";
955957
operators['&'] = "@binAnd";
956958
operators['|'] = "@binOr";
957959
operators['^'] = "@binXor";

mvmFunctions.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,19 @@ Ref<JSValue> mvmModulus (FunctionScope* pScope)
140140
return jsDouble( fmod(valA, valB) );
141141
}
142142

143+
/**
144+
* Power operation
145+
* @param pScope
146+
* @return
147+
*/
148+
Ref<JSValue> mvmPower (FunctionScope* pScope)
149+
{
150+
const double valA = pScope->getThis()->toDouble();
151+
const double valB = pScope->getParam("b")->toDouble();
152+
153+
return jsDouble( pow(valA, valB) );
154+
}
155+
143156
/**
144157
* Binary 'NOT' operation
145158
* @param pScope
@@ -419,6 +432,7 @@ void registerMvmFunctions(Ref<IScope> scope)
419432
addNative1("@multiply", "b", mvmMultiply, scope);
420433
addNative1("@divide", "b", mvmDivide, scope);
421434
addNative1("@modulus", "b", mvmModulus, scope);
435+
addNative1("@power", "b", mvmPower, scope);
422436

423437
addNative0("@binNot", mvmBinNot, scope);
424438
addNative1("@binAnd", "b", mvmBinAnd, scope);

tests/test039.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Assignment operators test
2+
3+
/*
4+
Assignment x = y x = y
5+
Addition assignment x += y x = x + y
6+
Subtraction assignment x -= y x = x - y
7+
Multiplication assignment x *= y x = x * y
8+
Division assignment x /= y x = x / y
9+
Remainder assignment x %= y x = x % y
10+
Exponentiation assignment x **= y x = x ** y
11+
Left shift assignment x <<= y x = x << y
12+
Right shift assignment x >>= y x = x >> y
13+
Unsigned right shift assignment x >>>= y x = x >>> y
14+
Bitwise AND assignment x &= y x = x & y
15+
Bitwise XOR assignment x ^= y x = x ^ y
16+
Bitwise OR assignment x |= y x = x | y
17+
*/
18+
19+
var x = 1;
20+
21+
assert (5 == (x+=4), "+= result");
22+
assert (5 == x, "+=");
23+
24+
x -= 7;
25+
assert (-2 == x, "-=");
26+
27+
x *= -12;
28+
assert (24 == x, "*=");
29+
30+
x /= 6;
31+
assert (4 == x, "/=");
32+
33+
x = 10;
34+
x %= 4;
35+
assert (2 == x, "%=");
36+
37+
x **= 8;
38+
assert (256 == x, "**=");
39+
40+
x <<= 2;
41+
assert (1024 == x, "<<=");
42+
43+
x |= 0x1F;
44+
assert (0x41F == x, "|=");
45+
46+
x ^= 0xff;
47+
assert (0x4E0 == x, "^=");
48+
49+
x = -17;
50+
x >>= 1;
51+
assert (-9 == x, ">>=");
52+
53+
x >>>= 22;
54+
assert (0x3FF == x, ">>>=");
55+
56+
x &= 0x1019;
57+
assert (0x19 == x, "&=");
58+
59+
result = 1;

0 commit comments

Comments
 (0)