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")
57JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)
60struct JavascriptEngine::RootObject final : public DynamicObject
64 setMethod (
"exec", exec);
65 setMethod (
"eval", eval);
66 setMethod (
"trace", trace);
67 setMethod (
"charToInt", charToInt);
68 setMethod (
"parseInt", IntegerClass::parseInt);
69 setMethod (
"typeof", typeof_internal);
70 setMethod (
"parseFloat", parseFloat);
75 using Args =
const var::NativeFunctionArgs&;
76 using TokenType =
const char*;
78 void execute (
const String& code)
80 ExpressionTreeBuilder tb (code);
81 std::unique_ptr<BlockStatement> (tb.parseStatementList())->perform (Scope ({}, *
this, *
this),
nullptr);
84 var evaluate (
const String& code)
86 ExpressionTreeBuilder tb (code);
87 return ExpPtr (tb.parseExpression())->getResult (Scope ({}, *
this, *
this));
91 static bool areTypeEqual (
const var& a,
const var& b)
93 return a.hasSameTypeAs (b) && isFunction (a) == isFunction (b)
94 && (((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid())) || a == b);
97 static String getTokenName (TokenType t) {
return t[0] ==
'$' ? String (t + 1) : (
"'" + String (t) +
"'"); }
98 static bool isFunction (
const var& v)
noexcept {
return dynamic_cast<FunctionObject*
> (v.getObject()) !=
nullptr; }
99 static bool isNumeric (
const var& v)
noexcept {
return v.isInt() || v.isDouble() || v.isInt64() || v.isBool(); }
100 static bool isNumericOrUndefined (
const var& v)
noexcept {
return isNumeric (v) || v.isUndefined(); }
101 static int64 getOctalValue (
const String& s) { BigInteger b; b.parseString (s.initialSectionContainingOnly (
"01234567"), 8);
return b.toInt64(); }
102 static Identifier getPrototypeIdentifier() {
static const Identifier i (
"prototype");
return i; }
103 static var* getPropertyPointer (DynamicObject& o,
const Identifier& i)
noexcept {
return o.getProperties().getVarPointer (i); }
108 CodeLocation (
const String& code) noexcept : program (code), location (program.getCharPointer()) {}
109 CodeLocation (
const CodeLocation& other) noexcept : program (other.program), location (other.location) {}
111 void throwError (
const String& message)
const
113 int col = 1, line = 1;
115 for (
auto i = program.getCharPointer(); i < location && ! i.isEmpty(); ++i)
118 if (*i ==
'\n') { col = 1; ++line; }
121 throw "Line " + String (line) +
", column " + String (col) +
" : " + message;
125 String::CharPointerType location;
131 Scope (
const Scope* p, ReferenceCountedObjectPtr<RootObject> rt, DynamicObject::Ptr scp) noexcept
132 : parent (p), root (std::move (rt)),
133 scope (std::move (scp)) {}
135 const Scope*
const parent;
136 ReferenceCountedObjectPtr<RootObject> root;
137 DynamicObject::Ptr scope;
139 var findFunctionCall (
const CodeLocation& location,
const var& targetObject,
const Identifier& functionName)
const
141 if (
auto* o = targetObject.getDynamicObject())
143 if (
auto* prop = getPropertyPointer (*o, functionName))
146 for (
auto* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p !=
nullptr;
147 p = p->getProperty (getPrototypeIdentifier()).getDynamicObject())
149 if (
auto* prop = getPropertyPointer (*p, functionName))
154 if (o->hasMethod (functionName))
158 if (targetObject.isString())
159 if (
auto* m = findRootClassProperty (StringClass::getClassName(), functionName))
162 if (targetObject.isArray())
163 if (
auto* m = findRootClassProperty (ArrayClass::getClassName(), functionName))
166 if (
auto* m = findRootClassProperty (ObjectClass::getClassName(), functionName))
169 location.throwError (
"Unknown function '" + functionName.toString() +
"'");
173 var* findRootClassProperty (
const Identifier& className,
const Identifier& propName)
const
175 if (
auto* cls = root->getProperty (className).getDynamicObject())
176 return getPropertyPointer (*cls, propName);
181 var findSymbolInParentScopes (
const Identifier& name)
const
183 if (
auto v = getPropertyPointer (*scope, name))
186 return parent !=
nullptr ? parent->findSymbolInParentScopes (name)
190 bool findAndInvokeMethod (
const Identifier& function,
const var::NativeFunctionArgs& args, var& result)
const
192 auto* target = args.thisObject.getDynamicObject();
194 if (target ==
nullptr || target == scope.get())
196 if (
auto* m = getPropertyPointer (*scope, function))
198 if (
auto fo =
dynamic_cast<FunctionObject*
> (m->getObject()))
200 result = fo->invoke (*
this, args);
206 const auto& props = scope->getProperties();
208 for (
int i = 0; i < props.size(); ++i)
209 if (
auto* o = props.getValueAt (i).getDynamicObject())
210 if (Scope (
this, *root, *o).findAndInvokeMethod (function, args, result))
216 bool invokeMethod (
const var& m,
const var::NativeFunctionArgs& args, var& result)
const
220 auto* target = args.thisObject.getDynamicObject();
222 if (target ==
nullptr || target == scope.get())
224 if (
auto fo =
dynamic_cast<FunctionObject*
> (m.getObject()))
226 result = fo->invoke (*
this, args);
235 void checkTimeOut (
const CodeLocation& location)
const
238 location.throwError (root->timeout == Time() ?
"Interrupted" :
"Execution timed-out");
241 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Scope)
247 Statement (
const CodeLocation& l) noexcept : location (l) {}
248 virtual ~Statement() =
default;
250 enum ResultCode { ok = 0, returnWasHit, breakWasHit, continueWasHit };
251 virtual ResultCode perform (
const Scope&, var*)
const {
return ok; }
253 CodeLocation location;
254 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Statement)
257 struct Expression :
public Statement
259 Expression (
const CodeLocation& l) noexcept : Statement (l) {}
261 virtual var getResult (
const Scope&)
const {
return var::undefined(); }
262 virtual void assign (
const Scope&,
const var&)
const { location.throwError (
"Cannot assign to this expression!"); }
264 ResultCode perform (
const Scope& s, var*)
const override { getResult (s);
return ok; }
267 using ExpPtr = std::unique_ptr<Expression>;
269 struct BlockStatement final :
public Statement
271 BlockStatement (
const CodeLocation& l) noexcept : Statement (l) {}
273 ResultCode perform (
const Scope& s, var* returnedValue)
const override
275 for (
auto* statement : statements)
276 if (
auto r = statement->perform (s, returnedValue))
282 OwnedArray<Statement> statements;
285 struct IfStatement final :
public Statement
287 IfStatement (
const CodeLocation& l) noexcept : Statement (l) {}
289 ResultCode perform (
const Scope& s, var* returnedValue)
const override
291 return (condition->getResult (s) ? trueBranch : falseBranch)->perform (s, returnedValue);
295 std::unique_ptr<Statement> trueBranch, falseBranch;
298 struct VarStatement final :
public Statement
300 VarStatement (
const CodeLocation& l) noexcept : Statement (l) {}
302 ResultCode perform (
const Scope& s, var*)
const override
304 s.scope->setProperty (name, initialiser->getResult (s));
312 struct LoopStatement final :
public Statement
314 LoopStatement (
const CodeLocation& l,
bool isDo) noexcept : Statement (l), isDoLoop (isDo) {}
316 ResultCode perform (
const Scope& s, var* returnedValue)
const override
318 initialiser->perform (s,
nullptr);
320 while (isDoLoop || condition->getResult (s))
322 s.checkTimeOut (location);
323 auto r = body->perform (s, returnedValue);
325 if (r == returnWasHit)
return r;
326 if (r == breakWasHit)
break;
328 iterator->perform (s,
nullptr);
330 if (isDoLoop && r != continueWasHit && ! condition->getResult (s))
337 std::unique_ptr<Statement> initialiser, iterator, body;
342 struct ReturnStatement final :
public Statement
344 ReturnStatement (
const CodeLocation& l, Expression* v) noexcept : Statement (l), returnValue (v) {}
346 ResultCode perform (
const Scope& s, var* ret)
const override
348 if (ret !=
nullptr) *ret = returnValue->getResult (s);
355 struct BreakStatement final :
public Statement
357 BreakStatement (
const CodeLocation& l) noexcept : Statement (l) {}
358 ResultCode perform (
const Scope&, var*)
const override {
return breakWasHit; }
361 struct ContinueStatement final :
public Statement
363 ContinueStatement (
const CodeLocation& l) noexcept : Statement (l) {}
364 ResultCode perform (
const Scope&, var*)
const override {
return continueWasHit; }
367 struct LiteralValue final :
public Expression
369 LiteralValue (
const CodeLocation& l,
const var& v) noexcept : Expression (l), value (v) {}
370 var getResult (
const Scope&)
const override {
return value; }
374 struct UnqualifiedName final :
public Expression
376 UnqualifiedName (
const CodeLocation& l,
const Identifier& n) noexcept : Expression (l), name (n) {}
378 var getResult (
const Scope& s)
const override {
return s.findSymbolInParentScopes (name); }
380 void assign (
const Scope& s,
const var& newValue)
const override
382 if (
auto* v = getPropertyPointer (*s.scope, name))
385 s.root->setProperty (name, newValue);
391 struct DotOperator final :
public Expression
393 DotOperator (
const CodeLocation& l, ExpPtr& p,
const Identifier& c) noexcept : Expression (l), parent (p.release()), child (c) {}
395 var getResult (
const Scope& s)
const override
397 auto p = parent->getResult (s);
398 static const Identifier lengthID (
"length");
400 if (child == lengthID)
402 if (
auto* array = p.getArray())
return array->size();
403 if (p.isString())
return p.toString().length();
406 if (
auto* o = p.getDynamicObject())
407 if (
auto* v = getPropertyPointer (*o, child))
413 void assign (
const Scope& s,
const var& newValue)
const override
415 if (
auto* o = parent->getResult (s).getDynamicObject())
416 o->setProperty (child, newValue);
418 Expression::assign (s, newValue);
425 struct ArraySubscript final :
public Expression
427 ArraySubscript (
const CodeLocation& l) noexcept : Expression (l) {}
429 var getResult (
const Scope& s)
const override
431 auto arrayVar =
object->getResult (s);
432 auto key = index->getResult (s);
434 if (
const auto* array = arrayVar.getArray())
435 if (key.isInt() || key.isInt64() || key.isDouble())
436 return (*array) [
static_cast<int> (key)];
438 if (
auto* o = arrayVar.getDynamicObject())
440 if (
auto* v = getPropertyPointer (*o, Identifier (key)))
446 void assign (
const Scope& s,
const var& newValue)
const override
448 auto arrayVar =
object->getResult (s);
449 auto key = index->getResult (s);
451 if (
auto* array = arrayVar.getArray())
453 if (key.isInt() || key.isInt64() || key.isDouble())
456 while (array->size() < i)
459 array->set (i, newValue);
464 if (
auto* o = arrayVar.getDynamicObject())
468 o->setProperty (Identifier (key), newValue);
473 Expression::assign (s, newValue);
476 ExpPtr object, index;
479 struct BinaryOperatorBase :
public Expression
481 BinaryOperatorBase (
const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
482 : Expression (l), lhs (a.release()), rhs (b.release()), operation (op) {}
488 struct BinaryOperator :
public BinaryOperatorBase
490 BinaryOperator (
const CodeLocation& l, ExpPtr& a, ExpPtr& b, TokenType op) noexcept
491 : BinaryOperatorBase (l, a, b, op) {}
493 virtual var getWithUndefinedArg()
const {
return var::undefined(); }
494 virtual var getWithDoubles (
double,
double)
const {
return throwError (
"Double"); }
495 virtual var getWithInts (int64, int64)
const {
return throwError (
"Integer"); }
496 virtual var getWithArrayOrObject (
const var& a,
const var&)
const {
return throwError (a.isArray() ?
"Array" :
"Object"); }
497 virtual var getWithStrings (
const String&,
const String&)
const {
return throwError (
"String"); }
499 var getResult (
const Scope& s)
const override
501 var a (lhs->getResult (s)), b (rhs->getResult (s));
503 if ((a.isUndefined() || a.isVoid()) && (b.isUndefined() || b.isVoid()))
504 return getWithUndefinedArg();
506 if (isNumericOrUndefined (a) && isNumericOrUndefined (b))
507 return (a.isDouble() || b.isDouble()) ? getWithDoubles (a, b) : getWithInts (a, b);
509 if (a.isArray() || a.isObject())
510 return getWithArrayOrObject (a, b);
512 return getWithStrings (a.toString(), b.toString());
515 var throwError (
const char* typeName)
const
516 { location.throwError (getTokenName (operation) +
" is not allowed on the " + typeName +
" type");
return {}; }
519 struct EqualsOp final :
public BinaryOperator
521 EqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::equals) {}
522 var getWithUndefinedArg()
const override {
return true; }
523 var getWithDoubles (
double a,
double b)
const override {
return exactlyEqual (a, b); }
524 var getWithInts (int64 a, int64 b)
const override {
return a == b; }
525 var getWithStrings (
const String& a,
const String& b)
const override {
return a == b; }
526 var getWithArrayOrObject (
const var& a,
const var& b)
const override {
return a == b; }
529 struct NotEqualsOp final :
public BinaryOperator
531 NotEqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::notEquals) {}
532 var getWithUndefinedArg()
const override {
return false; }
533 var getWithDoubles (
double a,
double b)
const override {
return ! exactlyEqual (a, b); }
534 var getWithInts (int64 a, int64 b)
const override {
return a != b; }
535 var getWithStrings (
const String& a,
const String& b)
const override {
return a != b; }
536 var getWithArrayOrObject (
const var& a,
const var& b)
const override {
return a != b; }
539 struct LessThanOp final :
public BinaryOperator
541 LessThanOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThan) {}
542 var getWithDoubles (
double a,
double b)
const override {
return a < b; }
543 var getWithInts (int64 a, int64 b)
const override {
return a < b; }
544 var getWithStrings (
const String& a,
const String& b)
const override {
return a < b; }
547 struct LessThanOrEqualOp final :
public BinaryOperator
549 LessThanOrEqualOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::lessThanOrEqual) {}
550 var getWithDoubles (
double a,
double b)
const override {
return a <= b; }
551 var getWithInts (int64 a, int64 b)
const override {
return a <= b; }
552 var getWithStrings (
const String& a,
const String& b)
const override {
return a <= b; }
555 struct GreaterThanOp final :
public BinaryOperator
557 GreaterThanOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThan) {}
558 var getWithDoubles (
double a,
double b)
const override {
return a > b; }
559 var getWithInts (int64 a, int64 b)
const override {
return a > b; }
560 var getWithStrings (
const String& a,
const String& b)
const override {
return a > b; }
563 struct GreaterThanOrEqualOp final :
public BinaryOperator
565 GreaterThanOrEqualOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::greaterThanOrEqual) {}
566 var getWithDoubles (
double a,
double b)
const override {
return a >= b; }
567 var getWithInts (int64 a, int64 b)
const override {
return a >= b; }
568 var getWithStrings (
const String& a,
const String& b)
const override {
return a >= b; }
571 struct AdditionOp final :
public BinaryOperator
573 AdditionOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::plus) {}
574 var getWithDoubles (
double a,
double b)
const override {
return a + b; }
575 var getWithInts (int64 a, int64 b)
const override {
return a + b; }
576 var getWithStrings (
const String& a,
const String& b)
const override {
return a + b; }
579 struct SubtractionOp final :
public BinaryOperator
581 SubtractionOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::minus) {}
582 var getWithDoubles (
double a,
double b)
const override {
return a - b; }
583 var getWithInts (int64 a, int64 b)
const override {
return a - b; }
586 struct MultiplyOp final :
public BinaryOperator
588 MultiplyOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::times) {}
589 var getWithDoubles (
double a,
double b)
const override {
return a * b; }
590 var getWithInts (int64 a, int64 b)
const override {
return a * b; }
593 struct DivideOp final :
public BinaryOperator
595 DivideOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {}
596 var getWithDoubles (
double a,
double b)
const override {
return exactlyEqual (b, 0.0) ? std::numeric_limits<double>::infinity() : a / b; }
597 var getWithInts (int64 a, int64 b)
const override {
return b != 0 ? var ((
double) a / (
double) b) : var (std::numeric_limits<double>::infinity()); }
600 struct ModuloOp final :
public BinaryOperator
602 ModuloOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {}
603 var getWithDoubles (
double a,
double b)
const override {
return exactlyEqual (b, 0.0) ? std::numeric_limits<double>::infinity() : fmod (a, b); }
604 var getWithInts (int64 a, int64 b)
const override {
return b != 0 ? var (a % b) : var (std::numeric_limits<double>::infinity()); }
607 struct BitwiseOrOp final :
public BinaryOperator
609 BitwiseOrOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseOr) {}
610 var getWithInts (int64 a, int64 b)
const override {
return a | b; }
613 struct BitwiseAndOp final :
public BinaryOperator
615 BitwiseAndOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseAnd) {}
616 var getWithInts (int64 a, int64 b)
const override {
return a & b; }
619 struct BitwiseXorOp final :
public BinaryOperator
621 BitwiseXorOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::bitwiseXor) {}
622 var getWithInts (int64 a, int64 b)
const override {
return a ^ b; }
625 struct LeftShiftOp final :
public BinaryOperator
627 LeftShiftOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::leftShift) {}
628 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) << (int) b; }
631 struct RightShiftOp final :
public BinaryOperator
633 RightShiftOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShift) {}
634 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) >> (int) b; }
637 struct RightShiftUnsignedOp final :
public BinaryOperator
639 RightShiftUnsignedOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::rightShiftUnsigned) {}
640 var getWithInts (int64 a, int64 b)
const override {
return (
int) (((uint32) a) >> (int) b); }
643 struct LogicalAndOp final :
public BinaryOperatorBase
645 LogicalAndOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalAnd) {}
646 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) && rhs->getResult (s); }
649 struct LogicalOrOp final :
public BinaryOperatorBase
651 LogicalOrOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::logicalOr) {}
652 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) || rhs->getResult (s); }
655 struct TypeEqualsOp final :
public BinaryOperatorBase
657 TypeEqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeEquals) {}
658 var getResult (
const Scope& s)
const override {
return areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
661 struct TypeNotEqualsOp final :
public BinaryOperatorBase
663 TypeNotEqualsOp (
const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperatorBase (l, a, b, TokenTypes::typeNotEquals) {}
664 var getResult (
const Scope& s)
const override {
return ! areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
667 struct ConditionalOp final :
public Expression
669 ConditionalOp (
const CodeLocation& l) noexcept : Expression (l) {}
671 var getResult (
const Scope& s)
const override {
return (condition->getResult (s) ? trueBranch : falseBranch)->getResult (s); }
672 void assign (
const Scope& s,
const var& v)
const override { (condition->getResult (s) ? trueBranch : falseBranch)->assign (s, v); }
674 ExpPtr condition, trueBranch, falseBranch;
677 struct Assignment final :
public Expression
679 Assignment (
const CodeLocation& l, ExpPtr& dest, ExpPtr& source) noexcept : Expression (l), target (dest.release()), newValue (source.release()) {}
681 var getResult (
const Scope& s)
const override
683 auto value = newValue->getResult (s);
684 target->assign (s, value);
688 ExpPtr target, newValue;
691 struct SelfAssignment :
public Expression
693 SelfAssignment (
const CodeLocation& l, Expression* dest, Expression* source) noexcept
694 : Expression (l), target (dest), newValue (source) {}
696 var getResult (
const Scope& s)
const override
698 auto value = newValue->getResult (s);
699 target->assign (s, value);
708 struct PostAssignment final :
public SelfAssignment
710 PostAssignment (
const CodeLocation& l, Expression* dest, Expression* source) noexcept : SelfAssignment (l, dest, source) {}
712 var getResult (
const Scope& s)
const override
714 auto oldValue = target->getResult (s);
715 target->assign (s, newValue->getResult (s));
720 struct FunctionCall :
public Expression
722 FunctionCall (
const CodeLocation& l) noexcept : Expression (l) {}
724 var getResult (
const Scope& s)
const override
726 if (
auto* dot =
dynamic_cast<DotOperator*
> (
object.get()))
728 auto thisObject = dot->parent->getResult (s);
729 return invokeFunction (s, s.findFunctionCall (location, thisObject, dot->child), thisObject);
732 auto function =
object->getResult (s);
733 return invokeFunction (s, function, var (s.scope.get()));
736 var invokeFunction (
const Scope& s,
const var& function,
const var& thisObject)
const
738 s.checkTimeOut (location);
741 for (
auto* a : arguments)
742 argVars.add (a->getResult (s));
744 const var::NativeFunctionArgs args (thisObject, argVars.begin(), argVars.size());
746 if (var::NativeFunction nativeFunction = function.getNativeFunction())
747 return nativeFunction (args);
749 if (
auto* fo =
dynamic_cast<FunctionObject*
> (function.getObject()))
750 return fo->invoke (s, args);
752 if (
auto* dot =
dynamic_cast<DotOperator*
> (
object.get()))
753 if (
auto* o = thisObject.getDynamicObject())
754 if (o->hasMethod (dot->child))
755 return o->invokeMethod (dot->child, args);
757 location.throwError (
"This expression is not a function!");
return {};
761 OwnedArray<Expression> arguments;
764 struct NewOperator final :
public FunctionCall
766 NewOperator (
const CodeLocation& l) noexcept : FunctionCall (l) {}
768 var getResult (
const Scope& s)
const override
770 var classOrFunc =
object->getResult (s);
771 const bool isFunc = isFunction (classOrFunc);
773 if (! (isFunc || classOrFunc.getDynamicObject() !=
nullptr))
776 DynamicObject::Ptr newObject (
new DynamicObject());
779 invokeFunction (s, classOrFunc, newObject.get());
781 newObject->setProperty (getPrototypeIdentifier(), classOrFunc);
783 return newObject.get();
787 struct ObjectDeclaration final :
public Expression
789 ObjectDeclaration (
const CodeLocation& l) noexcept : Expression (l) {}
791 var getResult (
const Scope& s)
const override
793 DynamicObject::Ptr newObject (
new DynamicObject());
795 for (
int i = 0; i < names.size(); ++i)
796 newObject->setProperty (names.getUnchecked (i), initialisers.getUnchecked (i)->getResult (s));
798 return newObject.get();
801 Array<Identifier> names;
802 OwnedArray<Expression> initialisers;
805 struct ArrayDeclaration final :
public Expression
807 ArrayDeclaration (
const CodeLocation& l) noexcept : Expression (l) {}
809 var getResult (
const Scope& s)
const override
813 for (
int i = 0; i < values.size(); ++i)
814 a.add (values.getUnchecked (i)->getResult (s));
817 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wredundant-move")
818 return std::move (a);
819 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
822 OwnedArray<Expression> values;
826 struct FunctionObject final : public DynamicObject
828 FunctionObject() noexcept {}
830 FunctionObject (
const FunctionObject& other) : DynamicObject(), functionCode (other.functionCode)
832 ExpressionTreeBuilder tb (functionCode);
833 tb.parseFunctionParamsAndBody (*
this);
836 std::unique_ptr<DynamicObject> clone()
const override {
return std::make_unique<FunctionObject> (*
this); }
838 void writeAsJSON (OutputStream& out,
const JSON::FormatOptions&)
override
840 out <<
"function " << functionCode;
843 var invoke (
const Scope& s,
const var::NativeFunctionArgs& args)
const
845 DynamicObject::Ptr functionRoot (
new DynamicObject());
847 static const Identifier thisIdent (
"this");
848 functionRoot->setProperty (thisIdent, args.thisObject);
850 for (
int i = 0; i < parameters.size(); ++i)
851 functionRoot->setProperty (parameters.getReference (i),
855 body->perform (Scope (&s, s.root, functionRoot), &result);
860 Array<Identifier> parameters;
861 std::unique_ptr<Statement> body;
867 TokenIterator (
const String& code) : location (code), p (code.getCharPointer()) { skip(); }
871 skipWhitespaceAndComments();
872 location.location = p;
873 currentType = matchNextToken();
876 void match (TokenType expected)
878 if (currentType != expected)
879 location.throwError (
"Found " + getTokenName (currentType) +
" when expecting " + getTokenName (expected));
884 bool matchIf (TokenType expected) {
if (currentType == expected) { skip();
return true; }
return false; }
885 bool matchesAny (TokenType t1, TokenType t2)
const {
return currentType == t1 || currentType == t2; }
886 bool matchesAny (TokenType t1, TokenType t2, TokenType t3)
const {
return matchesAny (t1, t2) || currentType == t3; }
888 CodeLocation location;
889 TokenType currentType;
893 String::CharPointerType p;
898 TokenType matchNextToken()
900 if (isIdentifierStart (*p))
903 while (isIdentifierBody (*++end)) {}
905 auto len = (size_t) (end - p);
906 #define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name;
907 JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD)
909 currentValue = String (p, end); p = end;
910 return TokenTypes::identifier;
915 if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
916 return TokenTypes::literal;
918 location.throwError (
"Syntax error in numeric constant");
921 if (parseStringLiteral (*p) || (*p ==
'.' && parseFloatLiteral()))
922 return TokenTypes::literal;
924 #define JUCE_JS_COMPARE_OPERATOR(name, str) if (matchToken (TokenTypes::name, sizeof (str) - 1)) return TokenTypes::name;
925 JUCE_JS_OPERATORS (JUCE_JS_COMPARE_OPERATOR)
930 return TokenTypes::eof;
933 bool matchToken (TokenType name,
size_t len)
noexcept
935 if (p.compareUpTo (CharPointer_ASCII (name), (
int) len) != 0)
return false;
936 p += (int) len;
return true;
939 void skipWhitespaceAndComments()
943 p.incrementToEndOfWhitespace();
953 location.location = p;
955 if (p.isEmpty()) location.throwError (
"Unterminated '/*' comment");
964 bool parseStringLiteral (juce_wchar quoteType)
966 if (quoteType !=
'"' && quoteType !=
'\'')
970 if (r.failed()) location.throwError (r.getErrorMessage());
974 bool parseHexLiteral()
976 if (*p !=
'0' || (p[1] !=
'x' && p[1] !=
'X'))
return false;
980 if (v < 0)
return false;
985 if (digit < 0)
break;
989 currentValue = v; p = t;
993 bool parseFloatLiteral()
997 while (t.isDigit()) { ++t; ++numDigits; }
999 const bool hasPoint = (*t ==
'.');
1002 while ((++t).isDigit()) ++numDigits;
1008 const bool hasExponent = (c ==
'e' || c ==
'E');
1013 if (c ==
'+' || c ==
'-') ++t;
1014 if (! t.isDigit())
return false;
1015 while ((++t).isDigit()) {}
1018 if (! (hasExponent || hasPoint))
return false;
1024 bool parseOctalLiteral()
1028 if (v != 0)
return false;
1032 auto digit = (int) (*++t -
'0');
1033 if (isPositiveAndBelow (digit, 8)) v = v * 8 + digit;
1034 else if (isPositiveAndBelow (digit, 10)) location.throwError (
"Decimal digit in octal constant");
1038 currentValue = v; p = t;
1042 bool parseDecimalLiteral()
1048 auto digit = (int) (*p -
'0');
1049 if (isPositiveAndBelow (digit, 10)) v = v * 10 + digit;
1059 struct ExpressionTreeBuilder final :
private TokenIterator
1061 ExpressionTreeBuilder (
const String code) : TokenIterator (code) {}
1063 BlockStatement* parseStatementList()
1065 std::unique_ptr<BlockStatement> b (
new BlockStatement (location));
1067 while (currentType != TokenTypes::closeBrace && currentType != TokenTypes::eof)
1068 b->statements.add (parseStatement());
1073 void parseFunctionParamsAndBody (FunctionObject& fo)
1075 match (TokenTypes::openParen);
1077 while (currentType != TokenTypes::closeParen)
1079 auto paramName = currentValue.toString();
1080 match (TokenTypes::identifier);
1081 fo.parameters.add (paramName);
1083 if (currentType != TokenTypes::closeParen)
1084 match (TokenTypes::comma);
1087 match (TokenTypes::closeParen);
1088 fo.body.reset (parseBlock());
1091 Expression* parseExpression()
1093 ExpPtr lhs (parseLogicOperator());
1095 if (matchIf (TokenTypes::question))
return parseTernaryOperator (lhs);
1096 if (matchIf (TokenTypes::assign)) { ExpPtr rhs (parseExpression());
return new Assignment (location, lhs, rhs); }
1097 if (matchIf (TokenTypes::plusEquals))
return parseInPlaceOpExpression<AdditionOp> (lhs);
1098 if (matchIf (TokenTypes::minusEquals))
return parseInPlaceOpExpression<SubtractionOp> (lhs);
1099 if (matchIf (TokenTypes::timesEquals))
return parseInPlaceOpExpression<MultiplyOp> (lhs);
1100 if (matchIf (TokenTypes::divideEquals))
return parseInPlaceOpExpression<DivideOp> (lhs);
1101 if (matchIf (TokenTypes::moduloEquals))
return parseInPlaceOpExpression<ModuloOp> (lhs);
1102 if (matchIf (TokenTypes::leftShiftEquals))
return parseInPlaceOpExpression<LeftShiftOp> (lhs);
1103 if (matchIf (TokenTypes::rightShiftEquals))
return parseInPlaceOpExpression<RightShiftOp> (lhs);
1105 return lhs.release();
1109 void throwError (
const String& err)
const { location.throwError (err); }
1111 template <
typename OpType>
1112 Expression* parseInPlaceOpExpression (ExpPtr& lhs)
1114 ExpPtr rhs (parseExpression());
1115 Expression* bareLHS = lhs.get();
1116 return new SelfAssignment (location, bareLHS,
new OpType (location, lhs, rhs));
1119 BlockStatement* parseBlock()
1121 match (TokenTypes::openBrace);
1122 std::unique_ptr<BlockStatement> b (parseStatementList());
1123 match (TokenTypes::closeBrace);
1127 Statement* parseStatement()
1129 if (currentType == TokenTypes::openBrace)
return parseBlock();
1130 if (matchIf (TokenTypes::var))
return parseVar();
1131 if (matchIf (TokenTypes::if_))
return parseIf();
1132 if (matchIf (TokenTypes::while_))
return parseDoOrWhileLoop (
false);
1133 if (matchIf (TokenTypes::do_))
return parseDoOrWhileLoop (
true);
1134 if (matchIf (TokenTypes::for_))
return parseForLoop();
1135 if (matchIf (TokenTypes::return_))
return parseReturn();
1136 if (matchIf (TokenTypes::break_))
return new BreakStatement (location);
1137 if (matchIf (TokenTypes::continue_))
return new ContinueStatement (location);
1138 if (matchIf (TokenTypes::function))
return parseFunction();
1139 if (matchIf (TokenTypes::semicolon))
return new Statement (location);
1140 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1141 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1143 if (matchesAny (TokenTypes::openParen, TokenTypes::openBracket))
1144 return matchEndOfStatement (parseFactor());
1146 if (matchesAny (TokenTypes::identifier, TokenTypes::literal, TokenTypes::minus))
1147 return matchEndOfStatement (parseExpression());
1149 throwError (
"Found " + getTokenName (currentType) +
" when expecting a statement");
1153 Expression* matchEndOfStatement (Expression* ex) { ExpPtr e (ex);
if (currentType != TokenTypes::eof) match (TokenTypes::semicolon);
return e.release(); }
1154 Expression* matchCloseParen (Expression* ex) { ExpPtr e (ex); match (TokenTypes::closeParen);
return e.release(); }
1156 Statement* parseIf()
1158 std::unique_ptr<IfStatement> s (
new IfStatement (location));
1159 match (TokenTypes::openParen);
1160 s->condition.reset (parseExpression());
1161 match (TokenTypes::closeParen);
1162 s->trueBranch.reset (parseStatement());
1163 s->falseBranch.reset (matchIf (TokenTypes::else_) ? parseStatement() :
new Statement (location));
1167 Statement* parseReturn()
1169 if (matchIf (TokenTypes::semicolon))
1170 return new ReturnStatement (location,
new Expression (location));
1172 auto* r =
new ReturnStatement (location, parseExpression());
1173 matchIf (TokenTypes::semicolon);
1177 Statement* parseVar()
1179 std::unique_ptr<VarStatement> s (
new VarStatement (location));
1180 s->name = parseIdentifier();
1181 s->initialiser.reset (matchIf (TokenTypes::assign) ? parseExpression() :
new Expression (location));
1183 if (matchIf (TokenTypes::comma))
1185 std::unique_ptr<BlockStatement> block (
new BlockStatement (location));
1186 block->statements.add (std::move (s));
1187 block->statements.add (parseVar());
1188 return block.release();
1191 match (TokenTypes::semicolon);
1195 Statement* parseFunction()
1198 auto fn = parseFunctionDefinition (name);
1201 throwError (
"Functions defined at statement-level must have a name");
1203 ExpPtr nm (
new UnqualifiedName (location, name)), value (
new LiteralValue (location, fn));
1204 return new Assignment (location, nm, value);
1207 Statement* parseForLoop()
1209 std::unique_ptr<LoopStatement> s (
new LoopStatement (location,
false));
1210 match (TokenTypes::openParen);
1211 s->initialiser.reset (parseStatement());
1213 if (matchIf (TokenTypes::semicolon))
1214 s->condition.reset (
new LiteralValue (location,
true));
1217 s->condition.reset (parseExpression());
1218 match (TokenTypes::semicolon);
1221 if (matchIf (TokenTypes::closeParen))
1222 s->iterator.reset (
new Statement (location));
1225 s->iterator.reset (parseExpression());
1226 match (TokenTypes::closeParen);
1229 s->body.reset (parseStatement());
1233 Statement* parseDoOrWhileLoop (
bool isDoLoop)
1235 std::unique_ptr<LoopStatement> s (
new LoopStatement (location, isDoLoop));
1236 s->initialiser.reset (
new Statement (location));
1237 s->iterator.reset (
new Statement (location));
1241 s->body.reset (parseBlock());
1242 match (TokenTypes::while_);
1245 match (TokenTypes::openParen);
1246 s->condition.reset (parseExpression());
1247 match (TokenTypes::closeParen);
1250 s->body.reset (parseStatement());
1255 Identifier parseIdentifier()
1258 if (currentType == TokenTypes::identifier)
1259 i = currentValue.toString();
1261 match (TokenTypes::identifier);
1265 var parseFunctionDefinition (Identifier& functionName)
1267 auto functionStart = location.location;
1269 if (currentType == TokenTypes::identifier)
1270 functionName = parseIdentifier();
1272 std::unique_ptr<FunctionObject> fo (
new FunctionObject());
1273 parseFunctionParamsAndBody (*fo);
1274 fo->functionCode = String (functionStart, location.location);
1275 return var (fo.release());
1278 Expression* parseFunctionCall (FunctionCall* call, ExpPtr& function)
1280 std::unique_ptr<FunctionCall> s (call);
1281 s->object = std::move (function);
1282 match (TokenTypes::openParen);
1284 while (currentType != TokenTypes::closeParen)
1286 s->arguments.add (parseExpression());
1287 if (currentType != TokenTypes::closeParen)
1288 match (TokenTypes::comma);
1291 return matchCloseParen (s.release());
1294 Expression* parseSuffixes (Expression* e)
1298 if (matchIf (TokenTypes::dot))
1299 return parseSuffixes (
new DotOperator (location, input, parseIdentifier()));
1301 if (currentType == TokenTypes::openParen)
1302 return parseSuffixes (parseFunctionCall (
new FunctionCall (location), input));
1304 if (matchIf (TokenTypes::openBracket))
1306 std::unique_ptr<ArraySubscript> s (
new ArraySubscript (location));
1307 s->object = std::move (input);
1308 s->index.reset (parseExpression());
1309 match (TokenTypes::closeBracket);
1310 return parseSuffixes (s.release());
1313 if (matchIf (TokenTypes::plusplus))
return parsePostIncDec<AdditionOp> (input);
1314 if (matchIf (TokenTypes::minusminus))
return parsePostIncDec<SubtractionOp> (input);
1316 return input.release();
1319 Expression* parseFactor()
1321 if (currentType == TokenTypes::identifier)
return parseSuffixes (
new UnqualifiedName (location, parseIdentifier()));
1322 if (matchIf (TokenTypes::openParen))
return parseSuffixes (matchCloseParen (parseExpression()));
1323 if (matchIf (TokenTypes::true_))
return parseSuffixes (
new LiteralValue (location, (
int) 1));
1324 if (matchIf (TokenTypes::false_))
return parseSuffixes (
new LiteralValue (location, (
int) 0));
1325 if (matchIf (TokenTypes::null_))
return parseSuffixes (
new LiteralValue (location, var()));
1326 if (matchIf (TokenTypes::undefined))
return parseSuffixes (
new Expression (location));
1328 if (currentType == TokenTypes::literal)
1330 var v (currentValue); skip();
1331 return parseSuffixes (
new LiteralValue (location, v));
1334 if (matchIf (TokenTypes::openBrace))
1336 std::unique_ptr<ObjectDeclaration> e (
new ObjectDeclaration (location));
1338 while (currentType != TokenTypes::closeBrace)
1340 auto memberName = currentValue.toString();
1341 match ((currentType == TokenTypes::literal && currentValue.isString())
1342 ? TokenTypes::literal : TokenTypes::identifier);
1343 match (TokenTypes::colon);
1345 e->names.add (memberName);
1346 e->initialisers.add (parseExpression());
1348 if (currentType != TokenTypes::closeBrace)
1349 match (TokenTypes::comma);
1352 match (TokenTypes::closeBrace);
1353 return parseSuffixes (e.release());
1356 if (matchIf (TokenTypes::openBracket))
1358 std::unique_ptr<ArrayDeclaration> e (
new ArrayDeclaration (location));
1360 while (currentType != TokenTypes::closeBracket)
1362 e->values.add (parseExpression());
1364 if (currentType != TokenTypes::closeBracket)
1365 match (TokenTypes::comma);
1368 match (TokenTypes::closeBracket);
1369 return parseSuffixes (e.release());
1372 if (matchIf (TokenTypes::function))
1375 var fn = parseFunctionDefinition (name);
1378 throwError (
"Inline functions definitions cannot have a name");
1380 return new LiteralValue (location, fn);
1383 if (matchIf (TokenTypes::new_))
1385 ExpPtr name (
new UnqualifiedName (location, parseIdentifier()));
1387 while (matchIf (TokenTypes::dot))
1388 name.reset (
new DotOperator (location, name, parseIdentifier()));
1390 return parseFunctionCall (
new NewOperator (location), name);
1393 throwError (
"Found " + getTokenName (currentType) +
" when expecting an expression");
1397 template <
typename OpType>
1398 Expression* parsePreIncDec()
1400 Expression* e = parseFactor();
1401 ExpPtr lhs (e), one (
new LiteralValue (location, (
int) 1));
1402 return new SelfAssignment (location, e,
new OpType (location, lhs, one));
1405 template <
typename OpType>
1406 Expression* parsePostIncDec (ExpPtr& lhs)
1408 Expression* e = lhs.release();
1409 ExpPtr lhs2 (e), one (
new LiteralValue (location, (
int) 1));
1410 return new PostAssignment (location, e,
new OpType (location, lhs2, one));
1413 Expression* parseTypeof()
1415 std::unique_ptr<FunctionCall> f (
new FunctionCall (location));
1416 f->object.reset (
new UnqualifiedName (location,
"typeof"));
1417 f->arguments.add (parseUnary());
1421 Expression* parseUnary()
1423 if (matchIf (TokenTypes::minus)) { ExpPtr a (
new LiteralValue (location, (
int) 0)), b (parseUnary());
return new SubtractionOp (location, a, b); }
1424 if (matchIf (TokenTypes::logicalNot)) { ExpPtr a (
new LiteralValue (location, (
int) 0)), b (parseUnary());
return new EqualsOp (location, a, b); }
1425 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1426 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1427 if (matchIf (TokenTypes::typeof_))
return parseTypeof();
1429 return parseFactor();
1432 Expression* parseMultiplyDivide()
1434 ExpPtr a (parseUnary());
1438 if (matchIf (TokenTypes::times)) { ExpPtr b (parseUnary()); a.reset (
new MultiplyOp (location, a, b)); }
1439 else if (matchIf (TokenTypes::divide)) { ExpPtr b (parseUnary()); a.reset (
new DivideOp (location, a, b)); }
1440 else if (matchIf (TokenTypes::modulo)) { ExpPtr b (parseUnary()); a.reset (
new ModuloOp (location, a, b)); }
1447 Expression* parseAdditionSubtraction()
1449 ExpPtr a (parseMultiplyDivide());
1453 if (matchIf (TokenTypes::plus)) { ExpPtr b (parseMultiplyDivide()); a.reset (
new AdditionOp (location, a, b)); }
1454 else if (matchIf (TokenTypes::minus)) { ExpPtr b (parseMultiplyDivide()); a.reset (
new SubtractionOp (location, a, b)); }
1461 Expression* parseShiftOperator()
1463 ExpPtr a (parseAdditionSubtraction());
1467 if (matchIf (TokenTypes::leftShift)) { ExpPtr b (parseExpression()); a.reset (
new LeftShiftOp (location, a, b)); }
1468 else if (matchIf (TokenTypes::rightShift)) { ExpPtr b (parseExpression()); a.reset (
new RightShiftOp (location, a, b)); }
1469 else if (matchIf (TokenTypes::rightShiftUnsigned)) { ExpPtr b (parseExpression()); a.reset (
new RightShiftUnsignedOp (location, a, b)); }
1476 Expression* parseComparator()
1478 ExpPtr a (parseShiftOperator());
1482 if (matchIf (TokenTypes::equals)) { ExpPtr b (parseShiftOperator()); a.reset (
new EqualsOp (location, a, b)); }
1483 else if (matchIf (TokenTypes::notEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new NotEqualsOp (location, a, b)); }
1484 else if (matchIf (TokenTypes::typeEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new TypeEqualsOp (location, a, b)); }
1485 else if (matchIf (TokenTypes::typeNotEquals)) { ExpPtr b (parseShiftOperator()); a.reset (
new TypeNotEqualsOp (location, a, b)); }
1486 else if (matchIf (TokenTypes::lessThan)) { ExpPtr b (parseShiftOperator()); a.reset (
new LessThanOp (location, a, b)); }
1487 else if (matchIf (TokenTypes::lessThanOrEqual)) { ExpPtr b (parseShiftOperator()); a.reset (
new LessThanOrEqualOp (location, a, b)); }
1488 else if (matchIf (TokenTypes::greaterThan)) { ExpPtr b (parseShiftOperator()); a.reset (
new GreaterThanOp (location, a, b)); }
1489 else if (matchIf (TokenTypes::greaterThanOrEqual)) { ExpPtr b (parseShiftOperator()); a.reset (
new GreaterThanOrEqualOp (location, a, b)); }
1496 Expression* parseLogicOperator()
1498 ExpPtr a (parseComparator());
1502 if (matchIf (TokenTypes::logicalAnd)) { ExpPtr b (parseComparator()); a.reset (
new LogicalAndOp (location, a, b)); }
1503 else if (matchIf (TokenTypes::logicalOr)) { ExpPtr b (parseComparator()); a.reset (
new LogicalOrOp (location, a, b)); }
1504 else if (matchIf (TokenTypes::bitwiseAnd)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseAndOp (location, a, b)); }
1505 else if (matchIf (TokenTypes::bitwiseOr)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseOrOp (location, a, b)); }
1506 else if (matchIf (TokenTypes::bitwiseXor)) { ExpPtr b (parseComparator()); a.reset (
new BitwiseXorOp (location, a, b)); }
1513 Expression* parseTernaryOperator (ExpPtr& condition)
1515 std::unique_ptr<ConditionalOp> e (
new ConditionalOp (location));
1516 e->condition = std::move (condition);
1517 e->trueBranch.reset (parseExpression());
1518 match (TokenTypes::colon);
1519 e->falseBranch.reset (parseExpression());
1523 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ExpressionTreeBuilder)
1527 static var get (Args a,
int index)
noexcept {
return index < a.numArguments ? a.arguments[index] : var(); }
1528 static bool isInt (Args a,
int index)
noexcept {
return get (a, index).isInt() || get (a, index).isInt64(); }
1529 static int getInt (Args a,
int index)
noexcept {
return get (a, index); }
1530 static double getDouble (Args a,
int index)
noexcept {
return get (a, index); }
1531 static String getString (Args a,
int index)
noexcept {
return get (a, index).toString(); }
1534 struct ObjectClass final :
public DynamicObject
1538 setMethod (
"dump", dump);
1539 setMethod (
"clone", cloneFn);
1542 static Identifier getClassName() {
static const Identifier i (
"Object");
return i; }
1544 static var cloneFn (Args a) {
return a.thisObject.clone(); }
1548 struct ArrayClass final :
public DynamicObject
1552 setMethod (
"contains", contains);
1553 setMethod (
"remove", remove);
1554 setMethod (
"join", join);
1555 setMethod (
"push", push);
1556 setMethod (
"splice", splice);
1557 setMethod (
"indexOf", indexOf);
1560 static Identifier getClassName() {
static const Identifier i (
"Array");
return i; }
1562 static var contains (Args a)
1564 if (
auto* array = a.thisObject.getArray())
1565 return array->contains (get (a, 0));
1570 static var remove (Args a)
1572 if (
auto* array = a.thisObject.getArray())
1573 array->removeAllInstancesOf (get (a, 0));
1578 static var join (Args a)
1580 StringArray strings;
1582 if (
auto* array = a.thisObject.getArray())
1583 for (
auto& v : *array)
1584 strings.add (v.toString());
1586 return strings.joinIntoString (getString (a, 0));
1589 static var push (Args a)
1591 if (
auto* array = a.thisObject.getArray())
1593 for (
int i = 0; i < a.numArguments; ++i)
1594 array->add (a.arguments[i]);
1596 return array->size();
1602 static var splice (Args a)
1604 if (
auto* array = a.thisObject.getArray())
1606 auto arraySize = array->size();
1607 int start = get (a, 0);
1610 start = jmax (0, arraySize + start);
1611 else if (start > arraySize)
1614 const int num = a.numArguments > 1 ? jlimit (0, arraySize - start, getInt (a, 1))
1615 : arraySize - start;
1617 Array<var> itemsRemoved;
1618 itemsRemoved.ensureStorageAllocated (num);
1620 for (
int i = 0; i < num; ++i)
1621 itemsRemoved.add (array->getReference (start + i));
1623 array->removeRange (start, num);
1625 for (
int i = 2; i < a.numArguments; ++i)
1626 array->insert (start++, get (a, i));
1629 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wredundant-move")
1630 return std::move (itemsRemoved);
1631 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
1634 return var::undefined();
1637 static var indexOf (Args a)
1639 if (
auto* array = a.thisObject.getArray())
1641 auto target = get (a, 0);
1643 for (
int i = (a.numArguments > 1 ? getInt (a, 1) : 0); i < array->size(); ++i)
1644 if (array->getReference (i) == target)
1653 struct StringClass final :
public DynamicObject
1657 setMethod (
"substring", substring);
1658 setMethod (
"indexOf", indexOf);
1659 setMethod (
"charAt", charAt);
1660 setMethod (
"charCodeAt", charCodeAt);
1661 setMethod (
"fromCharCode", fromCharCode);
1662 setMethod (
"split", split);
1665 static Identifier getClassName() {
static const Identifier i (
"String");
return i; }
1667 static var fromCharCode (Args a) {
return String::charToString (
static_cast<juce_wchar
> (getInt (a, 0))); }
1668 static var substring (Args a) {
return a.thisObject.toString().substring (getInt (a, 0), getInt (a, 1)); }
1669 static var indexOf (Args a) {
return a.thisObject.toString().indexOf (getString (a, 0)); }
1670 static var charCodeAt (Args a) {
return (
int) a.thisObject.toString() [getInt (a, 0)]; }
1671 static var charAt (Args a) {
int p = getInt (a, 0);
return a.thisObject.toString().substring (p, p + 1); }
1673 static var split (Args a)
1675 auto str = a.thisObject.toString();
1676 auto sep = getString (a, 0);
1677 StringArray strings;
1679 if (sep.isNotEmpty())
1680 strings.addTokens (str, sep.substring (0, 1), {});
1682 for (
auto pos = str.getCharPointer(); ! pos.isEmpty(); ++pos)
1687 for (
auto& s : strings)
1695 struct MathClass final :
public DynamicObject
1699 setMethod (
"abs", Math_abs); setMethod (
"round", Math_round);
1700 setMethod (
"random", Math_random); setMethod (
"randInt", Math_randInt);
1701 setMethod (
"min", Math_min); setMethod (
"max", Math_max);
1702 setMethod (
"range", Math_range); setMethod (
"sign", Math_sign);
1703 setMethod (
"toDegrees", Math_toDegrees); setMethod (
"toRadians", Math_toRadians);
1704 setMethod (
"sin", Math_sin); setMethod (
"asin", Math_asin);
1705 setMethod (
"sinh", Math_sinh); setMethod (
"asinh", Math_asinh);
1706 setMethod (
"cos", Math_cos); setMethod (
"acos", Math_acos);
1707 setMethod (
"cosh", Math_cosh); setMethod (
"acosh", Math_acosh);
1708 setMethod (
"tan", Math_tan); setMethod (
"atan", Math_atan);
1709 setMethod (
"tanh", Math_tanh); setMethod (
"atanh", Math_atanh);
1710 setMethod (
"log", Math_log); setMethod (
"log10", Math_log10);
1711 setMethod (
"exp", Math_exp); setMethod (
"pow", Math_pow);
1712 setMethod (
"sqr", Math_sqr); setMethod (
"sqrt", Math_sqrt);
1713 setMethod (
"ceil", Math_ceil); setMethod (
"floor", Math_floor);
1714 setMethod (
"hypot", Math_hypot);
1719 setProperty (
"SQRT1_2", std::sqrt (0.5));
1720 setProperty (
"LN2", std::log (2.0));
1721 setProperty (
"LN10", std::log (10.0));
1728 static var Math_abs (Args a) {
return isInt (a, 0) ? var (std::abs (getInt (a, 0))) : var (std::abs (getDouble (a, 0))); }
1729 static var Math_round (Args a) {
return isInt (a, 0) ? var (roundToInt (getInt (a, 0))) : var (roundToInt (getDouble (a, 0))); }
1730 static var Math_sign (Args a) {
return isInt (a, 0) ? var (sign (getInt (a, 0))) : var (sign (getDouble (a, 0))); }
1731 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))); }
1732 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))); }
1733 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))); }
1734 static var Math_toDegrees (Args a) {
return radiansToDegrees (getDouble (a, 0)); }
1735 static var Math_toRadians (Args a) {
return degreesToRadians (getDouble (a, 0)); }
1736 static var Math_sin (Args a) {
return std::sin (getDouble (a, 0)); }
1737 static var Math_asin (Args a) {
return std::asin (getDouble (a, 0)); }
1738 static var Math_cos (Args a) {
return std::cos (getDouble (a, 0)); }
1739 static var Math_acos (Args a) {
return std::acos (getDouble (a, 0)); }
1740 static var Math_sinh (Args a) {
return std::sinh (getDouble (a, 0)); }
1741 static var Math_cosh (Args a) {
return std::cosh (getDouble (a, 0)); }
1742 static var Math_tan (Args a) {
return std::tan (getDouble (a, 0)); }
1743 static var Math_tanh (Args a) {
return std::tanh (getDouble (a, 0)); }
1744 static var Math_atan (Args a) {
return std::atan (getDouble (a, 0)); }
1745 static var Math_log (Args a) {
return std::log (getDouble (a, 0)); }
1746 static var Math_log10 (Args a) {
return std::log10 (getDouble (a, 0)); }
1747 static var Math_exp (Args a) {
return std::exp (getDouble (a, 0)); }
1748 static var Math_pow (Args a) {
return std::pow (getDouble (a, 0), getDouble (a, 1)); }
1749 static var Math_sqr (Args a) {
return square (getDouble (a, 0)); }
1750 static var Math_sqrt (Args a) {
return std::sqrt (getDouble (a, 0)); }
1751 static var Math_ceil (Args a) {
return std::ceil (getDouble (a, 0)); }
1752 static var Math_floor (Args a) {
return std::floor (getDouble (a, 0)); }
1753 static var Math_hypot (Args a) {
return std::hypot (getDouble (a, 0), getDouble (a, 1)); }
1757 static var Math_asinh (Args a) {
return asinh (getDouble (a, 0)); }
1758 static var Math_acosh (Args a) {
return acosh (getDouble (a, 0)); }
1759 static var Math_atanh (Args a) {
return atanh (getDouble (a, 0)); }
1761 static Identifier getClassName() {
static const Identifier i (
"Math");
return i; }
1762 template <
typename Type>
static Type sign (Type n)
noexcept {
return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); }
1766 struct JSONClass final :
public DynamicObject
1768 JSONClass() { setMethod (
"stringify", stringify); }
1769 static Identifier getClassName() {
static const Identifier i (
"JSON");
return i; }
1770 static var stringify (Args a) {
return JSON::toString (get (a, 0)); }
1774 struct IntegerClass final :
public DynamicObject
1776 IntegerClass() { setMethod (
"parseInt", parseInt); }
1777 static Identifier getClassName() {
static const Identifier i (
"Integer");
return i; }
1779 static var parseInt (Args a)
1781 auto s = getString (a, 0).trim();
1783 return s[0] ==
'0' ? (s[1] ==
'x' ? s.substring (2).getHexValue64() : getOctalValue (s))
1784 : s.getLargeIntValue();
1790 static var charToInt (Args a) {
return (
int) (getString (a, 0)[0]); }
1791 static var parseFloat (Args a) {
return getDouble (a, 0); }
1793 static var typeof_internal (Args a)
1797 if (v.isVoid())
return "void";
1798 if (v.isString())
return "string";
1799 if (isNumeric (v))
return "number";
1800 if (isFunction (v) || v.isMethod())
return "function";
1801 if (v.isObject())
return "object";
1806 static var exec (Args a)
1808 if (
auto* root =
dynamic_cast<RootObject*
> (a.thisObject.getObject()))
1809 root->execute (getString (a, 0));
1814 static var eval (Args a)
1816 if (
auto* root =
dynamic_cast<RootObject*
> (a.thisObject.getObject()))
1817 return root->evaluate (getString (a, 0));
1826 registerNativeObject (RootObject::ObjectClass ::getClassName(),
new RootObject::ObjectClass());
1828 registerNativeObject (RootObject::StringClass ::getClassName(),
new RootObject::StringClass());
1831 registerNativeObject (RootObject::IntegerClass ::getClassName(),
new RootObject::IntegerClass());
1841 root->setProperty (name,
object);
1849 root->execute (code);
1864 if (result !=
nullptr) *result =
Result::ok();
1865 return root->evaluate (code);
1882 if (result !=
nullptr) *result =
Result::ok();
1883 RootObject::Scope ({}, *root, *root).findAndInvokeMethod (function, args, returnVal);
1901 if (result !=
nullptr) *result =
Result::ok();
1902 RootObject::Scope rootScope ({}, *root, *root);
1904 .invokeMethod (functionObject, args, returnVal);
1916 return root->getProperties();
1919JUCE_END_IGNORE_WARNINGS_MSVC
static bool isLetter(char character) noexcept
static int getHexDigitValue(juce_wchar digit) noexcept
static bool isLetterOrDigit(char character) noexcept
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
static double getDoubleValue(CharPointerType text) noexcept
static String toString(const var &objectToFormat, bool allOnOneLine=false, int maximumDecimalPlaces=15)
static Result parseQuotedString(String::CharPointerType &text, var &result)
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 void JUCE_CALLTYPE outputDebugString(const String &text)
double nextDouble() noexcept
static Random & getSystemRandom() noexcept
static Result fail(const String &errorMessage) noexcept
static Result ok() noexcept
static String charToString(juce_wchar character)
static Time JUCE_CALLTYPE getCurrentTime() noexcept
static var undefined() noexcept
static constexpr FloatType sqrt2
static constexpr FloatType pi
static constexpr FloatType euler