26#define JUCE_JS_OPERATORS(X) \
27 X(semicolon, ";") X(dot, ".") X(comma, ",") \
28 X(openParen, "(") X(closeParen, ")") X(openBrace, "{") X(closeBrace, "}") \
29 X(openBracket, "[") X(closeBracket, "]") X(colon, ":") X(question, "?") \
30 X(typeEquals, "===") X(equals, "==") X(assign, "=") \
31 X(typeNotEquals, "!==") X(notEquals, "!=") X(logicalNot, "!") \
32 X(plusEquals, "+=") X(plusplus, "++") X(plus, "+") \
33 X(minusEquals, "-=") X(minusminus, "--") X(minus, "-") \
34 X(timesEquals, "*=") X(times, "*") X(divideEquals, "/=") X(divide, "/") \
35 X(moduloEquals, "%=") X(modulo, "%") X(xorEquals, "^=") X(bitwiseXor, "^") \
36 X(andEquals, "&=") X(logicalAnd, "&&") X(bitwiseAnd, "&") \
37 X(orEquals, "|=") X(logicalOr, "||") X(bitwiseOr, "|") \
38 X(leftShiftEquals, "<<=") X(lessThanOrEqual, "<=") X(leftShift, "<<") X(lessThan, "<") \
39 X(rightShiftUnsigned, ">>>") X(rightShiftEquals, ">>=") X(rightShift, ">>") X(greaterThanOrEqual, ">=") X(greaterThan, ">")
41#define JUCE_JS_KEYWORDS(X) \
42 X(var, "var") X(if_, "if") X(else_, "else") X(do_, "do") X(null_, "null") \
43 X(while_, "while") X(for_, "for") X(break_, "break") X(continue_, "continue") X(undefined, "undefined") \
44 X(function, "function") X(return_, "return") X(true_, "true") X(false_, "false") X(new_, "new") \
49 #define JUCE_DECLARE_JS_TOKEN(name, str) static const char* const name = str;
50 JUCE_JS_KEYWORDS (JUCE_DECLARE_JS_TOKEN)
51 JUCE_JS_OPERATORS (JUCE_DECLARE_JS_TOKEN)
52 JUCE_DECLARE_JS_TOKEN (eof,
"$eof")
53 JUCE_DECLARE_JS_TOKEN (literal, "$literal")
54 JUCE_DECLARE_JS_TOKEN (identifier, "$identifier")
58 #pragma warning (push)
59 #pragma warning (disable: 4702)
63struct JavascriptEngine::RootObject :
public DynamicObject
67 setMethod (
"exec", exec);
68 setMethod (
"eval", eval);
69 setMethod (
"trace", trace);
70 setMethod (
"charToInt", charToInt);
71 setMethod (
"parseInt", IntegerClass::parseInt);
72 setMethod (
"typeof", typeof_internal);
73 setMethod (
"parseFloat", parseFloat);
78 using Args =
const var::NativeFunctionArgs&;
79 using TokenType =
const char*;
81 void execute (
const String& code)
83 ExpressionTreeBuilder tb (code);
84 std::unique_ptr<BlockStatement> (tb.parseStatementList())->perform (Scope ({}, *
this, *
this),
nullptr);
87 var evaluate (
const String& code)
89 ExpressionTreeBuilder tb (code);
90 return ExpPtr (tb.parseExpression())->getResult (Scope ({}, *
this, *
this));
94 static bool areTypeEqual (
const var& a,
const var& b)
96 return a.hasSameTypeAs (b) && isFunction (a) == isFunction (b)
97 && (((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid())) || a == b);
100 static String getTokenName (TokenType t) {
return t[0] ==
'$' ? String (t + 1) : (
"'" + String (t) +
"'"); }
101 static bool isFunction (
const var& v)
noexcept {
return dynamic_cast<FunctionObject*
> (v.getObject()) !=
nullptr; }
102 static bool isNumeric (
const var& v)
noexcept {
return v.isInt() || v.isDouble() || v.isInt64() || v.isBool(); }
103 static bool isNumericOrUndefined (
const var& v)
noexcept {
return isNumeric (v) || v.isUndefined(); }
104 static int64 getOctalValue (
const String& s) { BigInteger b; b.parseString (s.initialSectionContainingOnly (
"01234567"), 8);
return b.toInt64(); }
105 static Identifier getPrototypeIdentifier() {
static const Identifier i (
"prototype");
return i; }
106 static var* getPropertyPointer (DynamicObject& o,
const Identifier& i)
noexcept {
return o.getProperties().getVarPointer (i); }
111 CodeLocation (
const String& code) noexcept : program (code), location (program.getCharPointer()) {}
112 CodeLocation (
const CodeLocation& other) noexcept : program (other.program), location (other.location) {}
114 void throwError (
const String& message)
const
116 int col = 1, line = 1;
118 for (
auto i = program.getCharPointer(); i < location && ! i.isEmpty(); ++i)
121 if (*i ==
'\n') { col = 1; ++line; }
124 throw "Line " + String (line) +
", column " + String (col) +
" : " + message;
128 String::CharPointerType location;
134 Scope (
const Scope* p, ReferenceCountedObjectPtr<RootObject> rt, DynamicObject::Ptr scp) noexcept
135 : parent (p), root (std::move (rt)),
136 scope (std::move (scp)) {}
138 const Scope*
const parent;
139 ReferenceCountedObjectPtr<RootObject> root;
140 DynamicObject::Ptr scope;
142 var findFunctionCall (
const CodeLocation& location,
const var& targetObject,
const Identifier& functionName)
const
144 if (
auto* o = targetObject.getDynamicObject())
146 if (
auto* prop = getPropertyPointer (*o, functionName))
149 for (
auto* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p !=
nullptr;
150 p = p->getProperty (getPrototypeIdentifier()).getDynamicObject())
152 if (
auto* prop = getPropertyPointer (*p, functionName))
157 if (o->hasMethod (functionName))
161 if (targetObject.isString())
162 if (
auto* m = findRootClassProperty (StringClass::getClassName(), functionName))
165 if (targetObject.isArray())
166 if (
auto* m = findRootClassProperty (ArrayClass::getClassName(), functionName))
169 if (
auto* m = findRootClassProperty (ObjectClass::getClassName(), functionName))
172 location.throwError (
"Unknown function '" + functionName.toString() +
"'");
176 var* findRootClassProperty (
const Identifier& className,
const Identifier& propName)
const
178 if (
auto* cls = root->getProperty (className).getDynamicObject())
179 return getPropertyPointer (*cls, propName);
184 var findSymbolInParentScopes (
const Identifier& name)
const
186 if (
auto v = getPropertyPointer (*scope, name))
189 return parent !=
nullptr ? parent->findSymbolInParentScopes (name)
193 bool findAndInvokeMethod (
const Identifier& function,
const var::NativeFunctionArgs& args, var& result)
const
195 auto* target = args.thisObject.getDynamicObject();
197 if (target ==
nullptr || target == scope.get())
199 if (
auto* m = getPropertyPointer (*scope, function))
201 if (
auto fo =
dynamic_cast<FunctionObject*
> (m->getObject()))
203 result = fo->invoke (*
this, args);
209 const auto& props = scope->getProperties();
211 for (
int i = 0; i < props.size(); ++i)
212 if (
auto* o = props.getValueAt (i).getDynamicObject())
213 if (Scope (
this, *root, *o).findAndInvokeMethod (function, args, result))
219 bool invokeMethod (
const var& m,
const var::NativeFunctionArgs& args, var& result)
const
223 auto* target = args.thisObject.getDynamicObject();
225 if (target ==
nullptr || target == scope.get())
227 if (
auto fo =
dynamic_cast<FunctionObject*
> (m.getObject()))
229 result = fo->invoke (*
this, args);
238 void checkTimeOut (
const CodeLocation& location)
const
240 if (Time::getCurrentTime() > root->timeout)
241 location.throwError (root->timeout == Time() ?
"Interrupted" :
"Execution timed-out");
244 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Scope)
250 Statement (
const CodeLocation& l) noexcept : location (l) {}
251 virtual ~Statement() {}
253 enum ResultCode { ok = 0, returnWasHit, breakWasHit, continueWasHit };
254 virtual ResultCode perform (
const Scope&, var*)
const {
return ok; }
256 CodeLocation location;
257 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Statement)
260 struct Expression :
public Statement
262 Expression (
const CodeLocation& l) noexcept : Statement (l) {}
264 virtual var getResult (
const Scope&)
const {
return var::undefined(); }
265 virtual void assign (
const Scope&,
const var&)
const { location.throwError (
"Cannot assign to this expression!"); }
267 ResultCode perform (
const Scope& s, var*)
const override { getResult (s);
return ok; }
270 using ExpPtr = std::unique_ptr<Expression>;
272 struct BlockStatement :
public Statement
274 BlockStatement (
const CodeLocation& l) noexcept : Statement (l) {}
276 ResultCode perform (
const Scope& s, var* returnedValue)
const override
278 for (
auto* statement : statements)
279 if (auto r = statement->perform (s, returnedValue))
285 OwnedArray<Statement> statements;
288 struct IfStatement :
public Statement
290 IfStatement (
const CodeLocation& l) noexcept : Statement (l) {}
292 ResultCode perform (
const Scope& s, var* returnedValue)
const override
294 return (condition->getResult(s) ? trueBranch : falseBranch)->perform (s, returnedValue);
298 std::unique_ptr<Statement> trueBranch, falseBranch;
301 struct VarStatement :
public Statement
303 VarStatement (
const CodeLocation& l) noexcept : Statement (l) {}
305 ResultCode perform (
const Scope& s, var*)
const override
307 s.scope->setProperty (name, initialiser->getResult (s));
315 struct LoopStatement :
public Statement
317 LoopStatement (
const CodeLocation& l,
bool isDo) noexcept : Statement (l), isDoLoop (isDo) {}
319 ResultCode perform (
const Scope& s, var* returnedValue)
const override
321 initialiser->perform (s,
nullptr);
323 while (isDoLoop || condition->getResult (s))
325 s.checkTimeOut (location);
326 auto r = body->perform (s, returnedValue);
328 if (r == returnWasHit)
return r;
329 if (r == breakWasHit)
break;
331 iterator->perform (s,
nullptr);
333 if (isDoLoop && r != continueWasHit && ! condition->getResult (s))
340 std::unique_ptr<Statement> initialiser, iterator, body;
345 struct ReturnStatement :
public Statement
347 ReturnStatement (
const CodeLocation& l, Expression* v) noexcept : Statement (l), returnValue (v) {}
349 ResultCode perform (
const Scope& s, var* ret)
const override
351 if (ret !=
nullptr) *ret = returnValue->getResult (s);
358 struct BreakStatement :
public Statement
360 BreakStatement (
const CodeLocation& l) noexcept : Statement (l) {}
361 ResultCode perform (
const Scope&, var*)
const override {
return breakWasHit; }
364 struct ContinueStatement :
public Statement
366 ContinueStatement (
const CodeLocation& l) noexcept : Statement (l) {}
367 ResultCode perform (
const Scope&, var*)
const override {
return continueWasHit; }
370 struct LiteralValue :
public Expression
372 LiteralValue (
const CodeLocation& l,
const var& v) noexcept : Expression (l), value (v) {}
373 var getResult (
const Scope&)
const override {
return value; }
377 struct UnqualifiedName :
public Expression
379 UnqualifiedName (
const CodeLocation& l,
const Identifier& n) noexcept : Expression (l), name (n) {}
381 var getResult (
const Scope& s)
const override {
return s.findSymbolInParentScopes (name); }
383 void assign (
const Scope& s,
const var& newValue)
const override
385 if (
auto* v = getPropertyPointer (*s.scope, name))
388 s.root->setProperty (name, newValue);
394 struct DotOperator :
public Expression
396 DotOperator (
const CodeLocation& l, ExpPtr& p,
const Identifier& c) noexcept : Expression (l), parent (p.release()), child (c) {}
398 var getResult (
const Scope& s)
const override
400 auto p = parent->getResult (s);
401 static const Identifier lengthID (
"length");
403 if (child == lengthID)
405 if (
auto* array = p.getArray())
return array->size();
406 if (p.isString())
return p.toString().length();
409 if (
auto* o = p.getDynamicObject())
410 if (
auto* v = getPropertyPointer (*o, child))
413 return var::undefined();
416 void assign (
const Scope& s,
const var& newValue)
const override
418 if (
auto* o = parent->getResult (s).getDynamicObject())
419 o->setProperty (child, newValue);
421 Expression::assign (s, newValue);
428 struct ArraySubscript :
public Expression
430 ArraySubscript (
const CodeLocation& l) noexcept : Expression (l) {}
432 var getResult (
const Scope& s)
const override
434 auto arrayVar =
object->getResult (s);
435 auto key = index->getResult (s);
437 if (
const auto* array = arrayVar.getArray())
438 if (key.isInt() || key.isInt64() || key.isDouble())
439 return (*array) [
static_cast<int> (key)];
441 if (
auto* o = arrayVar.getDynamicObject())
443 if (
auto* v = getPropertyPointer (*o, Identifier (key)))
446 return var::undefined();
449 void assign (
const Scope& s,
const var& newValue)
const override
451 auto arrayVar =
object->getResult (s);
452 auto key = index->getResult (s);
454 if (
auto* array = arrayVar.getArray())
456 if (key.isInt() || key.isInt64() || key.isDouble())
459 while (array->size() < i)
460 array->add (var::undefined());
462 array->set (i, newValue);
467 if (
auto* o = arrayVar.getDynamicObject())
471 o->setProperty (Identifier (key), newValue);
476 Expression::assign (s, newValue);
479 ExpPtr object, index;
482 struct BinaryOperatorBase :
public Expression
484 BinaryOperatorBase (
const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
485 : Expression (l), lhs (a.release()), rhs (b.release()), operation (op) {}
491 struct BinaryOperator :
public BinaryOperatorBase
493 BinaryOperator (
const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
494 : BinaryOperatorBase (l, a, b, op) {}
496 virtual var getWithUndefinedArg()
const {
return var::undefined(); }
497 virtual var getWithDoubles (
double,
double)
const {
return throwError (
"Double"); }
498 virtual var getWithInts (int64, int64)
const {
return throwError (
"Integer"); }
499 virtual var getWithArrayOrObject (
const var& a,
const var&)
const {
return throwError (a.isArray() ?
"Array" :
"Object"); }
500 virtual var getWithStrings (
const String&,
const String&)
const {
return throwError (
"String"); }
502 var getResult (
const Scope& s)
const override
504 var a (lhs->getResult (s)), b (rhs->getResult (s));
506 if ((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid()))
507 return getWithUndefinedArg();
509 if (isNumericOrUndefined (a) && isNumericOrUndefined (b))
510 return (a.isDouble() || b.isDouble()) ? getWithDoubles (a, b) : getWithInts (a, b);
512 if (a.isArray() || a.isObject())
513 return getWithArrayOrObject (a, b);
515 return getWithStrings (a.toString(), b.toString());
518 var throwError (
const char* typeName)
const
519 { location.throwError (getTokenName (operation) +
" is not allowed on the " + typeName +
" type");
return {}; }
522 struct EqualsOp :
public BinaryOperator
524 EqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::equals) {}
525 var getWithUndefinedArg()
const override {
return true; }
526 var getWithDoubles (
double a,
double b)
const override {
return a == b; }
527 var getWithInts (int64 a, int64 b)
const override {
return a == b; }
528 var getWithStrings (
const String& a,
const String& b)
const override {
return a == b; }
529 var getWithArrayOrObject (
const var& a,
const var& b)
const override {
return a == b; }
532 struct NotEqualsOp :
public BinaryOperator
534 NotEqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::notEquals) {}
535 var getWithUndefinedArg()
const override {
return false; }
536 var getWithDoubles (
double a,
double b)
const override {
return a != b; }
537 var getWithInts (int64 a, int64 b)
const override {
return a != b; }
538 var getWithStrings (
const String& a,
const String& b)
const override {
return a != b; }
539 var getWithArrayOrObject (
const var& a,
const var& b)
const override {
return a != b; }
542 struct LessThanOp :
public BinaryOperator
544 LessThanOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThan) {}
545 var getWithDoubles (
double a,
double b)
const override {
return a < b; }
546 var getWithInts (int64 a, int64 b)
const override {
return a < b; }
547 var getWithStrings (
const String& a,
const String& b)
const override {
return a < b; }
550 struct LessThanOrEqualOp :
public BinaryOperator
552 LessThanOrEqualOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThanOrEqual) {}
553 var getWithDoubles (
double a,
double b)
const override {
return a <= b; }
554 var getWithInts (int64 a, int64 b)
const override {
return a <= b; }
555 var getWithStrings (
const String& a,
const String& b)
const override {
return a <= b; }
558 struct GreaterThanOp :
public BinaryOperator
560 GreaterThanOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThan) {}
561 var getWithDoubles (
double a,
double b)
const override {
return a > b; }
562 var getWithInts (int64 a, int64 b)
const override {
return a > b; }
563 var getWithStrings (
const String& a,
const String& b)
const override {
return a > b; }
566 struct GreaterThanOrEqualOp :
public BinaryOperator
568 GreaterThanOrEqualOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThanOrEqual) {}
569 var getWithDoubles (
double a,
double b)
const override {
return a >= b; }
570 var getWithInts (int64 a, int64 b)
const override {
return a >= b; }
571 var getWithStrings (
const String& a,
const String& b)
const override {
return a >= b; }
574 struct AdditionOp :
public BinaryOperator
576 AdditionOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::plus) {}
577 var getWithDoubles (
double a,
double b)
const override {
return a + b; }
578 var getWithInts (int64 a, int64 b)
const override {
return a + b; }
579 var getWithStrings (
const String& a,
const String& b)
const override {
return a + b; }
582 struct SubtractionOp :
public BinaryOperator
584 SubtractionOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::minus) {}
585 var getWithDoubles (
double a,
double b)
const override {
return a - b; }
586 var getWithInts (int64 a, int64 b)
const override {
return a - b; }
589 struct MultiplyOp :
public BinaryOperator
591 MultiplyOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::times) {}
592 var getWithDoubles (
double a,
double b)
const override {
return a * b; }
593 var getWithInts (int64 a, int64 b)
const override {
return a * b; }
596 struct DivideOp :
public BinaryOperator
598 DivideOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {}
599 var getWithDoubles (
double a,
double b)
const override {
return b != 0 ? a / b : std::numeric_limits<double>::infinity(); }
600 var getWithInts (int64 a, int64 b)
const override {
return b != 0 ? var (a / (
double) b) : var (std::numeric_limits<double>::infinity()); }
603 struct ModuloOp :
public BinaryOperator
605 ModuloOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {}
606 var getWithDoubles (
double a,
double b)
const override {
return b != 0 ? fmod (a, b) : std::numeric_limits<double>::infinity(); }
607 var getWithInts (int64 a, int64 b)
const override {
return b != 0 ? var (a % b) : var (std::numeric_limits<double>::infinity()); }
610 struct BitwiseOrOp :
public BinaryOperator
612 BitwiseOrOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseOr) {}
613 var getWithInts (int64 a, int64 b)
const override {
return a | b; }
616 struct BitwiseAndOp :
public BinaryOperator
618 BitwiseAndOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseAnd) {}
619 var getWithInts (int64 a, int64 b)
const override {
return a & b; }
622 struct BitwiseXorOp :
public BinaryOperator
624 BitwiseXorOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseXor) {}
625 var getWithInts (int64 a, int64 b)
const override {
return a ^ b; }
628 struct LeftShiftOp :
public BinaryOperator
630 LeftShiftOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::leftShift) {}
631 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) << (int) b; }
634 struct RightShiftOp :
public BinaryOperator
636 RightShiftOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShift) {}
637 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) >> (int) b; }
640 struct RightShiftUnsignedOp :
public BinaryOperator
642 RightShiftUnsignedOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShiftUnsigned) {}
643 var getWithInts (int64 a, int64 b)
const override {
return (
int) (((uint32) a) >> (int) b); }
646 struct LogicalAndOp :
public BinaryOperatorBase
648 LogicalAndOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalAnd) {}
649 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) && rhs->getResult (s); }
652 struct LogicalOrOp :
public BinaryOperatorBase
654 LogicalOrOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalOr) {}
655 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) || rhs->getResult (s); }
658 struct TypeEqualsOp :
public BinaryOperatorBase
660 TypeEqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeEquals) {}
661 var getResult (
const Scope& s)
const override {
return areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
664 struct TypeNotEqualsOp :
public BinaryOperatorBase
666 TypeNotEqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeNotEquals) {}
667 var getResult (
const Scope& s)
const override {
return ! areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
670 struct ConditionalOp :
public Expression
672 ConditionalOp (
const CodeLocation& l) noexcept : Expression (l) {}
674 var getResult (
const Scope& s)
const override {
return (condition->getResult (s) ? trueBranch : falseBranch)->getResult (s); }
675 void assign (
const Scope& s,
const var& v)
const override { (condition->getResult (s) ? trueBranch : falseBranch)->assign (s, v); }
677 ExpPtr condition, trueBranch, falseBranch;
680 struct Assignment :
public Expression
682 Assignment (
const CodeLocation& l, ExpPtr& dest, ExpPtr& source) noexcept : Expression (l), target (dest.release()), newValue (source.release()) {}
684 var getResult (
const Scope& s)
const override
686 auto value = newValue->getResult (s);
687 target->assign (s, value);
691 ExpPtr target, newValue;
694 struct SelfAssignment :
public Expression
696 SelfAssignment (
const CodeLocation& l, Expression* dest, Expression* source) noexcept
697 : Expression (l), target (dest), newValue (source) {}
699 var getResult (
const Scope& s)
const override
701 auto value = newValue->getResult (s);
702 target->assign (s, value);
711 struct PostAssignment :
public SelfAssignment
713 PostAssignment (
const CodeLocation& l, Expression* dest, Expression* source) noexcept : SelfAssignment (l, dest, source) {}
715 var getResult (
const Scope& s)
const override
717 auto oldValue = target->getResult (s);
718 target->assign (s, newValue->getResult (s));
723 struct FunctionCall :
public Expression
725 FunctionCall (
const CodeLocation& l) noexcept : Expression (l) {}
727 var getResult (
const Scope& s)
const override
729 if (
auto* dot =
dynamic_cast<DotOperator*
> (
object.get()))
731 auto thisObject = dot->parent->getResult (s);
732 return invokeFunction (s, s.findFunctionCall (location, thisObject, dot->child), thisObject);
735 auto function =
object->getResult (s);
736 return invokeFunction (s, function, var (s.scope.get()));
739 var invokeFunction (
const Scope& s,
const var& function,
const var& thisObject)
const
741 s.checkTimeOut (location);
744 for (
auto* a : arguments)
745 argVars.add (a->getResult (s));
747 const var::NativeFunctionArgs args (thisObject, argVars.begin(), argVars.size());
749 if (var::NativeFunction nativeFunction = function.getNativeFunction())
750 return nativeFunction (args);
752 if (
auto* fo =
dynamic_cast<FunctionObject*
> (function.getObject()))
753 return fo->invoke (s, args);
755 if (
auto* dot =
dynamic_cast<DotOperator*
> (
object.get()))
756 if (
auto* o = thisObject.getDynamicObject())
757 if (o->hasMethod (dot->child))
758 return o->invokeMethod (dot->child, args);
760 location.throwError (
"This expression is not a function!");
return {};
764 OwnedArray<Expression> arguments;
767 struct NewOperator :
public FunctionCall
769 NewOperator (
const CodeLocation& l) noexcept : FunctionCall (l) {}
771 var getResult (
const Scope& s)
const override
773 var classOrFunc =
object->getResult (s);
774 const bool isFunc = isFunction (classOrFunc);
776 if (! (isFunc || classOrFunc.getDynamicObject() !=
nullptr))
777 return var::undefined();
779 DynamicObject::Ptr newObject (
new DynamicObject());
782 invokeFunction (s, classOrFunc, newObject.get());
784 newObject->setProperty (getPrototypeIdentifier(), classOrFunc);
786 return newObject.get();
790 struct ObjectDeclaration :
public Expression
792 ObjectDeclaration (
const CodeLocation& l) noexcept : Expression (l) {}
794 var getResult (
const Scope& s)
const override
796 DynamicObject::Ptr newObject (
new DynamicObject());
798 for (
int i = 0; i < names.size(); ++i)
799 newObject->setProperty (names.getUnchecked(i), initialisers.getUnchecked(i)->getResult (s));
801 return newObject.get();
804 Array<Identifier> names;
805 OwnedArray<Expression> initialisers;
808 struct ArrayDeclaration :
public Expression
810 ArrayDeclaration (
const CodeLocation& l) noexcept : Expression (l) {}
812 var getResult (
const Scope& s)
const override
816 for (
int i = 0; i < values.size(); ++i)
817 a.add (values.getUnchecked(i)->getResult (s));
820 return std::move (a);
823 OwnedArray<Expression> values;
827 struct FunctionObject :
public DynamicObject
829 FunctionObject() noexcept {}
831 FunctionObject (
const FunctionObject& other) : DynamicObject(), functionCode (other.functionCode)
833 ExpressionTreeBuilder tb (functionCode);
834 tb.parseFunctionParamsAndBody (*
this);
837 DynamicObject::Ptr clone()
override {
return *
new FunctionObject (*
this); }
839 void writeAsJSON (OutputStream& out,
int ,
bool ,
int )
override
841 out <<
"function " << functionCode;
844 var invoke (
const Scope& s,
const var::NativeFunctionArgs& args)
const
846 DynamicObject::Ptr functionRoot (
new DynamicObject());
848 static const Identifier thisIdent (
"this");
849 functionRoot->setProperty (thisIdent, args.thisObject);
851 for (
int i = 0; i < parameters.size(); ++i)
852 functionRoot->setProperty (parameters.getReference(i),
853 i < args.numArguments ? args.arguments[i] : var::undefined());
856 body->perform (Scope (&s, s.root, functionRoot), &result);
861 Array<Identifier> parameters;
862 std::unique_ptr<Statement> body;
868 TokenIterator (
const String& code) : location (code), p (code.getCharPointer()) { skip(); }
872 skipWhitespaceAndComments();
873 location.location = p;
874 currentType = matchNextToken();
877 void match (TokenType expected)
879 if (currentType != expected)
880 location.throwError (
"Found " + getTokenName (currentType) +
" when expecting " + getTokenName (expected));
885 bool matchIf (TokenType expected) {
if (currentType == expected) { skip();
return true; }
return false; }
886 bool matchesAny (TokenType t1, TokenType t2)
const {
return currentType == t1 || currentType == t2; }
887 bool matchesAny (TokenType t1, TokenType t2, TokenType t3)
const {
return matchesAny (t1, t2) || currentType == t3; }
889 CodeLocation location;
890 TokenType currentType;
894 String::CharPointerType p;
896 static bool isIdentifierStart (juce_wchar c)
noexcept {
return CharacterFunctions::isLetter (c) || c ==
'_'; }
897 static bool isIdentifierBody (juce_wchar c)
noexcept {
return CharacterFunctions::isLetterOrDigit (c) || c ==
'_'; }
899 TokenType matchNextToken()
901 if (isIdentifierStart (*p))
904 while (isIdentifierBody (*++end)) {}
906 auto len = (size_t) (end - p);
907 #define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name;
908 JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD)
910 currentValue = String (p, end); p = end;
911 return TokenTypes::identifier;
916 if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
917 return TokenTypes::literal;
919 location.throwError (
"Syntax error in numeric constant");
922 if (parseStringLiteral (*p) || (*p ==
'.' && parseFloatLiteral()))
923 return TokenTypes::literal;
925 #define JUCE_JS_COMPARE_OPERATOR(name, str) if (matchToken (TokenTypes::name, sizeof (str) - 1)) return TokenTypes::name;
926 JUCE_JS_OPERATORS (JUCE_JS_COMPARE_OPERATOR)
929 location.throwError (
"Unexpected character '" + String::charToString (*p) +
"' in source");
931 return TokenTypes::eof;
934 bool matchToken (TokenType name,
size_t len)
noexcept
936 if (p.compareUpTo (CharPointer_ASCII (name), (
int) len) != 0)
return false;
937 p += (int) len;
return true;
940 void skipWhitespaceAndComments()
944 p = p.findEndOfWhitespace();
950 if (c2 ==
'/') { p = CharacterFunctions::find (p, (juce_wchar)
'\n');
continue; }
954 location.location = p;
955 p = CharacterFunctions::find (p + 2, CharPointer_ASCII (
"*/"));
956 if (p.isEmpty()) location.throwError (
"Unterminated '/*' comment");
965 bool parseStringLiteral (juce_wchar quoteType)
967 if (quoteType !=
'"' && quoteType !=
'\'')
970 auto r = JSON::parseQuotedString (p, currentValue);
971 if (r.failed()) location.throwError (r.getErrorMessage());
975 bool parseHexLiteral()
977 if (*p !=
'0' || (p[1] !=
'x' && p[1] !=
'X'))
return false;
980 int64 v = CharacterFunctions::getHexDigitValue (*++t);
981 if (v < 0)
return false;
985 auto digit = CharacterFunctions::getHexDigitValue (*++t);
986 if (digit < 0)
break;
990 currentValue = v; p = t;
994 bool parseFloatLiteral()
998 while (t.isDigit()) { ++t; ++numDigits; }
1000 const bool hasPoint = (*t ==
'.');
1003 while ((++t).isDigit()) ++numDigits;
1009 const bool hasExponent = (c ==
'e' || c ==
'E');
1014 if (c ==
'+' || c ==
'-') ++t;
1015 if (! t.isDigit())
return false;
1016 while ((++t).isDigit()) {}
1019 if (! (hasExponent || hasPoint))
return false;
1021 currentValue = CharacterFunctions::getDoubleValue (p); p = t;
1025 bool parseOctalLiteral()
1029 if (v != 0)
return false;
1033 auto digit = (int) (*++t -
'0');
1034 if (isPositiveAndBelow (digit, 8)) v = v * 8 + digit;
1035 else if (isPositiveAndBelow (digit, 10)) location.throwError (
"Decimal digit in octal constant");
1039 currentValue = v; p = t;
1043 bool parseDecimalLiteral()
1049 auto digit = (int) (*p -
'0');
1050 if (isPositiveAndBelow (digit, 10)) v = v * 10 + digit;
1060 struct ExpressionTreeBuilder :
private TokenIterator
1062 ExpressionTreeBuilder (
const String code) : TokenIterator (code) {}
1064 BlockStatement* parseStatementList()
1066 std::unique_ptr<BlockStatement> b (
new BlockStatement (location));
1068 while (currentType != TokenTypes::closeBrace && currentType != TokenTypes::eof)
1069 b->statements.add (parseStatement());
1074 void parseFunctionParamsAndBody (FunctionObject& fo)
1076 match (TokenTypes::openParen);
1078 while (currentType != TokenTypes::closeParen)
1080 auto paramName = currentValue.toString();
1081 match (TokenTypes::identifier);
1082 fo.parameters.add (paramName);
1084 if (currentType != TokenTypes::closeParen)
1085 match (TokenTypes::comma);
1088 match (TokenTypes::closeParen);
1089 fo.body.reset (parseBlock());
1092 Expression* parseExpression()
1094 ExpPtr lhs (parseLogicOperator());
1096 if (matchIf (TokenTypes::question))
return parseTernaryOperator (lhs);
1097 if (matchIf (TokenTypes::assign)) { ExpPtr rhs (parseExpression());
return new Assignment (location, lhs, rhs); }
1098 if (matchIf (TokenTypes::plusEquals))
return parseInPlaceOpExpression<AdditionOp> (lhs);
1099 if (matchIf (TokenTypes::minusEquals))
return parseInPlaceOpExpression<SubtractionOp> (lhs);
1100 if (matchIf (TokenTypes::timesEquals))
return parseInPlaceOpExpression<MultiplyOp> (lhs);
1101 if (matchIf (TokenTypes::divideEquals))
return parseInPlaceOpExpression<DivideOp> (lhs);
1102 if (matchIf (TokenTypes::moduloEquals))
return parseInPlaceOpExpression<ModuloOp> (lhs);
1103 if (matchIf (TokenTypes::leftShiftEquals))
return parseInPlaceOpExpression<LeftShiftOp> (lhs);
1104 if (matchIf (TokenTypes::rightShiftEquals))
return parseInPlaceOpExpression<RightShiftOp> (lhs);
1106 return lhs.release();
1110 void throwError (
const String& err)
const { location.throwError (err); }
1112 template <
typename OpType>
1113 Expression* parseInPlaceOpExpression (ExpPtr& lhs)
1115 ExpPtr rhs (parseExpression());
1116 Expression* bareLHS = lhs.get();
1117 return new SelfAssignment (location, bareLHS,
new OpType (location, lhs, rhs));
1120 BlockStatement* parseBlock()
1122 match (TokenTypes::openBrace);
1123 std::unique_ptr<BlockStatement> b (parseStatementList());
1124 match (TokenTypes::closeBrace);
1128 Statement* parseStatement()
1130 if (currentType == TokenTypes::openBrace)
return parseBlock();
1131 if (matchIf (TokenTypes::var))
return parseVar();
1132 if (matchIf (TokenTypes::if_))
return parseIf();
1133 if (matchIf (TokenTypes::while_))
return parseDoOrWhileLoop (
false);
1134 if (matchIf (TokenTypes::do_))
return parseDoOrWhileLoop (
true);
1135 if (matchIf (TokenTypes::for_))
return parseForLoop();
1136 if (matchIf (TokenTypes::return_))
return parseReturn();
1137 if (matchIf (TokenTypes::break_))
return new BreakStatement (location);
1138 if (matchIf (TokenTypes::continue_))
return new ContinueStatement (location);
1139 if (matchIf (TokenTypes::function))
return parseFunction();
1140 if (matchIf (TokenTypes::semicolon))
return new Statement (location);
1141 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1142 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1144 if (matchesAny (TokenTypes::openParen, TokenTypes::openBracket))
1145 return matchEndOfStatement (parseFactor());
1147 if (matchesAny (TokenTypes::identifier, TokenTypes::literal, TokenTypes::minus))
1148 return matchEndOfStatement (parseExpression());
1150 throwError (
"Found " + getTokenName (currentType) +
" when expecting a statement");
1154 Expression* matchEndOfStatement (Expression* ex) { ExpPtr e (ex);
if (currentType != TokenTypes::eof) match (TokenTypes::semicolon);
return e.release(); }
1155 Expression* matchCloseParen (Expression* ex) { ExpPtr e (ex); match (TokenTypes::closeParen);
return e.release(); }
1157 Statement* parseIf()
1159 std::unique_ptr<IfStatement> s (
new IfStatement (location));
1160 match (TokenTypes::openParen);
1161 s->condition.reset (parseExpression());
1162 match (TokenTypes::closeParen);
1163 s->trueBranch.reset (parseStatement());
1164 s->falseBranch.reset (matchIf (TokenTypes::else_) ? parseStatement() : new Statement (location));
1168 Statement* parseReturn()
1170 if (matchIf (TokenTypes::semicolon))
1171 return new ReturnStatement (location,
new Expression (location));
1173 auto* r =
new ReturnStatement (location, parseExpression());
1174 matchIf (TokenTypes::semicolon);
1178 Statement* parseVar()
1180 std::unique_ptr<VarStatement> s (
new VarStatement (location));
1181 s->name = parseIdentifier();
1182 s->initialiser.reset (matchIf (TokenTypes::assign) ? parseExpression() : new Expression (location));
1184 if (matchIf (TokenTypes::comma))
1186 std::unique_ptr<BlockStatement> block (
new BlockStatement (location));
1187 block->statements.add (std::move (s));
1188 block->statements.add (parseVar());
1189 return block.release();
1192 match (TokenTypes::semicolon);
1196 Statement* parseFunction()
1199 auto fn = parseFunctionDefinition (name);
1202 throwError (
"Functions defined at statement-level must have a name");
1204 ExpPtr nm (
new UnqualifiedName (location, name)), value (
new LiteralValue (location, fn));
1205 return new Assignment (location, nm, value);
1208 Statement* parseForLoop()
1210 std::unique_ptr<LoopStatement> s (
new LoopStatement (location,
false));
1211 match (TokenTypes::openParen);
1212 s->initialiser.reset (parseStatement());
1214 if (matchIf (TokenTypes::semicolon))
1215 s->condition.reset (
new LiteralValue (location,
true));
1218 s->condition.reset (parseExpression());
1219 match (TokenTypes::semicolon);
1222 if (matchIf (TokenTypes::closeParen))
1223 s->iterator.reset (
new Statement (location));
1226 s->iterator.reset (parseExpression());
1227 match (TokenTypes::closeParen);
1230 s->body.reset (parseStatement());
1234 Statement* parseDoOrWhileLoop (
bool isDoLoop)
1236 std::unique_ptr<LoopStatement> s (
new LoopStatement (location, isDoLoop));
1237 s->initialiser.reset (
new Statement (location));
1238 s->iterator.reset (
new Statement (location));
1242 s->body.reset (parseBlock());
1243 match (TokenTypes::while_);
1246 match (TokenTypes::openParen);
1247 s->condition.reset (parseExpression());
1248 match (TokenTypes::closeParen);
1251 s->body.reset (parseStatement());
1256 Identifier parseIdentifier()
1259 if (currentType == TokenTypes::identifier)
1260 i = currentValue.toString();
1262 match (TokenTypes::identifier);
1266 var parseFunctionDefinition (Identifier& functionName)
1268 auto functionStart = location.location;
1270 if (currentType == TokenTypes::identifier)
1271 functionName = parseIdentifier();
1273 std::unique_ptr<FunctionObject> fo (
new FunctionObject());
1274 parseFunctionParamsAndBody (*fo);
1275 fo->functionCode = String (functionStart, location.location);
1276 return var (fo.release());
1279 Expression* parseFunctionCall (FunctionCall* call, ExpPtr& function)
1281 std::unique_ptr<FunctionCall> s (call);
1282 s->object.reset (function.release());
1283 match (TokenTypes::openParen);
1285 while (currentType != TokenTypes::closeParen)
1287 s->arguments.add (parseExpression());
1288 if (currentType != TokenTypes::closeParen)
1289 match (TokenTypes::comma);
1292 return matchCloseParen (s.release());
1295 Expression* parseSuffixes (Expression* e)
1299 if (matchIf (TokenTypes::dot))
1300 return parseSuffixes (
new DotOperator (location, input, parseIdentifier()));
1302 if (currentType == TokenTypes::openParen)
1303 return parseSuffixes (parseFunctionCall (
new FunctionCall (location), input));
1305 if (matchIf (TokenTypes::openBracket))
1307 std::unique_ptr<ArraySubscript> s (
new ArraySubscript (location));
1308 s->object.reset (input.release());
1309 s->index.reset (parseExpression());
1310 match (TokenTypes::closeBracket);
1311 return parseSuffixes (s.release());
1314 if (matchIf (TokenTypes::plusplus))
return parsePostIncDec<AdditionOp> (input);
1315 if (matchIf (TokenTypes::minusminus))
return parsePostIncDec<SubtractionOp> (input);
1317 return input.release();
1320 Expression* parseFactor()
1322 if (currentType == TokenTypes::identifier)
return parseSuffixes (
new UnqualifiedName (location, parseIdentifier()));
1323 if (matchIf (TokenTypes::openParen))
return parseSuffixes (matchCloseParen (parseExpression()));
1324 if (matchIf (TokenTypes::true_))
return parseSuffixes (
new LiteralValue (location, (
int) 1));
1325 if (matchIf (TokenTypes::false_))
return parseSuffixes (
new LiteralValue (location, (
int) 0));
1326 if (matchIf (TokenTypes::null_))
return parseSuffixes (
new LiteralValue (location, var()));
1327 if (matchIf (TokenTypes::undefined))
return parseSuffixes (
new Expression (location));
1329 if (currentType == TokenTypes::literal)
1331 var v (currentValue); skip();
1332 return parseSuffixes (
new LiteralValue (location, v));
1335 if (matchIf (TokenTypes::openBrace))
1337 std::unique_ptr<ObjectDeclaration> e (
new ObjectDeclaration (location));
1339 while (currentType != TokenTypes::closeBrace)
1341 auto memberName = currentValue.toString();
1342 match ((currentType == TokenTypes::literal && currentValue.isString())
1343 ? TokenTypes::literal : TokenTypes::identifier);
1344 match (TokenTypes::colon);
1346 e->names.add (memberName);
1347 e->initialisers.add (parseExpression());
1349 if (currentType != TokenTypes::closeBrace)
1350 match (TokenTypes::comma);
1353 match (TokenTypes::closeBrace);
1354 return parseSuffixes (e.release());
1357 if (matchIf (TokenTypes::openBracket))
1359 std::unique_ptr<ArrayDeclaration> e (
new ArrayDeclaration (location));
1361 while (currentType != TokenTypes::closeBracket)
1363 e->values.add (parseExpression());
1365 if (currentType != TokenTypes::closeBracket)
1366 match (TokenTypes::comma);
1369 match (TokenTypes::closeBracket);
1370 return parseSuffixes (e.release());
1373 if (matchIf (TokenTypes::function))
1376 var fn = parseFunctionDefinition (name);
1379 throwError (
"Inline functions definitions cannot have a name");
1381 return new LiteralValue (location, fn);
1384 if (matchIf (TokenTypes::new_))
1386 ExpPtr name (
new UnqualifiedName (location, parseIdentifier()));
1388 while (matchIf (TokenTypes::dot))
1389 name.reset (
new DotOperator (location, name, parseIdentifier()));
1391 return parseFunctionCall (
new NewOperator (location), name);
1394 throwError (
"Found " + getTokenName (currentType) +
" when expecting an expression");
1398 template <
typename OpType>
1399 Expression* parsePreIncDec()
1401 Expression* e = parseFactor();
1402 ExpPtr lhs (e), one (
new LiteralValue (location, (
int) 1));
1403 return new SelfAssignment (location, e,
new OpType (location, lhs, one));
1406 template <
typename OpType>
1407 Expression* parsePostIncDec (ExpPtr& lhs)
1409 Expression* e = lhs.release();
1410 ExpPtr lhs2 (e), one (
new LiteralValue (location, (
int) 1));
1411 return new PostAssignment (location, e,
new OpType (location, lhs2, one));
1414 Expression* parseTypeof()
1416 std::unique_ptr<FunctionCall> f (
new FunctionCall (location));
1417 f->object.reset (
new UnqualifiedName (location,
"typeof"));
1418 f->arguments.add (parseUnary());
1422 Expression* parseUnary()
1424 if (matchIf (TokenTypes::minus)) { ExpPtr a (
new LiteralValue (location, (
int) 0)), b (parseUnary());
return new SubtractionOp (location, a, b); }
1425 if (matchIf (TokenTypes::logicalNot)) { ExpPtr a (
new LiteralValue (location, (
int) 0)), b (parseUnary());
return new EqualsOp (location, a, b); }
1426 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1427 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1428 if (matchIf (TokenTypes::typeof_))
return parseTypeof();
1430 return parseFactor();
1433 Expression* parseMultiplyDivide()
1435 ExpPtr a (parseUnary());
1439 if (matchIf (TokenTypes::times)) { ExpPtr b (parseUnary()); a.reset (
new MultiplyOp (location, a, b)); }
1440 else if (matchIf (TokenTypes::divide)) { ExpPtr b (parseUnary()); a.reset (
new DivideOp (location, a, b)); }
1441 else if (matchIf (TokenTypes::modulo)) { ExpPtr b (parseUnary()); a.reset (
new ModuloOp (location, a, b)); }
1448 Expression* parseAdditionSubtraction()
1450 ExpPtr a (parseMultiplyDivide());
1454 if (matchIf (TokenTypes::plus)) { ExpPtr b (parseMultiplyDivide()); a.reset (
new AdditionOp (location, a, b)); }
1455 else if (matchIf (TokenTypes::minus)) { ExpPtr b (parseMultiplyDivide()); a.reset (
new SubtractionOp (location, a, b)); }
1462 Expression* parseShiftOperator()
1464 ExpPtr a (parseAdditionSubtraction());
1468 if (matchIf (TokenTypes::leftShift)) { ExpPtr b (parseExpression()); a.reset (
new LeftShiftOp (location, a, b)); }
1469 else if (matchIf (TokenTypes::rightShift)) { ExpPtr b (parseExpression()); a.reset (
new RightShiftOp (location, a, b)); }
1470 else if (matchIf (TokenTypes::rightShiftUnsigned)) { ExpPtr b (parseExpression()); a.reset (
new RightShiftUnsignedOp (location, a, b)); }
1477 Expression* parseComparator()
1479 ExpPtr a (parseShiftOperator());
1483 if (matchIf (TokenTypes::equals)) { ExpPtr b (parseShiftOperator()); a.reset (
new EqualsOp (location, a, b)); }
1484 else if (matchIf (TokenTypes::notEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new NotEqualsOp (location, a, b)); }
1485 else if (matchIf (TokenTypes::typeEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new TypeEqualsOp (location, a, b)); }
1486 else if (matchIf (TokenTypes::typeNotEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new TypeNotEqualsOp (location, a, b)); }
1487 else if (matchIf (TokenTypes::lessThan)) { ExpPtr b (parseShiftOperator()); a.reset (
new LessThanOp (location, a, b)); }
1488 else if (matchIf (TokenTypes::lessThanOrEqual)) { ExpPtr b (parseShiftOperator()); a.reset (
new LessThanOrEqualOp (location, a, b)); }
1489 else if (matchIf (TokenTypes::greaterThan)) { ExpPtr b (parseShiftOperator()); a.reset (
new GreaterThanOp (location, a, b)); }
1490 else if (matchIf (TokenTypes::greaterThanOrEqual)) { ExpPtr b (parseShiftOperator()); a.reset (
new GreaterThanOrEqualOp (location, a, b)); }
1497 Expression* parseLogicOperator()
1499 ExpPtr a (parseComparator());
1503 if (matchIf (TokenTypes::logicalAnd)) { ExpPtr b (parseComparator()); a.reset (
new LogicalAndOp (location, a, b)); }
1504 else if (matchIf (TokenTypes::logicalOr)) { ExpPtr b (parseComparator()); a.reset (
new LogicalOrOp (location, a, b)); }
1505 else if (matchIf (TokenTypes::bitwiseAnd)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseAndOp (location, a, b)); }
1506 else if (matchIf (TokenTypes::bitwiseOr)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseOrOp (location, a, b)); }
1507 else if (matchIf (TokenTypes::bitwiseXor)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseXorOp (location, a, b)); }
1514 Expression* parseTernaryOperator (ExpPtr& condition)
1516 std::unique_ptr<ConditionalOp> e (
new ConditionalOp (location));
1517 e->condition.reset (condition.release());
1518 e->trueBranch.reset (parseExpression());
1519 match (TokenTypes::colon);
1520 e->falseBranch.reset (parseExpression());
1524 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ExpressionTreeBuilder)
1528 static var get (Args a,
int index)
noexcept {
return index < a.numArguments ? a.arguments[index] : var(); }
1529 static bool isInt (Args a,
int index)
noexcept {
return get (a, index).isInt() || get (a, index).isInt64(); }
1530 static int getInt (Args a,
int index)
noexcept {
return get (a, index); }
1531 static double getDouble (Args a,
int index)
noexcept {
return get (a, index); }
1532 static String getString (Args a,
int index)
noexcept {
return get (a, index).toString(); }
1535 struct ObjectClass :
public DynamicObject
1539 setMethod (
"dump", dump);
1540 setMethod (
"clone", cloneFn);
1543 static Identifier getClassName() {
static const Identifier i (
"Object");
return i; }
1544 static var dump (Args a) { DBG (JSON::toString (a.thisObject)); ignoreUnused (a);
return var::undefined(); }
1545 static var cloneFn (Args a) {
return a.thisObject.clone(); }
1549 struct ArrayClass :
public DynamicObject
1553 setMethod (
"contains", contains);
1554 setMethod (
"remove", remove);
1555 setMethod (
"join", join);
1556 setMethod (
"push", push);
1557 setMethod (
"splice", splice);
1558 setMethod (
"indexOf", indexOf);
1561 static Identifier getClassName() {
static const Identifier i (
"Array");
return i; }
1563 static var contains (Args a)
1565 if (
auto* array = a.thisObject.getArray())
1566 return array->contains (get (a, 0));
1571 static var remove (Args a)
1573 if (
auto* array = a.thisObject.getArray())
1574 array->removeAllInstancesOf (get (a, 0));
1576 return var::undefined();
1579 static var join (Args a)
1581 StringArray strings;
1583 if (
auto* array = a.thisObject.getArray())
1584 for (
auto& v : *array)
1585 strings.add (v.toString());
1587 return strings.joinIntoString (getString (a, 0));
1590 static var push (Args a)
1592 if (
auto* array = a.thisObject.getArray())
1594 for (
int i = 0; i < a.numArguments; ++i)
1595 array->add (a.arguments[i]);
1597 return array->size();
1600 return var::undefined();
1603 static var splice (Args a)
1605 if (
auto* array = a.thisObject.getArray())
1607 auto arraySize = array->size();
1608 int start = get (a, 0);
1611 start = jmax (0, arraySize + start);
1612 else if (start > arraySize)
1615 const int num = a.numArguments > 1 ? jlimit (0, arraySize - start, getInt (a, 1))
1616 : arraySize - start;
1618 Array<var> itemsRemoved;
1619 itemsRemoved.ensureStorageAllocated (num);
1621 for (
int i = 0; i < num; ++i)
1622 itemsRemoved.add (array->getReference (start + i));
1624 array->removeRange (start, num);
1626 for (
int i = 2; i < a.numArguments; ++i)
1627 array->insert (start++, get (a, i));
1630 return std::move (itemsRemoved);
1633 return var::undefined();
1636 static var indexOf (Args a)
1638 if (
auto* array = a.thisObject.getArray())
1640 auto target = get (a, 0);
1642 for (
int i = (a.numArguments > 1 ? getInt (a, 1) : 0); i < array->size(); ++i)
1643 if (array->getReference(i) == target)
1652 struct StringClass :
public DynamicObject
1656 setMethod (
"substring", substring);
1657 setMethod (
"indexOf", indexOf);
1658 setMethod (
"charAt", charAt);
1659 setMethod (
"charCodeAt", charCodeAt);
1660 setMethod (
"fromCharCode", fromCharCode);
1661 setMethod (
"split", split);
1664 static Identifier getClassName() {
static const Identifier i (
"String");
return i; }
1666 static var fromCharCode (Args a) {
return String::charToString (
static_cast<juce_wchar
> (getInt (a, 0))); }
1667 static var substring (Args a) {
return a.thisObject.toString().substring (getInt (a, 0), getInt (a, 1)); }
1668 static var indexOf (Args a) {
return a.thisObject.toString().indexOf (getString (a, 0)); }
1669 static var charCodeAt (Args a) {
return (
int) a.thisObject.toString() [getInt (a, 0)]; }
1670 static var charAt (Args a) {
int p = getInt (a, 0);
return a.thisObject.toString().substring (p, p + 1); }
1672 static var split (Args a)
1674 auto str = a.thisObject.toString();
1675 auto sep = getString (a, 0);
1676 StringArray strings;
1678 if (sep.isNotEmpty())
1679 strings.addTokens (str, sep.substring (0, 1), {});
1681 for (
auto pos = str.getCharPointer(); ! pos.isEmpty(); ++pos)
1682 strings.add (String::charToString (*pos));
1686 for (
auto& s : strings)
1694 struct MathClass :
public DynamicObject
1698 setMethod (
"abs", Math_abs); setMethod (
"round", Math_round);
1699 setMethod (
"random", Math_random); setMethod (
"randInt", Math_randInt);
1700 setMethod (
"min", Math_min); setMethod (
"max", Math_max);
1701 setMethod (
"range", Math_range); setMethod (
"sign", Math_sign);
1702 setMethod (
"toDegrees", Math_toDegrees); setMethod (
"toRadians", Math_toRadians);
1703 setMethod (
"sin", Math_sin); setMethod (
"asin", Math_asin);
1704 setMethod (
"sinh", Math_sinh); setMethod (
"asinh", Math_asinh);
1705 setMethod (
"cos", Math_cos); setMethod (
"acos", Math_acos);
1706 setMethod (
"cosh", Math_cosh); setMethod (
"acosh", Math_acosh);
1707 setMethod (
"tan", Math_tan); setMethod (
"atan", Math_atan);
1708 setMethod (
"tanh", Math_tanh); setMethod (
"atanh", Math_atanh);
1709 setMethod (
"log", Math_log); setMethod (
"log10", Math_log10);
1710 setMethod (
"exp", Math_exp); setMethod (
"pow", Math_pow);
1711 setMethod (
"sqr", Math_sqr); setMethod (
"sqrt", Math_sqrt);
1712 setMethod (
"ceil", Math_ceil); setMethod (
"floor", Math_floor);
1714 setProperty (
"PI", MathConstants<double>::pi);
1715 setProperty (
"E", MathConstants<double>::euler);
1716 setProperty (
"SQRT2", MathConstants<double>::sqrt2);
1717 setProperty (
"SQRT1_2", std::sqrt (0.5));
1718 setProperty (
"LN2", std::log (2.0));
1719 setProperty (
"LN10", std::log (10.0));
1720 setProperty (
"LOG2E", std::log (MathConstants<double>::euler) / std::log (2.0));
1721 setProperty (
"LOG10E", std::log (MathConstants<double>::euler) / std::log (10.0));
1724 static var Math_random (Args) {
return Random::getSystemRandom().nextDouble(); }
1725 static var Math_randInt (Args a) {
return Random::getSystemRandom().nextInt (Range<int> (getInt (a, 0), getInt (a, 1))); }
1726 static var Math_abs (Args a) {
return isInt (a, 0) ? var (std::abs (getInt (a, 0))) : var (std::abs (getDouble (a, 0))); }
1727 static var Math_round (Args a) {
return isInt (a, 0) ? var (roundToInt (getInt (a, 0))) : var (roundToInt (getDouble (a, 0))); }
1728 static var Math_sign (Args a) {
return isInt (a, 0) ? var (sign (getInt (a, 0))) : var (sign (getDouble (a, 0))); }
1729 static var Math_range (Args a) {
return isInt (a, 0) ? var (jlimit (getInt (a, 1), getInt (a, 2), getInt (a, 0))) : var (jlimit (getDouble (a, 1), getDouble (a, 2), getDouble (a, 0))); }
1730 static var Math_min (Args a) {
return (isInt (a, 0) && isInt (a, 1)) ? var (jmin (getInt (a, 0), getInt (a, 1))) : var (jmin (getDouble (a, 0), getDouble (a, 1))); }
1731 static var Math_max (Args a) {
return (isInt (a, 0) && isInt (a, 1)) ? var (jmax (getInt (a, 0), getInt (a, 1))) : var (jmax (getDouble (a, 0), getDouble (a, 1))); }
1732 static var Math_toDegrees (Args a) {
return radiansToDegrees (getDouble (a, 0)); }
1733 static var Math_toRadians (Args a) {
return degreesToRadians (getDouble (a, 0)); }
1734 static var Math_sin (Args a) {
return std::sin (getDouble (a, 0)); }
1735 static var Math_asin (Args a) {
return std::asin (getDouble (a, 0)); }
1736 static var Math_cos (Args a) {
return std::cos (getDouble (a, 0)); }
1737 static var Math_acos (Args a) {
return std::acos (getDouble (a, 0)); }
1738 static var Math_sinh (Args a) {
return std::sinh (getDouble (a, 0)); }
1739 static var Math_cosh (Args a) {
return std::cosh (getDouble (a, 0)); }
1740 static var Math_tan (Args a) {
return std::tan (getDouble (a, 0)); }
1741 static var Math_tanh (Args a) {
return std::tanh (getDouble (a, 0)); }
1742 static var Math_atan (Args a) {
return std::atan (getDouble (a, 0)); }
1743 static var Math_log (Args a) {
return std::log (getDouble (a, 0)); }
1744 static var Math_log10 (Args a) {
return std::log10 (getDouble (a, 0)); }
1745 static var Math_exp (Args a) {
return std::exp (getDouble (a, 0)); }
1746 static var Math_pow (Args a) {
return std::pow (getDouble (a, 0), getDouble (a, 1)); }
1747 static var Math_sqr (Args a) {
return square (getDouble (a, 0)); }
1748 static var Math_sqrt (Args a) {
return std::sqrt (getDouble (a, 0)); }
1749 static var Math_ceil (Args a) {
return std::ceil (getDouble (a, 0)); }
1750 static var Math_floor (Args a) {
return std::floor (getDouble (a, 0)); }
1754 static var Math_asinh (Args a) {
return asinh (getDouble (a, 0)); }
1755 static var Math_acosh (Args a) {
return acosh (getDouble (a, 0)); }
1756 static var Math_atanh (Args a) {
return atanh (getDouble (a, 0)); }
1758 static Identifier getClassName() {
static const Identifier i (
"Math");
return i; }
1759 template <
typename Type>
static Type sign (Type n)
noexcept {
return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); }
1763 struct JSONClass :
public DynamicObject
1765 JSONClass() { setMethod (
"stringify", stringify); }
1766 static Identifier getClassName() {
static const Identifier i (
"JSON");
return i; }
1767 static var stringify (Args a) {
return JSON::toString (get (a, 0)); }
1771 struct IntegerClass :
public DynamicObject
1773 IntegerClass() { setMethod (
"parseInt", parseInt); }
1774 static Identifier getClassName() {
static const Identifier i (
"Integer");
return i; }
1776 static var parseInt (Args a)
1778 auto s = getString (a, 0).trim();
1780 return s[0] ==
'0' ? (s[1] ==
'x' ? s.substring(2).getHexValue64() : getOctalValue (s))
1781 : s.getLargeIntValue();
1786 static var trace (Args a) { Logger::outputDebugString (JSON::toString (a.thisObject));
return var::undefined(); }
1787 static var charToInt (Args a) {
return (
int) (getString (a, 0)[0]); }
1788 static var parseFloat (Args a) {
return getDouble (a, 0); }
1790 static var typeof_internal (Args a)
1794 if (v.isVoid())
return "void";
1795 if (v.isString())
return "string";
1796 if (isNumeric (v))
return "number";
1797 if (isFunction (v) || v.isMethod())
return "function";
1798 if (v.isObject())
return "object";
1803 static var exec (Args a)
1805 if (
auto* root =
dynamic_cast<RootObject*
> (a.thisObject.getObject()))
1806 root->execute (getString (a, 0));
1808 return var::undefined();
1811 static var eval (Args a)
1813 if (
auto* root =
dynamic_cast<RootObject*
> (a.thisObject.getObject()))
1814 return root->evaluate (getString (a, 0));
1816 return var::undefined();
1823 registerNativeObject (RootObject::ObjectClass ::getClassName(),
new RootObject::ObjectClass());
1825 registerNativeObject (RootObject::StringClass ::getClassName(),
new RootObject::StringClass());
1828 registerNativeObject (RootObject::IntegerClass ::getClassName(),
new RootObject::IntegerClass());
1838 root->setProperty (name,
object);
1846 root->execute (
code);
1861 if (result !=
nullptr) *result =
Result::ok();
1862 return root->evaluate (
code);
1879 if (result !=
nullptr) *result =
Result::ok();
1880 RootObject::Scope ({}, *root, *root).findAndInvokeMethod (function,
args,
returnVal);
1898 if (result !=
nullptr) *result =
Result::ok();
1899 RootObject::Scope
rootScope ({}, *root, *root);
1913 return root->getProperties();
1917 #pragma warning (pop)
const NamedValueSet & getRootObjectProperties() const noexcept
Result execute(const String &javascriptCode)
var callFunction(const Identifier &function, const var::NativeFunctionArgs &args, Result *errorMessage=nullptr)
var evaluate(const String &javascriptCode, Result *errorMessage=nullptr)
void registerNativeObject(const Identifier &objectName, DynamicObject *object)
var callFunctionObject(DynamicObject *objectScope, const var &functionObject, const var::NativeFunctionArgs &args, Result *errorMessage=nullptr)
RelativeTime maximumExecutionTime
static Result fail(const String &errorMessage) noexcept
static Result ok() noexcept
static Time JUCE_CALLTYPE getCurrentTime() noexcept
static var undefined() noexcept