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)
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);
79 using TokenType =
const char*;
81 void execute (
const String& code)
84 std::unique_ptr<BlockStatement> (tb.parseStatementList())->perform (
Scope ({}, *
this, *
this),
nullptr);
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(); }
105 static Identifier getPrototypeIdentifier() {
static const Identifier i (
"prototype");
return i; }
111 CodeLocation (
const String& code) noexcept : program (code), location (program.getCharPointer()) {}
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;
135 : parent (p), root (std::move (rt)),
136 scope (std::move (scp)) {}
138 const Scope*
const parent;
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))
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() +
"'");
178 if (
auto* cls = root->getProperty (className).getDynamicObject())
179 return getPropertyPointer (*cls, propName);
186 if (
auto v = getPropertyPointer (*scope, name))
189 return parent !=
nullptr ? parent->findSymbolInParentScopes (name)
195 auto* target = args.thisObject.getDynamicObject();
197 if (target ==
nullptr || target == scope.
get())
199 if (
auto* m = getPropertyPointer (*scope,
function))
203 result = fo->
invoke (*
this, args);
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))
223 auto* target = args.thisObject.getDynamicObject();
225 if (target ==
nullptr || target == scope.
get())
229 result = fo->
invoke (*
this, args);
241 location.throwError (root->timeout ==
Time() ?
"Interrupted" :
"Execution timed-out");
244 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (
Scope)
253 enum ResultCode { ok = 0, returnWasHit, breakWasHit, continueWasHit };
254 virtual ResultCode perform (
const Scope&,
var*)
const {
return ok; }
257 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (
Statement)
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>;
276 ResultCode perform (
const Scope& s,
var* returnedValue)
const override
278 for (
auto* statement : statements)
279 if (
auto r = statement->perform (s, returnedValue))
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;
305 ResultCode perform (
const Scope& s,
var*)
const override
307 s.scope->
setProperty (name, initialiser->getResult (s));
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;
349 ResultCode perform (
const Scope& s,
var* ret)
const override
351 if (ret !=
nullptr) *ret = returnValue->getResult (s);
361 ResultCode perform (
const Scope&,
var*)
const override {
return breakWasHit; }
367 ResultCode perform (
const Scope&,
var*)
const override {
return continueWasHit; }
373 var getResult (
const Scope&)
const override {
return value; }
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);
398 var getResult (
const Scope& s)
const override
400 auto p = parent->getResult (s);
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))
416 void assign (
const Scope& s,
const var& newValue)
const override
418 if (
auto* o = parent->getResult (s).getDynamicObject())
421 Expression::assign (s, newValue);
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)))
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)
462 array->set (i, newValue);
467 if (
auto* o = arrayVar.getDynamicObject())
476 Expression::assign (s, newValue);
479 ExpPtr object, index;
485 :
Expression (l), lhs (a.release()), rhs (b.release()), operation (op) {}
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 {}; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
585 var getWithDoubles (
double a,
double b)
const override {
return a - b; }
586 var getWithInts (int64 a, int64 b)
const override {
return a - b; }
592 var getWithDoubles (
double a,
double b)
const override {
return a * b; }
593 var getWithInts (int64 a, int64 b)
const override {
return a * b; }
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()); }
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()); }
613 var getWithInts (int64 a, int64 b)
const override {
return a | b; }
619 var getWithInts (int64 a, int64 b)
const override {
return a & b; }
625 var getWithInts (int64 a, int64 b)
const override {
return a ^ b; }
631 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) << (int) b; }
637 var getWithInts (int64 a, int64 b)
const override {
return ((
int) a) >> (int) b; }
643 var getWithInts (int64 a, int64 b)
const override {
return (
int) (((uint32) a) >> (int) b); }
649 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) && rhs->getResult (s); }
655 var getResult (
const Scope& s)
const override {
return lhs->getResult (s) || rhs->getResult (s); }
661 var getResult (
const Scope& s)
const override {
return areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
667 var getResult (
const Scope& s)
const override {
return ! areTypeEqual (lhs->getResult (s), rhs->getResult (s)); }
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;
684 var getResult (
const Scope& s)
const override
686 auto value = newValue->getResult (s);
687 target->assign (s, value);
691 ExpPtr target, newValue;
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);
715 var getResult (
const Scope& s)
const override
717 auto oldValue = target->getResult (s);
718 target->assign (s, newValue->getResult (s));
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));
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())
760 location.throwError (
"This expression is not a function!");
return {};
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))
782 invokeFunction (s, classOrFunc, newObject.
get());
784 newObject->
setProperty (getPrototypeIdentifier(), classOrFunc);
786 return newObject.
get();
794 var getResult (
const Scope& s)
const override
798 for (
int i = 0; i < names.size(); ++i)
799 newObject->
setProperty (names.getUnchecked(i), initialisers.getUnchecked(i)->getResult (s));
801 return newObject.
get();
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);
834 tb.parseFunctionParamsAndBody (*
this);
839 void writeAsJSON (
OutputStream& out,
int ,
bool ,
int )
override
841 out <<
"function " << functionCode;
849 functionRoot->setProperty (thisIdent, args.thisObject);
851 for (
int i = 0; i < parameters.size(); ++i)
852 functionRoot->setProperty (parameters.getReference(i),
856 body->perform (
Scope (&s, s.root, functionRoot), &result);
862 std::unique_ptr<Statement> body;
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; }
890 TokenType currentType;
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)
931 return TokenTypes::eof;
934 bool matchToken (TokenType name,
size_t len) noexcept
937 p += (int) len;
return true;
940 void skipWhitespaceAndComments()
954 location.location = p;
956 if (p.
isEmpty()) location.throwError (
"Unterminated '/*' comment");
965 bool parseStringLiteral (juce_wchar quoteType)
967 if (quoteType !=
'"' && quoteType !=
'\'')
971 if (r.failed()) location.throwError (r.getErrorMessage());
975 bool parseHexLiteral()
977 if (*p !=
'0' || (p[1] !=
'x' && p[1] !=
'X'))
return false;
981 if (v < 0)
return false;
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;
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)
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(); }
1539 setMethod (
"dump", dump);
1540 setMethod (
"clone", cloneFn);
1543 static Identifier getClassName() {
static const Identifier i (
"Object");
return i; }
1545 static var cloneFn (
Args a) {
return a.thisObject.
clone(); }
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));
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();
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);
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)
1656 setMethod (
"substring", substring);
1657 setMethod (
"indexOf", indexOf);
1658 setMethod (
"charAt", charAt);
1659 setMethod (
"charCodeAt", charCodeAt);
1660 setMethod (
"fromCharCode", fromCharCode);
1661 setMethod (
"split", split);
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)
1686 for (
auto& s : strings)
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);
1717 setProperty (
"SQRT1_2", std::sqrt (0.5));
1718 setProperty (
"LN2", std::log (2.0));
1719 setProperty (
"LN10", std::log (10.0));
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)); }
1759 template <
typename Type>
static Type sign (Type n) noexcept {
return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); }
1765 JSONClass() { setMethod (
"stringify", stringify); }
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();
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));
1811 static var eval (Args a)
1813 if (
auto* root =
dynamic_cast<RootObject*
> (a.thisObject.getObject()))
1814 return root->evaluate (getString (a, 0));
1823 registerNativeObject (RootObject::ObjectClass ::getClassName(),
new RootObject::ObjectClass());
1825 registerNativeObject (RootObject::StringClass ::getClassName(),
new RootObject::StringClass());
1838 root->setProperty (name,
object);
1846 root->execute (code);
1848 catch (String& error)
1861 if (result !=
nullptr) *result =
Result::ok();
1862 return root->evaluate (code);
1864 catch (String& error)
1879 if (result !=
nullptr) *result =
Result::ok();
1880 RootObject::Scope ({}, *root, *root).findAndInvokeMethod (
function, args, returnVal);
1882 catch (String& error)
1891 const var::NativeFunctionArgs& args, Result* result)
1898 if (result !=
nullptr) *result =
Result::ok();
1899 RootObject::Scope rootScope ({}, *root, *root);
1900 RootObject::Scope (&rootScope, *root, DynamicObject::Ptr (objectScope))
1901 .invokeMethod (functionObject, args, returnVal);
1903 catch (String& error)
1913 return root->getProperties();
1917 #pragma warning (pop)
Holds a resizable array of primitive or copy-by-value objects.
int size() const noexcept
Returns the current number of elements in the array.
ElementType * begin() noexcept
Returns a pointer to the first element in the array.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
An arbitrarily large integer class.
void parseString(StringRef text, int base)
Reads the numeric value from a string.
int64 toInt64() const noexcept
Attempts to get the lowest 64 bits of the value as an integer.
Wraps a pointer to a null-terminated ASCII character string, and provides various methods to operate ...
Wraps a pointer to a null-terminated UTF-8 character string, and provides various methods to operate ...
int compareUpTo(const CharPointer other, const int maxChars) const noexcept
Compares this string with another one, up to a specified number of characters.
bool isEmpty() const noexcept
Returns true if this pointer is pointing to a null character.
CharPointer_UTF8 findEndOfWhitespace() const noexcept
Returns the first non-whitespace character in the string.
bool isDigit() const noexcept
Returns true if the first character of this string is a digit.
static bool isLetter(char character) noexcept
Checks whether a character is alphabetic.
static int getHexDigitValue(juce_wchar digit) noexcept
Returns 0 to 16 for '0' to 'F", or -1 for characters that aren't a legal hex digit.
static bool isLetterOrDigit(char character) noexcept
Checks whether a character is alphabetic or numeric.
static CharPointerType1 find(CharPointerType1 textToSearch, const CharPointerType2 substringToLookFor) noexcept
Returns a pointer to the first occurrence of a substring in a string.
static double getDoubleValue(CharPointerType text) noexcept
Parses a character string, to read a floating-point value.
Represents a dynamically implemented object.
NamedValueSet & getProperties() noexcept
Returns the NamedValueSet that holds the object's properties.
virtual var invokeMethod(Identifier methodName, const var::NativeFunctionArgs &args)
Invokes a named method on this object.
virtual bool hasMethod(const Identifier &methodName) const
Checks whether this object has the specified method.
virtual const var & getProperty(const Identifier &propertyName) const
Returns a named property.
virtual void setProperty(const Identifier &propertyName, const var &newValue)
Sets a named property.
Represents a string identifier, designed for accessing properties by name.
const String & toString() const noexcept
Returns this identifier as a string.
String::CharPointerType getCharPointer() const noexcept
Returns this identifier's raw string pointer.
static String toString(const var &objectToFormat, bool allOnOneLine=false, int maximumDecimalPlaces=15)
Returns a string which contains a JSON-formatted representation of the var object.
static Result parseQuotedString(String::CharPointerType &text, var &result)
Parses a quoted string-literal in JSON format, returning the un-escaped result in the result paramete...
void stop() noexcept
When called from another thread, causes the interpreter to time-out as soon as possible.
const NamedValueSet & getRootObjectProperties() const noexcept
Provides access to the set of properties of the root namespace object.
Result execute(const String &javascriptCode)
Attempts to parse and run a block of javascript code.
var callFunction(const Identifier &function, const var::NativeFunctionArgs &args, Result *errorMessage=nullptr)
Calls a function in the root namespace, and returns the result.
var evaluate(const String &javascriptCode, Result *errorMessage=nullptr)
Attempts to parse and run a javascript expression, and returns the result.
void registerNativeObject(const Identifier &objectName, DynamicObject *object)
Adds a native object to the root namespace.
var callFunctionObject(DynamicObject *objectScope, const var &functionObject, const var::NativeFunctionArgs &args, Result *errorMessage=nullptr)
Calls a function object in the namespace of a dynamic object, and returns the result.
JavascriptEngine()
Creates an instance of the engine.
RelativeTime maximumExecutionTime
This value indicates how long a call to one of the evaluate methods is permitted to run before timing...
~JavascriptEngine()
Destructor.
static void JUCE_CALLTYPE outputDebugString(const String &text)
Writes a message to the standard error stream.
var * getVarPointer(const Identifier &name) noexcept
Returns a pointer to the var that holds a named value, or null if there is no value with this name.
The base class for streams that write data to some kind of destination.
An array designed for holding objects.
int nextInt() noexcept
Returns the next random 32 bit integer.
double nextDouble() noexcept
Returns the next random floating-point number.
static Random & getSystemRandom() noexcept
The overhead of creating a new Random object is fairly small, but if you want to avoid it,...
A smart-pointer class which points to a reference-counted object.
ReferencedType * get() const noexcept
Returns the object that this pointer references.
Represents the 'success' or 'failure' of an operation, and holds an associated error message to descr...
static Result fail(const String &errorMessage) noexcept
Creates a 'failure' result.
static Result ok() noexcept
Creates and returns a 'successful' result.
CharPointerType getCharPointer() const noexcept
Returns the character pointer currently being used to store this string.
String initialSectionContainingOnly(StringRef permittedCharacters) const
Returns a section from the start of the string that only contains a certain set of characters.
static String charToString(juce_wchar character)
Creates a string from a single character.
Holds an absolute date and time.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
A variant class, that can be used to hold a range of primitive values.
static var undefined() noexcept
Returns a var object that can be used where you need the javascript "undefined" value.
var invoke(const Identifier &method, const var *arguments, int numArguments) const
Invokes a named method call with a list of arguments.
bool hasSameTypeAs(const var &other) const noexcept
Returns true if this var has the same type as the one supplied.
var clone() const noexcept
Returns a deep copy of this object.
Commonly used mathematical constants.
This structure is passed to a NativeFunction callback, and contains invocation details about the func...