The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1988 lines
77KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2016 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. namespace littlefoot
  18. {
  19. using namespace juce;
  20. /**
  21. This class compiles littlefoot source code into a littlefoot::Program object
  22. which can be executed by a littlefoot::Runner.
  23. */
  24. struct Compiler
  25. {
  26. Compiler() {}
  27. /**
  28. */
  29. void addNativeFunctions (const char* const* functionPrototypes)
  30. {
  31. for (; *functionPrototypes != nullptr; ++functionPrototypes)
  32. nativeFunctions.add (NativeFunction (*functionPrototypes, nullptr));
  33. }
  34. /**
  35. */
  36. template <typename RunnerType>
  37. void addNativeFunctions (const RunnerType& runner)
  38. {
  39. for (int i = 0; i < runner.getNumNativeFunctions(); ++i)
  40. nativeFunctions.add (runner.getNativeFunction (i));
  41. }
  42. /**
  43. */
  44. Result compile (const String& sourceCode, uint32 heapSizeBytesRequired)
  45. {
  46. try
  47. {
  48. SyntaxTreeBuilder stb (sourceCode);
  49. stb.compile();
  50. stb.simplify();
  51. compiledObjectCode.clear();
  52. CodeGenerator codeGen (compiledObjectCode, nativeFunctions, stb.functions);
  53. codeGen.generateCode (stb.blockBeingParsed, (heapSizeBytesRequired + 3) & ~3u);
  54. return Result::ok();
  55. }
  56. catch (String error)
  57. {
  58. return Result::fail (error);
  59. }
  60. }
  61. /**
  62. */
  63. Array<uint8> compiledObjectCode;
  64. private:
  65. struct Statement;
  66. struct Expression;
  67. struct BlockStatement;
  68. struct Function;
  69. struct AllocatedObject { virtual ~AllocatedObject() noexcept {} };
  70. using StatementPtr = Statement*;
  71. using ExpPtr = Expression*;
  72. using BlockPtr = BlockStatement*;
  73. using TokenType = const char*;
  74. #define LITTLEFOOT_KEYWORDS(X) \
  75. X(if_, "if") X(else_, "else") X(do_, "do") \
  76. X(while_, "while") X(for_, "for") X(break_, "break") X(continue_, "continue") \
  77. X(void_, "void") X(int_, "int") X(float_, "float") X(bool_, "bool") \
  78. X(return_, "return") X(true_, "true") X(false_, "false")
  79. #define LITTLEFOOT_OPERATORS(X) \
  80. X(semicolon, ";") X(dot, ".") X(comma, ",") \
  81. X(openParen, "(") X(closeParen, ")") X(openBrace, "{") X(closeBrace, "}") \
  82. X(openBracket, "[") X(closeBracket, "]") X(colon, ":") X(question, "?") \
  83. X(equals, "==") X(assign, "=") X(notEquals, "!=") X(logicalNot, "!") \
  84. X(plusEquals, "+=") X(plusplus, "++") X(plus, "+") \
  85. X(minusEquals, "-=") X(minusminus, "--") X(minus, "-") \
  86. X(timesEquals, "*=") X(times, "*") X(divideEquals, "/=") X(divide, "/") \
  87. X(moduloEquals, "%=") X(modulo, "%") X(xorEquals, "^=") X(bitwiseXor, "^") X(bitwiseNot, "~") \
  88. X(andEquals, "&=") X(logicalAnd, "&&") X(bitwiseAnd, "&") \
  89. X(orEquals, "|=") X(logicalOr, "||") X(bitwiseOr, "|") \
  90. X(leftShiftEquals, "<<=") X(lessThanOrEqual, "<=") X(leftShift, "<<") X(lessThan, "<") \
  91. X(rightShiftUnsigned, ">>>") X(rightShiftEquals, ">>=") X(rightShift, ">>") X(greaterThanOrEqual, ">=") X(greaterThan, ">")
  92. struct Token
  93. {
  94. #define DECLARE_LITTLEFOOT_TOKEN(name, str) static constexpr const char* name = str;
  95. LITTLEFOOT_KEYWORDS (DECLARE_LITTLEFOOT_TOKEN)
  96. LITTLEFOOT_OPERATORS (DECLARE_LITTLEFOOT_TOKEN)
  97. DECLARE_LITTLEFOOT_TOKEN (eof, "$eof")
  98. DECLARE_LITTLEFOOT_TOKEN (literal, "$literal")
  99. DECLARE_LITTLEFOOT_TOKEN (identifier, "$identifier")
  100. };
  101. Array<NativeFunction> nativeFunctions;
  102. //==============================================================================
  103. struct CodeLocation
  104. {
  105. CodeLocation (const String& code) noexcept : program (code), location (program.getCharPointer()) {}
  106. CodeLocation (const CodeLocation& other) noexcept : program (other.program), location (other.location) {}
  107. void throwError (const String& message) const
  108. {
  109. int col = 1, line = 1;
  110. for (auto i = program.getCharPointer(); i < location && ! i.isEmpty(); ++i)
  111. {
  112. ++col;
  113. if (*i == '\n') { col = 1; ++line; }
  114. }
  115. throw "Line " + String (line) + ", column " + String (col) + " : " + message;
  116. }
  117. String program;
  118. String::CharPointerType location;
  119. };
  120. //==============================================================================
  121. struct TokenIterator
  122. {
  123. TokenIterator (const String& code) : location (code), p (code.getCharPointer()) { skip(); }
  124. TokenType skip()
  125. {
  126. skipWhitespaceAndComments();
  127. location.location = p;
  128. auto last = currentType;
  129. currentType = matchNextToken();
  130. return last;
  131. }
  132. void match (TokenType expected)
  133. {
  134. if (currentType != expected)
  135. throwErrorExpecting (getTokenDescription (expected));
  136. skip();
  137. }
  138. bool matchIf (TokenType expected) { if (currentType == expected) { skip(); return true; } return false; }
  139. template <typename... Args>
  140. bool matchesAny (TokenType t1, Args... others) const noexcept { return currentType == t1 || matchesAny (others...); }
  141. bool matchesAny (TokenType t1) const noexcept { return currentType == t1; }
  142. CodeLocation location;
  143. TokenType currentType;
  144. var currentValue;
  145. void throwErrorExpecting (const String& expected) { location.throwError ("Found " + getTokenDescription (currentType) + " when expecting " + expected); }
  146. private:
  147. String::CharPointerType p;
  148. static bool isIdentifierStart (const juce_wchar c) noexcept { return CharacterFunctions::isLetter (c) || c == '_'; }
  149. static bool isIdentifierBody (const juce_wchar c) noexcept { return CharacterFunctions::isLetterOrDigit (c) || c == '_'; }
  150. TokenType matchNextToken()
  151. {
  152. if (isIdentifierStart (*p))
  153. {
  154. String::CharPointerType end (p);
  155. while (isIdentifierBody (*++end)) {}
  156. const size_t len = (size_t) (end - p);
  157. #define LITTLEFOOT_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (Token::name, len)) return Token::name;
  158. LITTLEFOOT_KEYWORDS (LITTLEFOOT_COMPARE_KEYWORD)
  159. currentValue = String (p, end); p = end;
  160. return Token::identifier;
  161. }
  162. if (p.isDigit())
  163. {
  164. if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
  165. return Token::literal;
  166. location.throwError ("Syntax error in numeric constant");
  167. }
  168. if (parseStringLiteral (*p) || (*p == '.' && parseFloatLiteral()))
  169. return Token::literal;
  170. #define LITTLEFOOT_COMPARE_OPERATOR(name, str) if (matchToken (Token::name, sizeof (str) - 1)) return Token::name;
  171. LITTLEFOOT_OPERATORS (LITTLEFOOT_COMPARE_OPERATOR)
  172. if (! p.isEmpty())
  173. location.throwError ("Unexpected character '" + String::charToString (*p) + "' in source");
  174. return Token::eof;
  175. }
  176. bool matchToken (TokenType name, const size_t len) noexcept
  177. {
  178. if (p.compareUpTo (CharPointer_ASCII (name), (int) len) != 0) return false;
  179. p += (int) len; return true;
  180. }
  181. void skipWhitespaceAndComments()
  182. {
  183. for (;;)
  184. {
  185. p = p.findEndOfWhitespace();
  186. if (*p == '/')
  187. {
  188. const juce_wchar c2 = p[1];
  189. if (c2 == '/') { p = CharacterFunctions::find (p, (juce_wchar) '\n'); continue; }
  190. if (c2 == '*')
  191. {
  192. location.location = p;
  193. p = CharacterFunctions::find (p + 2, CharPointer_ASCII ("*/"));
  194. if (p.isEmpty()) location.throwError ("Unterminated '/*' comment");
  195. p += 2; continue;
  196. }
  197. }
  198. break;
  199. }
  200. }
  201. bool parseStringLiteral (juce_wchar quoteType)
  202. {
  203. if (quoteType != '"' && quoteType != '\'')
  204. return false;
  205. auto r = JSON::parseQuotedString (p, currentValue);
  206. if (r.failed()) location.throwError (r.getErrorMessage());
  207. return true;
  208. }
  209. bool parseHexLiteral()
  210. {
  211. if (*p != '0' || (p[1] != 'x' && p[1] != 'X')) return false;
  212. auto t = ++p;
  213. auto v = CharacterFunctions::getHexDigitValue (*++t);
  214. if (v < 0) return false;
  215. for (;;)
  216. {
  217. auto digit = CharacterFunctions::getHexDigitValue (*++t);
  218. if (digit < 0) break;
  219. v = v * 16 + digit;
  220. }
  221. currentValue = v; p = t;
  222. return true;
  223. }
  224. bool parseFloatLiteral()
  225. {
  226. int numDigits = 0;
  227. auto t = p;
  228. while (t.isDigit()) { ++t; ++numDigits; }
  229. const bool hasPoint = (*t == '.');
  230. if (hasPoint)
  231. while ((++t).isDigit()) ++numDigits;
  232. if (numDigits == 0)
  233. return false;
  234. auto c = *t;
  235. const bool hasExponent = (c == 'e' || c == 'E');
  236. if (hasExponent)
  237. {
  238. c = *++t;
  239. if (c == '+' || c == '-') ++t;
  240. if (! t.isDigit()) return false;
  241. while ((++t).isDigit()) {}
  242. }
  243. if (! (hasExponent || hasPoint)) return false;
  244. currentValue = CharacterFunctions::getDoubleValue (p); p = t;
  245. return true;
  246. }
  247. bool parseOctalLiteral()
  248. {
  249. String::CharPointerType t (p);
  250. int64 v = *t - '0';
  251. if (v != 0) return false; // first digit of octal must be 0
  252. for (;;)
  253. {
  254. auto digit = (int) (*++t - '0');
  255. if (isPositiveAndBelow (digit, 8)) v = v * 8 + digit;
  256. else if (isPositiveAndBelow (digit, 10)) location.throwError ("Decimal digit in octal constant");
  257. else break;
  258. }
  259. currentValue = v; p = t;
  260. return true;
  261. }
  262. bool parseDecimalLiteral()
  263. {
  264. int64 v = 0;
  265. for (;; ++p)
  266. {
  267. auto digit = (int) (*p - '0');
  268. if (isPositiveAndBelow (digit, 10)) v = v * 10 + digit;
  269. else break;
  270. }
  271. currentValue = v;
  272. return true;
  273. }
  274. };
  275. //==============================================================================
  276. //==============================================================================
  277. struct SyntaxTreeBuilder : private TokenIterator
  278. {
  279. SyntaxTreeBuilder (const String& code) : TokenIterator (code) {}
  280. void compile()
  281. {
  282. blockBeingParsed = allocate<BlockStatement> (location, nullptr, nullptr, false);
  283. while (currentType != Token::eof)
  284. {
  285. if (! matchesAnyTypeOrVoid())
  286. throwErrorExpecting ("a global variable or function");
  287. auto type = tokenToType (skip());
  288. auto name = parseIdentifier();
  289. if (matchIf (Token::openParen))
  290. {
  291. parseFunctionDeclaration (type, name);
  292. continue;
  293. }
  294. if (type == Type::void_)
  295. location.throwError ("A variable type cannot be 'void'");
  296. int arraySize = matchIf (Token::openBracket) ? parseArraySize() : 0;
  297. if (arraySize > 0)
  298. location.throwError ("Arrays not yet implemented!");
  299. while (matchIf (Token::comma))
  300. {
  301. blockBeingParsed->addVariable (name, type, location);
  302. name = parseIdentifier();
  303. }
  304. blockBeingParsed->addVariable (name, type, location);
  305. match (Token::semicolon);
  306. }
  307. }
  308. void simplify()
  309. {
  310. for (auto f : functions)
  311. f->block->simplify (*this);
  312. }
  313. //==============================================================================
  314. BlockPtr blockBeingParsed = nullptr;
  315. Array<Function*> functions;
  316. template <typename Type, typename... Args>
  317. Type* allocate (Args... args) { auto o = new Type (args...); allAllocatedObjects.add (o); return o; }
  318. private:
  319. OwnedArray<AllocatedObject> allAllocatedObjects;
  320. //==============================================================================
  321. void parseFunctionDeclaration (Type returnType, const String& name)
  322. {
  323. auto f = allocate<Function>();
  324. functions.add (f);
  325. while (matchesAnyType())
  326. {
  327. auto type = tokenToType (skip());
  328. f->arguments.add ({ parseIdentifier(), type });
  329. if (f->arguments.size() > 127)
  330. location.throwError ("Too many function arguments");
  331. if (currentType == Token::closeParen)
  332. break;
  333. match (Token::comma);
  334. }
  335. match (Token::closeParen);
  336. f->functionID = createFunctionID (name, returnType, f->getArgumentTypes());
  337. f->block = parseBlock (true);
  338. f->returnType = returnType;
  339. if (! f->block->alwaysReturns())
  340. {
  341. if (returnType != Type::void_)
  342. location.throwError ("This function must return a value");
  343. f->block->statements.add (allocate<ReturnStatement> (location, f->block, nullptr));
  344. }
  345. }
  346. int parseArraySize()
  347. {
  348. auto e = parseExpression();
  349. e->simplify (*this);
  350. if (auto literal = dynamic_cast<LiteralValue*> (e))
  351. {
  352. if (literal->value.isInt() || literal->value.isInt64())
  353. {
  354. auto value = static_cast<int> (literal->value);
  355. if (value > 0)
  356. return value;
  357. }
  358. }
  359. location.throwError ("An array size must be a constant integer");
  360. return 0;
  361. }
  362. BlockPtr parseBlock (bool isMainBlockOfFunction)
  363. {
  364. match (Token::openBrace);
  365. auto b = allocate<BlockStatement> (location, blockBeingParsed, functions.getLast(), isMainBlockOfFunction);
  366. auto lastBlock = blockBeingParsed;
  367. blockBeingParsed = b;
  368. while (! matchIf (Token::closeBrace))
  369. b->statements.add (parseStatement());
  370. blockBeingParsed = lastBlock;
  371. return b;
  372. }
  373. StatementPtr parseStatement()
  374. {
  375. if (currentType == Token::openBrace) return parseBlock (false);
  376. if (matchIf (Token::if_)) return parseIf();
  377. if (matchIf (Token::while_)) return parseDoOrWhileLoop (false);
  378. if (matchIf (Token::do_)) return parseDoOrWhileLoop (true);
  379. if (matchIf (Token::for_)) return parseForLoop();
  380. if (matchIf (Token::return_)) return parseReturn();
  381. if (matchIf (Token::break_)) return matchEndOfStatement (allocate<BreakStatement> (location, blockBeingParsed));
  382. if (matchIf (Token::continue_)) return matchEndOfStatement (allocate<ContinueStatement> (location, blockBeingParsed));
  383. if (matchIf (Token::semicolon)) return matchEndOfStatement (allocate<Statement> (location, blockBeingParsed));
  384. if (matchIf (Token::plusplus)) return matchEndOfStatement (parsePreIncDec (Token::plus));
  385. if (matchIf (Token::minusminus)) return matchEndOfStatement (parsePreIncDec (Token::minus));
  386. if (matchesAny (Token::openParen)) return matchEndOfStatement (parseFactor());
  387. if (matchesAnyType()) return parseVariableDeclaration (tokenToType (skip()));
  388. if (matchesAny (Token::identifier, Token::literal, Token::minus))
  389. return matchEndOfStatement (parseExpression());
  390. throwErrorExpecting ("a statement");
  391. return nullptr;
  392. }
  393. ExpPtr parseExpression()
  394. {
  395. auto lhs = parseLogicOperator();
  396. if (matchIf (Token::question)) return parseTerneryOperator (lhs);
  397. if (matchIf (Token::plusEquals)) return parseInPlaceOpExpression (lhs, Token::plus);
  398. if (matchIf (Token::minusEquals)) return parseInPlaceOpExpression (lhs, Token::minus);
  399. if (matchIf (Token::timesEquals)) return parseInPlaceOpExpression (lhs, Token::times);
  400. if (matchIf (Token::divideEquals)) return parseInPlaceOpExpression (lhs, Token::divide);
  401. if (matchIf (Token::moduloEquals)) return parseInPlaceOpExpression (lhs, Token::modulo);
  402. if (matchIf (Token::leftShiftEquals)) return parseInPlaceOpExpression (lhs, Token::leftShift);
  403. if (matchIf (Token::rightShiftEquals)) return parseInPlaceOpExpression (lhs, Token::rightShift);
  404. if (matchIf (Token::assign))
  405. {
  406. auto loc = location;
  407. return allocate<Assignment> (loc, blockBeingParsed, getIdentifierFromExpression (lhs), parseExpression(), false);
  408. }
  409. return lhs;
  410. }
  411. ExpPtr parseTerneryOperator (ExpPtr condition)
  412. {
  413. auto e = allocate<TerneryOp> (location, blockBeingParsed);
  414. e->condition = condition;
  415. e->trueBranch = parseExpression();
  416. match (Token::colon);
  417. e->falseBranch = parseExpression();
  418. return e;
  419. }
  420. ExpPtr parseLogicOperator()
  421. {
  422. for (auto a = parseComparator();;)
  423. {
  424. if (! matchesAny (Token::logicalAnd, Token::logicalOr, Token::bitwiseOr,
  425. Token::bitwiseAnd, Token::bitwiseXor))
  426. return a;
  427. auto loc = location;
  428. auto type = skip();
  429. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseComparator(), type);
  430. }
  431. }
  432. ExpPtr parseComparator()
  433. {
  434. for (auto a = parseShiftOperator();;)
  435. {
  436. if (! matchesAny (Token::equals, Token::notEquals, Token::lessThan,
  437. Token::lessThanOrEqual, Token::greaterThan, Token::greaterThanOrEqual))
  438. return a;
  439. auto loc = location;
  440. auto type = skip();
  441. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseShiftOperator(), type);
  442. }
  443. }
  444. ExpPtr parseShiftOperator()
  445. {
  446. for (auto a = parseAdditionSubtraction();;)
  447. {
  448. if (! matchesAny (Token::leftShift, Token::rightShift, Token::rightShiftUnsigned))
  449. return a;
  450. auto loc = location;
  451. auto type = skip();
  452. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseExpression(), type);
  453. }
  454. }
  455. ExpPtr parseAdditionSubtraction()
  456. {
  457. for (auto a = parseMultiplyDivide();;)
  458. {
  459. if (! matchesAny (Token::plus, Token::minus))
  460. return a;
  461. auto loc = location;
  462. auto type = skip();
  463. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseMultiplyDivide(), type);
  464. }
  465. }
  466. ExpPtr parseMultiplyDivide()
  467. {
  468. for (auto a = parseUnary();;)
  469. {
  470. if (! matchesAny (Token::times, Token::divide, Token::modulo))
  471. return a;
  472. auto loc = location;
  473. auto type = skip();
  474. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseUnary(), type);
  475. }
  476. }
  477. ExpPtr parseUnary()
  478. {
  479. if (matchIf (Token::plusplus)) return parsePreIncDec (Token::plus);
  480. if (matchIf (Token::minusminus)) return parsePreIncDec (Token::minus);
  481. if (matchesAny (Token::minus, Token::logicalNot, Token::bitwiseNot))
  482. {
  483. auto loc = location;
  484. auto type = skip();
  485. return allocate<UnaryOp> (loc, blockBeingParsed, parseUnary(), type);
  486. }
  487. return parseFactor();
  488. }
  489. ExpPtr parseFactor()
  490. {
  491. if (currentType == Token::identifier) return parseSuffixes (allocate<Identifier> (location, blockBeingParsed, parseIdentifier()));
  492. if (matchIf (Token::openParen)) return parseSuffixes (matchCloseParen (parseExpression()));
  493. if (matchIf (Token::true_)) return parseSuffixes (allocate<LiteralValue> (location, blockBeingParsed, (int) 1));
  494. if (matchIf (Token::false_)) return parseSuffixes (allocate<LiteralValue> (location, blockBeingParsed, (int) 0));
  495. if (currentType == Token::literal)
  496. {
  497. auto lit = allocate<LiteralValue> (location, blockBeingParsed, currentValue);
  498. skip();
  499. return parseSuffixes (lit);
  500. }
  501. if (matchesAny (Token::int_, Token::float_, Token::bool_))
  502. return parseSuffixes (parseFunctionCall (skip()));
  503. throwErrorExpecting ("an expression");
  504. return nullptr;
  505. }
  506. ExpPtr parseSuffixes (ExpPtr input)
  507. {
  508. if (currentType == Token::openParen)
  509. {
  510. if (auto functionName = dynamic_cast<Identifier*> (input))
  511. return parseSuffixes (parseFunctionCall (functionName->name));
  512. location.throwError ("Malformed function call");
  513. return {};
  514. }
  515. if (matchIf (Token::openBracket))
  516. {
  517. auto s = allocate<ArraySubscript> (location, blockBeingParsed);
  518. s->object = input;
  519. s->index = parseExpression();
  520. match (Token::closeBracket);
  521. return parseSuffixes (s);
  522. }
  523. if (matchIf (Token::plusplus)) return parsePostIncDec (input, Token::plus);
  524. if (matchIf (Token::minusminus)) return parsePostIncDec (input, Token::minus);
  525. return input;
  526. }
  527. ExpPtr parseInPlaceOpExpression (ExpPtr lhs, TokenType opType)
  528. {
  529. auto loc = location;
  530. auto rhs = parseExpression();
  531. return allocate<Assignment> (loc, blockBeingParsed, getIdentifierFromExpression (lhs),
  532. allocate<BinaryOperator> (location, blockBeingParsed, lhs, rhs, opType), false);
  533. }
  534. ExpPtr parsePreIncDec (TokenType opType)
  535. {
  536. auto lhs = parseFactor();
  537. auto one = allocate<LiteralValue> (location, blockBeingParsed, (int) 1);
  538. return allocate<Assignment> (location, blockBeingParsed, getIdentifierFromExpression (lhs),
  539. allocate<BinaryOperator> (location, blockBeingParsed, lhs, one, opType), false);
  540. }
  541. ExpPtr parsePostIncDec (ExpPtr lhs, TokenType opType)
  542. {
  543. auto one = allocate<LiteralValue> (location, blockBeingParsed, (int) 1);
  544. return allocate<Assignment> (location, blockBeingParsed, getIdentifierFromExpression (lhs),
  545. allocate<BinaryOperator> (location, blockBeingParsed, lhs, one, opType), true);
  546. }
  547. StatementPtr parseIf()
  548. {
  549. auto s = allocate<IfStatement> (location, blockBeingParsed);
  550. match (Token::openParen);
  551. s->condition = matchCloseParen (parseExpression());
  552. s->trueBranch = parseStatement();
  553. s->falseBranch = matchIf (Token::else_) ? parseStatement() : nullptr;
  554. return s;
  555. }
  556. StatementPtr parseReturn()
  557. {
  558. auto value = matchIf (Token::semicolon) ? nullptr : parseExpression();
  559. auto returnStatement = allocate<ReturnStatement> (location, blockBeingParsed, value);
  560. matchIf (Token::semicolon);
  561. return returnStatement;
  562. }
  563. StatementPtr parseVariableDeclaration (Type type)
  564. {
  565. for (StatementPtr result = nullptr;;)
  566. {
  567. auto name = parseIdentifier();
  568. auto loc = location;
  569. blockBeingParsed->addVariable (name, type, loc);
  570. auto assignedValue = matchIf (Token::assign) ? parseExpression() : nullptr;
  571. if (auto literal = dynamic_cast<LiteralValue*> (assignedValue))
  572. if (static_cast<double> (literal->value) == 0)
  573. assignedValue = nullptr;
  574. if (assignedValue != nullptr || ! blockBeingParsed->isMainBlockOfFunction) // no need to assign 0 for variables in the outer scope
  575. {
  576. if (assignedValue == nullptr)
  577. assignedValue = allocate<LiteralValue> (loc, blockBeingParsed, (int) 0);
  578. auto assignment = allocate<Assignment> (loc, blockBeingParsed, name, assignedValue, false);
  579. if (result == nullptr)
  580. {
  581. result = assignment;
  582. }
  583. else
  584. {
  585. auto block = dynamic_cast<BlockPtr> (result);
  586. if (block == nullptr)
  587. {
  588. block = allocate<BlockStatement> (loc, blockBeingParsed, functions.getLast(), false);
  589. block->statements.add (result);
  590. result = block;
  591. }
  592. block->statements.add (assignment);
  593. }
  594. }
  595. if (matchIf (Token::semicolon))
  596. return result != nullptr ? result : allocate<Statement> (location, blockBeingParsed);
  597. match (Token::comma);
  598. }
  599. }
  600. StatementPtr parseForLoop()
  601. {
  602. auto oldBlock = blockBeingParsed;
  603. auto block = allocate<BlockStatement> (location, oldBlock, functions.getLast(), false);
  604. blockBeingParsed = block;
  605. auto loopStatement = allocate<LoopStatement> (location, blockBeingParsed, false);
  606. block->statements.add (loopStatement);
  607. match (Token::openParen);
  608. loopStatement->initialiser = parseStatement();
  609. loopStatement->condition = matchIf (Token::semicolon) ? allocate<LiteralValue> (location, blockBeingParsed, true)
  610. : matchEndOfStatement (parseExpression());
  611. loopStatement->iterator = matchIf (Token::closeParen) ? allocate<Statement> (location, blockBeingParsed)
  612. : matchCloseParen (parseExpression());
  613. loopStatement->body = parseStatement();
  614. blockBeingParsed = oldBlock;
  615. return block;
  616. }
  617. StatementPtr parseDoOrWhileLoop (bool isDoLoop)
  618. {
  619. auto loopStatement = allocate<LoopStatement> (location, blockBeingParsed, isDoLoop);
  620. loopStatement->initialiser = allocate<Statement> (location, blockBeingParsed);
  621. loopStatement->iterator = allocate<Statement> (location, blockBeingParsed);
  622. if (isDoLoop)
  623. {
  624. loopStatement->body = parseBlock (false);
  625. match (Token::while_);
  626. }
  627. match (Token::openParen);
  628. loopStatement->condition = matchCloseParen (parseExpression());
  629. if (! isDoLoop)
  630. loopStatement->body = parseStatement();
  631. return loopStatement;
  632. }
  633. String parseIdentifier()
  634. {
  635. String name = currentValue.toString();
  636. match (Token::identifier);
  637. return name;
  638. }
  639. String getIdentifierFromExpression (ExpPtr e)
  640. {
  641. if (auto i = dynamic_cast<Identifier*> (e))
  642. return i->name;
  643. location.throwError ("This operator requires an assignable variable");
  644. return {};
  645. }
  646. ExpPtr parseFunctionCall (const String& name)
  647. {
  648. auto call = allocate<FunctionCall> (location, blockBeingParsed);
  649. call->functionName = name;
  650. match (Token::openParen);
  651. while (currentType != Token::closeParen)
  652. {
  653. call->arguments.add (parseExpression());
  654. if (currentType == Token::closeParen)
  655. break;
  656. match (Token::comma);
  657. }
  658. return matchCloseParen (call);
  659. }
  660. bool matchesAnyType() const noexcept { return matchesAny (Token::int_, Token::float_, Token::bool_); }
  661. bool matchesAnyTypeOrVoid() const noexcept { return matchesAnyType() || currentType == Token::void_; }
  662. ExpPtr matchCloseParen (ExpPtr e) { match (Token::closeParen); return e; }
  663. template<typename ExpType> ExpType matchEndOfStatement (ExpType e) { match (Token::semicolon); return e; }
  664. };
  665. //==============================================================================
  666. //==============================================================================
  667. struct CodeGenerator
  668. {
  669. CodeGenerator (Array<uint8>& output, const Array<NativeFunction>& nativeFns, const Array<Function*>& fns)
  670. : outputCode (output), nativeFunctions (nativeFns), functions (fns) {}
  671. void generateCode (BlockPtr outerBlock, uint32 heapSizeBytesRequired)
  672. {
  673. for (auto f : functions)
  674. {
  675. f->address = createMarker();
  676. f->unwindAddress = createMarker();
  677. }
  678. emit ((int16) 0); // checksum
  679. emit ((int16) 0); // size
  680. emit ((int16) functions.size());
  681. emit ((int16) outerBlock->variables.size());
  682. emit ((int16) heapSizeBytesRequired);
  683. for (auto f : functions)
  684. emit (f->functionID, f->address);
  685. for (auto f : functions)
  686. f->emit (*this);
  687. resolveMarkers();
  688. Program::writeInt16 (outputCode.begin() + 2, (int16) outputCode.size());
  689. const Program program (outputCode.begin(), (uint32) outputCode.size());
  690. Program::writeInt16 (outputCode.begin(), (int16) program.calculateChecksum());
  691. jassert (program.checksumMatches());
  692. }
  693. //==============================================================================
  694. Array<uint8>& outputCode;
  695. const Array<NativeFunction>& nativeFunctions;
  696. const Array<Function*>& functions;
  697. struct Marker { int index = 0; };
  698. struct MarkerAndAddress { int markerIndex, address; };
  699. int nextMarker = 0;
  700. Array<MarkerAndAddress> markersToResolve, resolvedMarkers;
  701. Marker createMarker() noexcept { Marker m; m.index = ++nextMarker; return m; }
  702. void attachMarker (Marker m) { resolvedMarkers.add ({ m.index, outputCode.size() }); }
  703. int getResolvedMarkerAddress (int markerIndex) const
  704. {
  705. for (auto m : resolvedMarkers)
  706. if (m.markerIndex == markerIndex)
  707. return m.address;
  708. jassertfalse;
  709. return 0;
  710. }
  711. void resolveMarkers()
  712. {
  713. for (auto m : markersToResolve)
  714. Program::writeInt16 (outputCode.begin() + m.address, (int16) getResolvedMarkerAddress (m.markerIndex));
  715. }
  716. Marker breakTarget, continueTarget;
  717. //==============================================================================
  718. void emit (OpCode op) { emit ((int8) op); }
  719. void emit (Marker m) { markersToResolve.add ({ m.index, outputCode.size() }); emit ((int16) 0); }
  720. void emit (int8 value) { outputCode.add ((uint8) value); }
  721. void emit (int16 value) { uint8 d[2]; Program::writeInt16 (d, value); outputCode.insertArray (-1, d, (int) sizeof (d)); }
  722. void emit (int32 value) { uint8 d[4]; Program::writeInt32 (d, value); outputCode.insertArray (-1, d, (int) sizeof (d)); }
  723. template <typename Arg1, typename... Args>
  724. void emit (Arg1 arg1, Args... args)
  725. {
  726. emit (arg1);
  727. emit (args...);
  728. }
  729. void emitPush (const var& value)
  730. {
  731. if (value.isDouble())
  732. {
  733. const float v = value;
  734. if (v == 0) emit (OpCode::push0);
  735. else emit (OpCode::push32, Program::floatToInt (v));
  736. }
  737. else
  738. {
  739. const int v = value;
  740. if (v == 0) emit (OpCode::push0);
  741. else if (v == 1) emit (OpCode::push1);
  742. else if (v > 0 && v < 128) emit (OpCode::push8, (int8) v);
  743. else if (v > 0 && v < 32768) emit (OpCode::push16, (int16) v);
  744. else emit (OpCode::push32, (int32) v);
  745. }
  746. }
  747. void emitCast (Type source, Type dest, const CodeLocation& location)
  748. {
  749. if (dest == source) return;
  750. if (dest == Type::void_) return emit (OpCode::drop);
  751. if (source == Type::bool_ && dest == Type::int_) return;
  752. if (source == Type::int_ && dest == Type::bool_) return emit (OpCode::testNZ_int32);
  753. if ((source == Type::int_ || source == Type::bool_) && dest == Type::float_) return emit (OpCode::int32ToFloat);
  754. location.throwError ("Cannot cast from " + getTypeName (source) + " to " + getTypeName (dest));
  755. }
  756. void emitVariableRead (Type sourceType, Type requiredType, int stackDepth, int index, const CodeLocation& location)
  757. {
  758. if (index < 0)
  759. {
  760. emit (OpCode::dupFromGlobal, (int16) ((-index) - 1));
  761. }
  762. else
  763. {
  764. index += stackDepth;
  765. if (index == 0)
  766. emit ((OpCode) ((int) OpCode::dup));
  767. else if (index < 8)
  768. emit ((OpCode) ((int) OpCode::dupOffset_01 + index - 1));
  769. else if (index >= 128)
  770. emit (OpCode::dupOffset16, (int16) index);
  771. else
  772. emit (OpCode::dupOffset, (int8) index);
  773. }
  774. emitCast (sourceType, requiredType, location);
  775. }
  776. //==============================================================================
  777. Function* findFunction (FunctionID functionID) const noexcept
  778. {
  779. for (auto f : functions)
  780. if (f->functionID == functionID)
  781. return f;
  782. return nullptr;
  783. }
  784. NativeFunction* findNativeFunction (FunctionID functionID) const noexcept
  785. {
  786. for (auto& f : nativeFunctions)
  787. if (f.functionID == functionID)
  788. return &f;
  789. return nullptr;
  790. }
  791. };
  792. //==============================================================================
  793. //==============================================================================
  794. struct Statement : public AllocatedObject
  795. {
  796. Statement (const CodeLocation& l, BlockPtr parent) noexcept : location (l), parentBlock (parent) {}
  797. virtual void emit (CodeGenerator&, Type, int /*stackDepth*/) const {}
  798. virtual bool alwaysReturns() const { return false; }
  799. virtual void visitSubStatements (std::function<void(StatementPtr)>) const {}
  800. virtual Statement* simplify (SyntaxTreeBuilder&) { return this; }
  801. CodeLocation location;
  802. BlockPtr parentBlock;
  803. };
  804. struct Expression : public Statement
  805. {
  806. Expression (const CodeLocation& l, BlockPtr parent) noexcept : Statement (l, parent) {}
  807. virtual Type getType (CodeGenerator&) const = 0;
  808. };
  809. struct Variable
  810. {
  811. String name;
  812. Type type;
  813. };
  814. //==============================================================================
  815. struct Function : public AllocatedObject
  816. {
  817. FunctionID functionID;
  818. Type returnType;
  819. Array<Variable> arguments;
  820. BlockPtr block;
  821. CodeGenerator::Marker address, unwindAddress;
  822. void emit (CodeGenerator& cg) const
  823. {
  824. cg.attachMarker (address);
  825. const int numLocals = getNumLocals();
  826. for (int num = numLocals; num > 0;)
  827. {
  828. if (num == 1)
  829. {
  830. cg.emit (OpCode::push0);
  831. --num;
  832. }
  833. else
  834. {
  835. int numToDo = jmin (127, num);
  836. cg.emit (OpCode::pushMultiple0, (int8) numToDo);
  837. num -= numToDo;
  838. }
  839. }
  840. block->emit (cg, Type::void_, 0);
  841. cg.attachMarker (unwindAddress);
  842. const bool keepTop = returnType != Type::void_;
  843. for (int num = numLocals; num > 0;)
  844. {
  845. if (num == 1 && ! keepTop)
  846. {
  847. cg.emit (OpCode::drop);
  848. --num;
  849. }
  850. else
  851. {
  852. int numToDo = jmin (127, num);
  853. cg.emit (OpCode::dropMultiple, (int8) (keepTop ? -numToDo : numToDo));
  854. num -= numToDo;
  855. }
  856. }
  857. cg.emit (keepTop ? OpCode::retValue : OpCode::retVoid, (int8) arguments.size());
  858. }
  859. Array<Type> getArgumentTypes() const
  860. {
  861. Array<Type> argTypes;
  862. for (auto& arg : arguments)
  863. argTypes.add (arg.type);
  864. return argTypes;
  865. }
  866. int getNumLocals() const noexcept
  867. {
  868. return countMaxNumLocalVariables (block);
  869. }
  870. static int countMaxNumLocalVariables (StatementPtr s) noexcept
  871. {
  872. int num = 0;
  873. if (s != nullptr)
  874. s->visitSubStatements ([&] (StatementPtr sub) { num = jmax (num, countMaxNumLocalVariables (sub)); });
  875. if (auto block = dynamic_cast<BlockPtr> (s))
  876. num += block->variables.size();
  877. return num;
  878. }
  879. };
  880. //==============================================================================
  881. struct BlockStatement : public Statement
  882. {
  883. BlockStatement (const CodeLocation& l, BlockPtr parent, Function* f, bool isMainFunctionBlock)
  884. : Statement (l, parent), function (f), isMainBlockOfFunction (isMainFunctionBlock) {}
  885. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  886. {
  887. jassert (requiredType == Type::void_); ignoreUnused (requiredType);
  888. jassert (function != nullptr);
  889. for (auto s : statements)
  890. s->emit (cg, Type::void_, stackDepth);
  891. }
  892. bool alwaysReturns() const override
  893. {
  894. return ! statements.isEmpty() && statements.getLast()->alwaysReturns();
  895. }
  896. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  897. {
  898. for (auto s : statements)
  899. visit (s);
  900. }
  901. Statement* simplify (SyntaxTreeBuilder& stb) override
  902. {
  903. for (int i = 0; i < statements.size(); ++i)
  904. statements.set (i, statements.getReference(i)->simplify (stb));
  905. return this;
  906. }
  907. // returns -ve values for globals
  908. int getVariableDepth (const String& name, const CodeLocation& locationForError) const
  909. {
  910. int index = indexOf (variables, name);
  911. if (index >= 0)
  912. return getNumVariablesInParentBlocks() + index;
  913. if (! isMainBlockOfFunction)
  914. return parentBlock->getVariableDepth (name, locationForError);
  915. for (int i = function->arguments.size(); --i >= 0;)
  916. if (function->arguments.getReference(i).name == name)
  917. return i + 1 + function->getNumLocals();
  918. index = indexOf (getGlobalVariables(), name);
  919. if (index >= 0)
  920. return -(index + 1);
  921. locationForError.throwError ("Unknown variable '" + name + "'");
  922. return 0;
  923. }
  924. int getNumVariablesInParentBlocks() const noexcept
  925. {
  926. return isMainBlockOfFunction ? 0 : (parentBlock->getNumVariablesInParentBlocks()
  927. + parentBlock->variables.size());
  928. }
  929. const Array<Variable>& getGlobalVariables() const noexcept
  930. {
  931. return parentBlock != nullptr ? parentBlock->getGlobalVariables() : variables;
  932. }
  933. Type getVariableType (const String& name, const CodeLocation& locationForError) const
  934. {
  935. for (auto& v : variables)
  936. if (v.name == name)
  937. return v.type;
  938. if (! isMainBlockOfFunction)
  939. return parentBlock->getVariableType (name, locationForError);
  940. for (auto& v : function->arguments)
  941. if (v.name == name)
  942. return v.type;
  943. for (auto& v : getGlobalVariables())
  944. if (v.name == name)
  945. return v.type;
  946. locationForError.throwError ("Unknown variable '" + name + "'");
  947. return {};
  948. }
  949. void addVariable (const String& name, Type type, const CodeLocation& locationForError)
  950. {
  951. if (indexOf (variables, name) >= 0)
  952. locationForError.throwError ("Variable '" + name + "' already exists");
  953. variables.add ({ name, type });
  954. }
  955. static int indexOf (const Array<Variable>& vars, const String& name) noexcept
  956. {
  957. for (int i = 0; i < vars.size(); ++i)
  958. if (vars.getReference(i).name == name)
  959. return i;
  960. return -1;
  961. }
  962. Function* function;
  963. Array<StatementPtr> statements;
  964. Array<Variable> variables;
  965. bool isMainBlockOfFunction;
  966. };
  967. struct IfStatement : public Statement
  968. {
  969. IfStatement (const CodeLocation& l, BlockPtr parent) : Statement (l, parent) {}
  970. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  971. {
  972. jassert (requiredType == Type::void_); ignoreUnused (requiredType);
  973. condition->emit (cg, Type::bool_, stackDepth);
  974. auto endOfStatement = cg.createMarker();
  975. if (falseBranch == nullptr)
  976. {
  977. cg.emit (OpCode::jumpIfFalse, endOfStatement);
  978. trueBranch->emit (cg, Type::void_, stackDepth);
  979. }
  980. else
  981. {
  982. auto elseTarget = cg.createMarker();
  983. cg.emit (OpCode::jumpIfFalse, elseTarget);
  984. trueBranch->emit (cg, Type::void_, stackDepth);
  985. cg.emit (OpCode::jump, endOfStatement);
  986. cg.attachMarker (elseTarget);
  987. falseBranch->emit (cg, Type::void_, stackDepth);
  988. }
  989. cg.attachMarker (endOfStatement);
  990. }
  991. bool alwaysReturns() const override
  992. {
  993. return trueBranch->alwaysReturns() && falseBranch != nullptr && falseBranch->alwaysReturns();
  994. }
  995. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  996. {
  997. visit (condition); visit (trueBranch); visit (falseBranch);
  998. }
  999. Statement* simplify (SyntaxTreeBuilder& stb) override
  1000. {
  1001. condition = dynamic_cast<ExpPtr> (condition->simplify (stb));
  1002. trueBranch = trueBranch->simplify (stb);
  1003. falseBranch = falseBranch != nullptr ? falseBranch->simplify (stb) : nullptr;
  1004. if (auto literal = dynamic_cast<LiteralValue*> (condition))
  1005. return literal->value ? trueBranch : (falseBranch != nullptr ? falseBranch : stb.allocate<Statement> (location, parentBlock));
  1006. return this;
  1007. }
  1008. ExpPtr condition;
  1009. StatementPtr trueBranch, falseBranch;
  1010. };
  1011. struct TerneryOp : public Expression
  1012. {
  1013. TerneryOp (const CodeLocation& l, BlockPtr parent) : Expression (l, parent) {}
  1014. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1015. {
  1016. condition->emit (cg, Type::bool_, stackDepth);
  1017. auto endOfStatement = cg.createMarker();
  1018. auto elseTarget = cg.createMarker();
  1019. cg.emit (OpCode::jumpIfFalse, elseTarget);
  1020. trueBranch->emit (cg, requiredType, stackDepth);
  1021. cg.emit (OpCode::jump, endOfStatement);
  1022. cg.attachMarker (elseTarget);
  1023. falseBranch->emit (cg, requiredType, stackDepth);
  1024. cg.attachMarker (endOfStatement);
  1025. }
  1026. Type getType (CodeGenerator& cg) const override
  1027. {
  1028. auto type = trueBranch->getType (cg);
  1029. if (type == Type::void_) location.throwError ("The ternery operator cannot take void arguments");
  1030. if (type != falseBranch->getType (cg)) location.throwError ("Expected both branches of this ternery operator to have the same type");
  1031. return type;
  1032. }
  1033. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1034. {
  1035. visit (condition); visit (trueBranch); visit (falseBranch);
  1036. }
  1037. Statement* simplify (SyntaxTreeBuilder& stb) override
  1038. {
  1039. condition = dynamic_cast<ExpPtr> (condition->simplify (stb));
  1040. trueBranch = dynamic_cast<ExpPtr> (trueBranch->simplify (stb));
  1041. falseBranch = dynamic_cast<ExpPtr> (falseBranch->simplify (stb));
  1042. if (auto literal = dynamic_cast<LiteralValue*> (condition))
  1043. return literal->value ? trueBranch : falseBranch;
  1044. return this;
  1045. }
  1046. ExpPtr condition, trueBranch, falseBranch;
  1047. };
  1048. struct LoopStatement : public Statement
  1049. {
  1050. LoopStatement (const CodeLocation& l, BlockPtr parent, bool isDo) noexcept : Statement (l, parent), isDoLoop (isDo) {}
  1051. void emit (CodeGenerator& cg, Type, int stackDepth) const override
  1052. {
  1053. initialiser->emit (cg, Type::void_, stackDepth);
  1054. auto loopStart = cg.createMarker();
  1055. cg.attachMarker (loopStart);
  1056. auto oldBreakTarget = cg.breakTarget;
  1057. auto oldContinueTarget = cg.continueTarget;
  1058. cg.breakTarget = cg.createMarker();
  1059. cg.continueTarget = cg.createMarker();
  1060. if (isDoLoop)
  1061. {
  1062. body->emit (cg, Type::void_, stackDepth);
  1063. cg.attachMarker (cg.continueTarget);
  1064. condition->emit (cg, Type::bool_, stackDepth);
  1065. cg.emit (OpCode::jumpIfTrue, loopStart);
  1066. }
  1067. else
  1068. {
  1069. condition->emit (cg, Type::bool_, stackDepth);
  1070. cg.emit (OpCode::jumpIfFalse, cg.breakTarget);
  1071. body->emit (cg, Type::void_, stackDepth);
  1072. cg.attachMarker (cg.continueTarget);
  1073. iterator->emit (cg, Type::void_, stackDepth);
  1074. cg.emit (OpCode::jump, loopStart);
  1075. }
  1076. cg.attachMarker (cg.breakTarget);
  1077. cg.breakTarget = oldBreakTarget;
  1078. cg.continueTarget = oldContinueTarget;
  1079. }
  1080. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1081. {
  1082. visit (condition); visit (initialiser); visit (iterator); visit (body);
  1083. }
  1084. StatementPtr initialiser, iterator, body;
  1085. ExpPtr condition;
  1086. bool isDoLoop;
  1087. };
  1088. struct ReturnStatement : public Statement
  1089. {
  1090. ReturnStatement (const CodeLocation& l, BlockPtr parent, ExpPtr v) noexcept : Statement (l, parent), returnValue (v) {}
  1091. void emit (CodeGenerator& cg, Type, int stackDepth) const override
  1092. {
  1093. if (auto fn = parentBlock->function)
  1094. {
  1095. if (returnValue != nullptr)
  1096. returnValue->emit (cg, fn->returnType, stackDepth);
  1097. else if (fn->returnType != Type::void_)
  1098. location.throwError ("Cannot return a value from a void function");
  1099. if (parentBlock->statements.getLast() != this)
  1100. cg.emit (OpCode::jump, fn->unwindAddress);
  1101. return;
  1102. }
  1103. location.throwError ("The return statement can only be used inside a function");
  1104. }
  1105. bool alwaysReturns() const override { return true; }
  1106. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1107. {
  1108. visit (returnValue);
  1109. }
  1110. ExpPtr returnValue;
  1111. };
  1112. struct BreakStatement : public Statement
  1113. {
  1114. BreakStatement (const CodeLocation& l, BlockPtr parent) : Statement (l, parent) {}
  1115. void emit (CodeGenerator& cg, Type, int) const override
  1116. {
  1117. if (cg.breakTarget.index == 0)
  1118. location.throwError ("The break statement can only be used inside a loop");
  1119. cg.emit (OpCode::jump, cg.breakTarget);
  1120. }
  1121. };
  1122. struct ContinueStatement : public Statement
  1123. {
  1124. ContinueStatement (const CodeLocation& l, BlockPtr parent) : Statement (l, parent) {}
  1125. void emit (CodeGenerator& cg, Type, int) const override
  1126. {
  1127. if (cg.continueTarget.index == 0)
  1128. location.throwError ("The continue statement can only be used inside a loop");
  1129. cg.emit (OpCode::jump, cg.continueTarget);
  1130. }
  1131. };
  1132. struct LiteralValue : public Expression
  1133. {
  1134. LiteralValue (const CodeLocation& l, BlockPtr parent, const var& v) noexcept : Expression (l, parent), value (v) {}
  1135. void emit (CodeGenerator& cg, Type requiredType, int) const override
  1136. {
  1137. if (requiredType != Type::void_)
  1138. {
  1139. auto type = getType (cg);
  1140. if (type != requiredType && value != var ((int) 0))
  1141. {
  1142. if (type == Type::int_ && requiredType == Type::bool_) return cg.emitPush (static_cast<bool> (value));
  1143. if (type == Type::int_ && requiredType == Type::float_) return cg.emitPush (static_cast<float> (value));
  1144. if (! (type == Type::bool_ && requiredType == Type::int_))
  1145. location.throwError ("Cannot cast from " + getTypeName (type) + " to " + getTypeName (requiredType));
  1146. }
  1147. cg.emitPush (value);
  1148. }
  1149. }
  1150. Type getType (CodeGenerator&) const override
  1151. {
  1152. auto t = getTypeOfVar (value);
  1153. if (t == Type::void_)
  1154. location.throwError ("Unsupported literal type");
  1155. return t;
  1156. }
  1157. var value;
  1158. };
  1159. struct Identifier : public Expression
  1160. {
  1161. Identifier (const CodeLocation& l, BlockPtr parent, const String& n) noexcept : Expression (l, parent), name (n) {}
  1162. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1163. {
  1164. cg.emitVariableRead (getType (cg), requiredType, stackDepth,
  1165. parentBlock->getVariableDepth (name, location), location);
  1166. }
  1167. Type getType (CodeGenerator&) const override
  1168. {
  1169. return parentBlock->getVariableType (name, location);
  1170. }
  1171. String name;
  1172. };
  1173. struct UnaryOp : public Expression
  1174. {
  1175. UnaryOp (const CodeLocation& l, BlockPtr parent, ExpPtr a, TokenType op) noexcept
  1176. : Expression (l, parent), source (a), operation (op) {}
  1177. ExpPtr source;
  1178. TokenType operation;
  1179. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1180. {
  1181. auto sourceType = source->getType (cg);
  1182. if (operation == Token::minus)
  1183. {
  1184. cg.emitPush ((int) 0);
  1185. source->emit (cg, sourceType, stackDepth + 1);
  1186. cg.emit (sourceType == Type::float_ ? OpCode::sub_float : OpCode::sub_int32);
  1187. cg.emitCast (sourceType, requiredType, location);
  1188. }
  1189. else
  1190. {
  1191. if (sourceType == Type::float_)
  1192. location.throwError ("Cannot perform this operation on a float");
  1193. if (operation == Token::logicalNot)
  1194. {
  1195. source->emit (cg, sourceType, stackDepth);
  1196. cg.emit (OpCode::logicalNot);
  1197. cg.emitCast (Type::bool_, requiredType, location);
  1198. }
  1199. else if (operation == Token::bitwiseNot)
  1200. {
  1201. source->emit (cg, Type::int_, stackDepth);
  1202. cg.emit (OpCode::bitwiseNot);
  1203. cg.emitCast (Type::int_, requiredType, location);
  1204. }
  1205. }
  1206. }
  1207. Type getType (CodeGenerator& cg) const override
  1208. {
  1209. if (operation == Token::minus) return source->getType (cg);
  1210. if (operation == Token::logicalNot) return Type::bool_;
  1211. return Type::int_;
  1212. }
  1213. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1214. {
  1215. visit (source);
  1216. }
  1217. Statement* simplify (SyntaxTreeBuilder& stb) override
  1218. {
  1219. source = dynamic_cast<ExpPtr> (source->simplify (stb));
  1220. if (auto literal = dynamic_cast<LiteralValue*> (source))
  1221. {
  1222. auto type = getTypeOfVar (literal->value);
  1223. if (type == Type::int_ && operation == Token::minus) { literal->value = -static_cast<int> (literal->value); return literal; }
  1224. if (type == Type::int_ && operation == Token::bitwiseNot) { literal->value = ~static_cast<int> (literal->value); return literal; }
  1225. if (type == Type::int_ && operation == Token::logicalNot) { literal->value = ! static_cast<int> (literal->value); return literal; }
  1226. if (type == Type::bool_ && operation == Token::logicalNot) { literal->value = ! static_cast<bool> (literal->value); return literal; }
  1227. if (type == Type::float_ && operation == Token::minus) { literal->value = -static_cast<double> (literal->value); return literal; }
  1228. }
  1229. return this;
  1230. }
  1231. };
  1232. struct BinaryOperator : public Expression
  1233. {
  1234. BinaryOperator (const CodeLocation& l, BlockPtr parent, ExpPtr a, ExpPtr b, TokenType op) noexcept
  1235. : Expression (l, parent), lhs (a), rhs (b), operation (op) {}
  1236. ExpPtr lhs, rhs;
  1237. TokenType operation;
  1238. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1239. {
  1240. auto typeA = lhs->getType (cg);
  1241. auto typeB = rhs->getType (cg);
  1242. if (typeA == Type::float_ || typeB == Type::float_)
  1243. {
  1244. lhs->emit (cg, Type::float_, stackDepth);
  1245. rhs->emit (cg, Type::float_, stackDepth + 1);
  1246. if (operation == Token::plus) return emitOpAndCast (cg, requiredType, OpCode::add_float);
  1247. if (operation == Token::minus) return emitOpAndCast (cg, requiredType, OpCode::sub_float);
  1248. if (operation == Token::times) return emitOpAndCast (cg, requiredType, OpCode::mul_float);
  1249. if (operation == Token::divide) return emitOpAndCast (cg, requiredType, OpCode::div_float);
  1250. cg.emit (OpCode::sub_float);
  1251. if (operation == Token::equals) return emitOpAndCast (cg, requiredType, OpCode::testZE_float);
  1252. if (operation == Token::notEquals) return emitOpAndCast (cg, requiredType, OpCode::testNZ_float);
  1253. if (operation == Token::lessThan) return emitOpAndCast (cg, requiredType, OpCode::testLT_float);
  1254. if (operation == Token::lessThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testLE_float);
  1255. if (operation == Token::greaterThan) return emitOpAndCast (cg, requiredType, OpCode::testGT_float);
  1256. if (operation == Token::greaterThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testGE_float);
  1257. location.throwError ("The operator " + getTokenDescription (operation) + " cannot take floating point arguments");
  1258. }
  1259. auto type = (typeA == Type::bool_ || typeB == Type::bool_) ? Type::bool_
  1260. : Type::int_;
  1261. lhs->emit (cg, type, stackDepth);
  1262. rhs->emit (cg, type, stackDepth + 1);
  1263. if (operation == Token::plus) return emitOpAndCast (cg, requiredType, OpCode::add_int32);
  1264. if (operation == Token::minus) return emitOpAndCast (cg, requiredType, OpCode::sub_int32);
  1265. if (operation == Token::times) return emitOpAndCast (cg, requiredType, OpCode::mul_int32);
  1266. if (operation == Token::divide) return emitOpAndCast (cg, requiredType, OpCode::div_int32);
  1267. if (operation == Token::modulo) return emitOpAndCast (cg, requiredType, OpCode::mod_int32);
  1268. if (operation == Token::logicalOr) return emitOpAndCast (cg, requiredType, OpCode::logicalOr);
  1269. if (operation == Token::logicalAnd) return emitOpAndCast (cg, requiredType, OpCode::logicalAnd);
  1270. if (operation == Token::bitwiseOr) return emitOpAndCast (cg, requiredType, OpCode::bitwiseOr);
  1271. if (operation == Token::bitwiseAnd) return emitOpAndCast (cg, requiredType, OpCode::bitwiseAnd);
  1272. if (operation == Token::bitwiseXor) return emitOpAndCast (cg, requiredType, OpCode::bitwiseXor);
  1273. if (operation == Token::leftShift) return emitOpAndCast (cg, requiredType, OpCode::bitShiftLeft);
  1274. if (operation == Token::rightShift) return emitOpAndCast (cg, requiredType, OpCode::bitShiftRight);
  1275. cg.emit (OpCode::sub_int32);
  1276. if (operation == Token::equals) return emitOpAndCast (cg, requiredType, OpCode::testZE_int32);
  1277. if (operation == Token::notEquals) return emitOpAndCast (cg, requiredType, OpCode::testNZ_int32);
  1278. if (operation == Token::lessThan) return emitOpAndCast (cg, requiredType, OpCode::testLT_int32);
  1279. if (operation == Token::lessThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testLE_int32);
  1280. if (operation == Token::greaterThan) return emitOpAndCast (cg, requiredType, OpCode::testGT_int32);
  1281. if (operation == Token::greaterThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testGE_int32);
  1282. location.throwError ("Unsupported operator");
  1283. jassertfalse;
  1284. }
  1285. void emitOpAndCast (CodeGenerator& cg, Type requiredType, OpCode op) const
  1286. {
  1287. cg.emit (op);
  1288. cg.emitCast (getType (cg), requiredType, location);
  1289. }
  1290. Type getResultType (Type typeA, Type typeB) const noexcept
  1291. {
  1292. if (operation == Token::logicalOr || operation == Token::logicalAnd
  1293. || operation == Token::equals || operation == Token::notEquals
  1294. || operation == Token::lessThan || operation == Token::lessThanOrEqual
  1295. || operation == Token::greaterThan || operation == Token::greaterThanOrEqual)
  1296. return Type::bool_;
  1297. if (operation == Token::plus || operation == Token::minus
  1298. || operation == Token::times || operation == Token::divide)
  1299. {
  1300. if (typeA == Type::float_ || typeB == Type::float_)
  1301. return Type::float_;
  1302. }
  1303. return Type::int_;
  1304. }
  1305. Type getType (CodeGenerator& cg) const override
  1306. {
  1307. return getResultType (lhs->getType (cg), rhs->getType (cg));
  1308. }
  1309. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1310. {
  1311. visit (lhs); visit (rhs);
  1312. }
  1313. Statement* simplifyFloat (double a, double b, LiteralValue* literal)
  1314. {
  1315. if (operation == Token::plus) { literal->value = a + b; return literal; }
  1316. if (operation == Token::minus) { literal->value = a - b; return literal; }
  1317. if (operation == Token::times) { literal->value = a * b; return literal; }
  1318. if (operation == Token::divide) { literal->value = a / b; return literal; }
  1319. if (operation == Token::equals) { literal->value = a == b; return literal; }
  1320. if (operation == Token::notEquals) { literal->value = a != b; return literal; }
  1321. if (operation == Token::lessThan) { literal->value = a < b; return literal; }
  1322. if (operation == Token::lessThanOrEqual) { literal->value = a <= b; return literal; }
  1323. if (operation == Token::greaterThan) { literal->value = a > b; return literal; }
  1324. if (operation == Token::greaterThanOrEqual) { literal->value = a >= b; return literal; }
  1325. return this;
  1326. }
  1327. Statement* simplifyBool (bool a, bool b, LiteralValue* literal)
  1328. {
  1329. if (operation == Token::logicalOr) { literal->value = a || b; return literal; }
  1330. if (operation == Token::logicalAnd) { literal->value = a && b; return literal; }
  1331. return this;
  1332. }
  1333. Statement* simplifyInt (int a, int b, LiteralValue* literal)
  1334. {
  1335. if (operation == Token::plus) { literal->value = a + b; return literal; }
  1336. if (operation == Token::minus) { literal->value = a - b; return literal; }
  1337. if (operation == Token::times) { literal->value = a * b; return literal; }
  1338. if (operation == Token::divide) { literal->value = a / b; return literal; }
  1339. if (operation == Token::equals) { literal->value = a == b; return literal; }
  1340. if (operation == Token::notEquals) { literal->value = a != b; return literal; }
  1341. if (operation == Token::lessThan) { literal->value = a < b; return literal; }
  1342. if (operation == Token::lessThanOrEqual) { literal->value = a <= b; return literal; }
  1343. if (operation == Token::greaterThan) { literal->value = a > b; return literal; }
  1344. if (operation == Token::greaterThanOrEqual) { literal->value = a >= b; return literal; }
  1345. if (operation == Token::modulo) { literal->value = a % b; return literal; }
  1346. if (operation == Token::logicalOr) { literal->value = a || b; return literal; }
  1347. if (operation == Token::logicalAnd) { literal->value = a && b; return literal; }
  1348. if (operation == Token::bitwiseOr) { literal->value = a | b; return literal; }
  1349. if (operation == Token::bitwiseAnd) { literal->value = a & b; return literal; }
  1350. if (operation == Token::bitwiseXor) { literal->value = a ^ b; return literal; }
  1351. if (operation == Token::leftShift) { literal->value = a << b; return literal; }
  1352. if (operation == Token::rightShift) { literal->value = a >> b; return literal; }
  1353. return this;
  1354. }
  1355. Statement* simplify (SyntaxTreeBuilder& stb) override
  1356. {
  1357. lhs = dynamic_cast<ExpPtr> (lhs->simplify (stb));
  1358. rhs = dynamic_cast<ExpPtr> (rhs->simplify (stb));
  1359. if (auto literal1 = dynamic_cast<LiteralValue*> (lhs))
  1360. {
  1361. if (auto literal2 = dynamic_cast<LiteralValue*> (rhs))
  1362. {
  1363. auto resultType = getResultType (getTypeOfVar (literal1->value),
  1364. getTypeOfVar (literal2->value));
  1365. if (resultType == Type::bool_) return simplifyBool (literal1->value, literal2->value, literal1);
  1366. if (resultType == Type::int_) return simplifyInt (literal1->value, literal2->value, literal1);
  1367. if (resultType == Type::float_) return simplifyFloat (literal1->value, literal2->value, literal1);
  1368. }
  1369. }
  1370. return this;
  1371. }
  1372. };
  1373. struct Assignment : public Expression
  1374. {
  1375. Assignment (const CodeLocation& l, BlockPtr parent, const String& dest, ExpPtr source, bool isPost) noexcept
  1376. : Expression (l, parent), target (dest), newValue (source), isPostAssignment (isPost) {}
  1377. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1378. {
  1379. auto variableType = getType (cg);
  1380. if (isPostAssignment && requiredType != Type::void_)
  1381. {
  1382. cg.emitVariableRead (variableType, requiredType, stackDepth,
  1383. parentBlock->getVariableDepth (target, location), location);
  1384. ++stackDepth;
  1385. requiredType = Type::void_;
  1386. }
  1387. newValue->emit (cg, variableType, stackDepth);
  1388. auto index = parentBlock->getVariableDepth (target, location);
  1389. if (requiredType != Type::void_)
  1390. {
  1391. cg.emit (OpCode::dup);
  1392. ++stackDepth;
  1393. }
  1394. if (index < 0)
  1395. {
  1396. cg.emit (OpCode::dropToGlobal, (int16) ((-index) - 1));
  1397. }
  1398. else
  1399. {
  1400. index += stackDepth;
  1401. if (index >= 128)
  1402. cg.emit (OpCode::dropToStack16, (int16) index);
  1403. else
  1404. cg.emit (OpCode::dropToStack, (int8) index);
  1405. }
  1406. if (requiredType != Type::void_)
  1407. cg.emitCast (variableType, requiredType, location);
  1408. }
  1409. Type getType (CodeGenerator&) const override
  1410. {
  1411. return parentBlock->getVariableType (target, location);
  1412. }
  1413. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1414. {
  1415. visit (newValue);
  1416. }
  1417. Statement* simplify (SyntaxTreeBuilder& stb) override
  1418. {
  1419. newValue = dynamic_cast<ExpPtr> (newValue->simplify (stb));
  1420. return this;
  1421. }
  1422. String target;
  1423. ExpPtr newValue;
  1424. bool isPostAssignment;
  1425. };
  1426. struct FunctionCall : public Expression
  1427. {
  1428. FunctionCall (const CodeLocation& l, BlockPtr parent) noexcept : Expression (l, parent) {}
  1429. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1430. {
  1431. if (functionName == Token::int_) return emitCast (cg, Type::int_, stackDepth);
  1432. if (functionName == Token::float_) return emitCast (cg, Type::float_, stackDepth);
  1433. if (functionName == Token::bool_) return emitCast (cg, Type::bool_, stackDepth);
  1434. auto functionID = getFunctionID (cg);
  1435. if (auto fn = cg.findFunction (functionID))
  1436. {
  1437. emitArgs (cg, fn->getArgumentTypes(), stackDepth);
  1438. cg.emit (OpCode::call, fn->address);
  1439. cg.emitCast (fn->returnType, requiredType, location);
  1440. return;
  1441. }
  1442. if (auto nativeFn = cg.findNativeFunction (functionID))
  1443. {
  1444. emitArgs (cg, getArgTypesFromFunctionName (nativeFn->nameAndArguments), stackDepth);
  1445. cg.emit (OpCode::callNative, nativeFn->functionID);
  1446. cg.emitCast (nativeFn->returnType, requiredType, location);
  1447. return;
  1448. }
  1449. if (auto b = findBuiltInFunction (functionID))
  1450. {
  1451. emitArgs (cg, getArgTypesFromFunctionName (b->name), stackDepth);
  1452. cg.emit (b->op);
  1453. cg.emitCast (b->returnType, requiredType, location);
  1454. return;
  1455. }
  1456. throwCannotFindFunctionError (cg, requiredType);
  1457. }
  1458. Type getType (CodeGenerator& cg) const override
  1459. {
  1460. if (arguments.size() == 1)
  1461. {
  1462. if (functionName == Token::float_) return Type::float_;
  1463. if (functionName == Token::int_) return Type::int_;
  1464. if (functionName == Token::bool_) return Type::bool_;
  1465. }
  1466. auto functionID = getFunctionID (cg);
  1467. if (auto fn = cg.findFunction (functionID))
  1468. return fn->returnType;
  1469. if (auto nativeFn = cg.findNativeFunction (functionID))
  1470. return nativeFn->returnType;
  1471. if (auto b = findBuiltInFunction (functionID))
  1472. return b->returnType;
  1473. throwCannotFindFunctionError (cg, Type::void_);
  1474. return {};
  1475. }
  1476. struct BuiltInFunction { OpCode op; Type returnType; const char* name; };
  1477. const BuiltInFunction* findBuiltInFunction (FunctionID functionID) const noexcept
  1478. {
  1479. static constexpr const BuiltInFunction builtIns[] =
  1480. {
  1481. { OpCode::getHeapByte, Type::int_, "getHeapByte/ii" },
  1482. { OpCode::getHeapInt, Type::int_, "getHeapInt/ii" },
  1483. { OpCode::getHeapBits, Type::int_, "getHeapBits/iii" },
  1484. { OpCode::setHeapByte, Type::void_, "setHeapByte/vii" },
  1485. { OpCode::setHeapInt, Type::void_, "setHeapInt/vii" }
  1486. };
  1487. for (auto& b : builtIns)
  1488. if (functionID == NativeFunction::createID (b.name))
  1489. return &b;
  1490. return nullptr;
  1491. }
  1492. void emitArgs (CodeGenerator& cg, const Array<Type>& argTypes, int stackDepth) const
  1493. {
  1494. for (int i = arguments.size(); --i >= 0;)
  1495. {
  1496. auto argType = argTypes[i];
  1497. auto argValue = arguments.getUnchecked(i);
  1498. if (argValue->getType (cg) != argType)
  1499. location.throwError ("Argument " + String (i + 1) + " requires an expression of type " + getTypeName (argType));
  1500. argValue->emit (cg, argType, stackDepth++);
  1501. }
  1502. }
  1503. void emitCast (CodeGenerator& cg, Type destType, int stackDepth) const
  1504. {
  1505. auto* arg = arguments.getReference (0);
  1506. const auto sourceType = arg->getType (cg);
  1507. arg->emit (cg, sourceType, stackDepth);
  1508. const bool sourceIsFloat = (sourceType == Type::float_);
  1509. const bool destIsFloat = (destType == Type::float_);
  1510. if (sourceIsFloat != destIsFloat)
  1511. cg.emit (destIsFloat ? OpCode::int32ToFloat : OpCode::floatToInt32);
  1512. }
  1513. FunctionID getFunctionID (CodeGenerator& cg) const
  1514. {
  1515. Array<Type> argTypes;
  1516. for (auto arg : arguments)
  1517. argTypes.add (arg->getType (cg));
  1518. return createFunctionID (functionName, Type::void_, argTypes); // NB: the ID ignores the return type so void is OK
  1519. }
  1520. void throwCannotFindFunctionError (CodeGenerator& cg, Type returnType) const
  1521. {
  1522. StringArray args;
  1523. for (auto arg : arguments)
  1524. args.add (getTypeName (arg->getType (cg)));
  1525. auto desc = getTypeName (returnType) + " " + functionName
  1526. + "(" + args.joinIntoString (", ") + ")";
  1527. location.throwError ("Cannot find matching function: " + desc.quoted());
  1528. }
  1529. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1530. {
  1531. for (auto& arg : arguments)
  1532. visit (arg);
  1533. }
  1534. String functionName;
  1535. Array<ExpPtr> arguments;
  1536. };
  1537. struct ArraySubscript : public Expression
  1538. {
  1539. ArraySubscript (const CodeLocation& l, BlockPtr parent) noexcept : Expression (l, parent) {}
  1540. void emit (CodeGenerator&, Type /*requiredType*/, int /*stackDepth*/) const override
  1541. {
  1542. location.throwError ("Arrays are not implemented yet!");
  1543. }
  1544. void visitSubStatements (std::function<void(StatementPtr)> visit) const override
  1545. {
  1546. visit (object); visit (index);
  1547. }
  1548. Statement* simplify (SyntaxTreeBuilder& stb) override
  1549. {
  1550. object = dynamic_cast<ExpPtr> (object->simplify (stb));
  1551. index = dynamic_cast<ExpPtr> (index->simplify (stb));
  1552. return this;
  1553. }
  1554. Type getType (CodeGenerator& cg) const override
  1555. {
  1556. return object->getType (cg);
  1557. }
  1558. ExpPtr object, index;
  1559. };
  1560. //==============================================================================
  1561. static Array<Type> getArgTypesFromFunctionName (const char* nameAndTypes)
  1562. {
  1563. Array<Type> types;
  1564. auto args = String (nameAndTypes).fromFirstOccurrenceOf ("/", false, false).substring (1);
  1565. for (int i = 0; i < args.length(); ++i)
  1566. types.add (static_cast<Type> (args[i]));
  1567. return types;
  1568. }
  1569. static FunctionID createFunctionID (String name, Type returnType, const Array<Type>& types)
  1570. {
  1571. name << "/" << (char) returnType;
  1572. for (auto t : types)
  1573. name << (char) t;
  1574. return NativeFunction::createID (name.toRawUTF8());
  1575. }
  1576. static String getTokenDescription (TokenType t) { return t[0] == '$' ? String (t + 1) : ("'" + String (t) + "'"); }
  1577. static String getTypeName (Type t) noexcept
  1578. {
  1579. if (t == Type::int_) return "int";
  1580. if (t == Type::bool_) return "bool";
  1581. if (t == Type::float_) return "float";
  1582. return "void";
  1583. }
  1584. static Type tokenToType (TokenType t) noexcept
  1585. {
  1586. if (t == Token::int_) return Type::int_;
  1587. if (t == Token::bool_) return Type::bool_;
  1588. if (t == Token::float_) return Type::float_;
  1589. return Type::void_;
  1590. }
  1591. static Type getTypeOfVar (const var& v) noexcept
  1592. {
  1593. if (v.isInt() || v.isInt64()) return Type::int_;
  1594. if (v.isDouble()) return Type::float_;
  1595. if (v.isBool()) return Type::bool_;
  1596. return Type::void_;
  1597. }
  1598. };
  1599. }