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.

2450 lines
93KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. #if JUCE_MSVC
  18. #pragma warning (push)
  19. #pragma warning (disable: 4702)
  20. #endif
  21. namespace littlefoot
  22. {
  23. /**
  24. This class compiles littlefoot source code into a littlefoot::Program object
  25. which can be executed by a littlefoot::Runner.
  26. @tags{Blocks}
  27. */
  28. struct Compiler
  29. {
  30. Compiler() = default;
  31. /** Gives the compiler a zero-terminated list of native function prototypes to
  32. use when parsing function calls.
  33. */
  34. void addNativeFunctions (const char* const* functionPrototypes)
  35. {
  36. for (; *functionPrototypes != nullptr; ++functionPrototypes)
  37. nativeFunctions.add (NativeFunction (*functionPrototypes, nullptr));
  38. }
  39. /** Tells the compiler to use the list of native function prototypes from
  40. this littlefoot::Runner object.
  41. */
  42. template <typename RunnerType>
  43. void addNativeFunctions (const RunnerType& runner)
  44. {
  45. for (int i = 0; i < runner.getNumNativeFunctions(); ++i)
  46. nativeFunctions.add (runner.getNativeFunction (i));
  47. }
  48. /** Compiles a littlefoot program.
  49. If there's an error, this returns it, otherwise the compiled bytecode is
  50. placed in the compiledObjectCode member.
  51. */
  52. Result compile (const String& sourceCode, uint32 defaultHeapSize, const Array<File>& searchPaths = {})
  53. {
  54. try
  55. {
  56. SyntaxTreeBuilder stb (sourceCode, nativeFunctions, defaultHeapSize, searchPaths);
  57. stb.compile();
  58. stb.simplify();
  59. compiledObjectCode.clear();
  60. CodeGenerator codeGen (compiledObjectCode, stb);
  61. codeGen.generateCode (stb.blockBeingParsed, stb.heapSizeRequired);
  62. return Result::ok();
  63. }
  64. catch (String error)
  65. {
  66. return Result::fail (error);
  67. }
  68. }
  69. /** After a successful compilation, this returns the finished Program. */
  70. Program getCompiledProgram() const noexcept
  71. {
  72. return Program (compiledObjectCode.begin(), (uint32) compiledObjectCode.size());
  73. }
  74. /** After a successful call to compile(), this contains the bytecode generated.
  75. A littlefoot::Program object can be created directly from this array.
  76. */
  77. Array<uint8> compiledObjectCode;
  78. private:
  79. #ifndef DOXYGEN
  80. struct Statement;
  81. struct Expression;
  82. struct Variable;
  83. struct BlockStatement;
  84. struct Function;
  85. struct AllocatedObject { virtual ~AllocatedObject() noexcept {} };
  86. using StatementPtr = Statement*;
  87. using ExpPtr = Expression*;
  88. using BlockPtr = BlockStatement*;
  89. using TokenType = const char*;
  90. #define LITTLEFOOT_KEYWORDS(X) \
  91. X(if_, "if") X(else_, "else") X(do_, "do") \
  92. X(while_, "while") X(for_, "for") X(break_, "break") X(continue_, "continue") \
  93. X(void_, "void") X(int_, "int") X(float_, "float") X(bool_, "bool") \
  94. X(return_, "return") X(true_, "true") X(false_, "false") X(const_, "const")
  95. #define LITTLEFOOT_OPERATORS(X) \
  96. X(semicolon, ";") X(dot, ".") X(comma, ",") X(hash, "#") \
  97. X(openParen, "(") X(closeParen, ")") X(openBrace, "{") X(closeBrace, "}") \
  98. X(openBracket, "[") X(closeBracket, "]") X(colon, ":") X(question, "?") \
  99. X(equals, "==") X(assign, "=") X(notEquals, "!=") X(logicalNot, "!") \
  100. X(plusEquals, "+=") X(plusplus, "++") X(plus, "+") \
  101. X(minusEquals, "-=") X(minusminus, "--") X(minus, "-") \
  102. X(timesEquals, "*=") X(times, "*") X(divideEquals, "/=") X(divide, "/") \
  103. X(moduloEquals, "%=") X(modulo, "%") X(xorEquals, "^=") X(bitwiseXor, "^") X(bitwiseNot, "~") \
  104. X(andEquals, "&=") X(logicalAnd, "&&") X(bitwiseAnd, "&") \
  105. X(orEquals, "|=") X(logicalOr, "||") X(bitwiseOr, "|") \
  106. X(leftShiftEquals, "<<=") X(lessThanOrEqual, "<=") X(leftShift, "<<") X(lessThan, "<") \
  107. X(rightShiftUnsigned, ">>>") X(rightShiftEquals, ">>=") X(rightShift, ">>") X(greaterThanOrEqual, ">=") X(greaterThan, ">")
  108. struct Token
  109. {
  110. #define DECLARE_LITTLEFOOT_TOKEN(name, str) static constexpr const char* name = str;
  111. LITTLEFOOT_KEYWORDS (DECLARE_LITTLEFOOT_TOKEN)
  112. LITTLEFOOT_OPERATORS (DECLARE_LITTLEFOOT_TOKEN)
  113. DECLARE_LITTLEFOOT_TOKEN (eof, "$eof")
  114. DECLARE_LITTLEFOOT_TOKEN (literal, "$literal")
  115. DECLARE_LITTLEFOOT_TOKEN (identifier, "$identifier")
  116. };
  117. Array<NativeFunction> nativeFunctions;
  118. //==============================================================================
  119. struct CodeLocation
  120. {
  121. CodeLocation (const String& code, const File& srcFile) noexcept : program (code), location (program.getCharPointer()), sourceFile (srcFile) {}
  122. CodeLocation (const CodeLocation& other) noexcept : program (other.program), location (other.location), sourceFile (other.sourceFile) {}
  123. [[noreturn]] void throwError (const String& message) const
  124. {
  125. int col = 1, line = 1;
  126. for (auto i = program.getCharPointer(); i < location && ! i.isEmpty(); ++i)
  127. {
  128. ++col;
  129. if (*i == '\n') { col = 1; ++line; }
  130. }
  131. auto filePath = sourceFile == File() ? String() : (sourceFile.getFullPathName() + ": ");
  132. throw filePath + "Line " + String (line) + ", column " + String (col) + " : " + message;
  133. }
  134. String program;
  135. String::CharPointerType location;
  136. File sourceFile;
  137. };
  138. //==============================================================================
  139. struct TokenIterator
  140. {
  141. TokenIterator (const String& code) : location (code, {}), p (code.getCharPointer()) { skip(); }
  142. TokenType skip()
  143. {
  144. skipWhitespaceAndComments();
  145. location.location = p;
  146. auto last = currentType;
  147. currentType = matchNextToken();
  148. return last;
  149. }
  150. void match (TokenType expected)
  151. {
  152. if (currentType != expected)
  153. throwErrorExpecting (getTokenDescription (expected));
  154. skip();
  155. }
  156. bool matchIf (TokenType expected) { if (currentType == expected) { skip(); return true; } return false; }
  157. template <typename... Args>
  158. bool matchesAny (TokenType t1, Args... others) const noexcept { return currentType == t1 || matchesAny (others...); }
  159. bool matchesAny (TokenType t1) const noexcept { return currentType == t1; }
  160. void throwErrorExpecting (const String& expected) { location.throwError ("Found " + getTokenDescription (currentType) + " when expecting " + expected); }
  161. CodeLocation location;
  162. TokenType currentType;
  163. var currentValue;
  164. protected:
  165. String::CharPointerType p;
  166. private:
  167. static bool isIdentifierStart (juce_wchar c) noexcept { return CharacterFunctions::isLetter (c) || c == '_'; }
  168. static bool isIdentifierBody (juce_wchar c) noexcept { return CharacterFunctions::isLetterOrDigit (c) || c == '_'; }
  169. TokenType matchNextToken()
  170. {
  171. if (isIdentifierStart (*p))
  172. {
  173. auto end = p;
  174. while (isIdentifierBody (*++end)) {}
  175. const size_t len = (size_t) (end - p);
  176. #define LITTLEFOOT_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (Token::name, len)) return Token::name;
  177. LITTLEFOOT_KEYWORDS (LITTLEFOOT_COMPARE_KEYWORD)
  178. currentValue = String (p, end); p = end;
  179. return Token::identifier;
  180. }
  181. if (p.isDigit())
  182. {
  183. if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
  184. return Token::literal;
  185. location.throwError ("Syntax error in numeric constant");
  186. }
  187. if (parseStringLiteral (*p) || (*p == '.' && parseFloatLiteral()))
  188. return Token::literal;
  189. #define LITTLEFOOT_COMPARE_OPERATOR(name, str) if (matchToken (Token::name, sizeof (str) - 1)) return Token::name;
  190. LITTLEFOOT_OPERATORS (LITTLEFOOT_COMPARE_OPERATOR)
  191. if (! p.isEmpty())
  192. location.throwError ("Unexpected character '" + String::charToString (*p) + "' in source");
  193. return Token::eof;
  194. }
  195. bool matchToken (TokenType name, const size_t len) noexcept
  196. {
  197. if (p.compareUpTo (CharPointer_ASCII (name), (int) len) != 0) return false;
  198. p += (int) len; return true;
  199. }
  200. void skipWhitespaceAndComments()
  201. {
  202. for (;;)
  203. {
  204. p = p.findEndOfWhitespace();
  205. if (*p == '/')
  206. {
  207. auto c2 = p[1];
  208. if (c2 == '/') { p = CharacterFunctions::find (p, (juce_wchar) '\n'); continue; }
  209. if (c2 == '*')
  210. {
  211. location.location = p;
  212. p = CharacterFunctions::find (p + 2, CharPointer_ASCII ("*/"));
  213. if (p.isEmpty()) location.throwError ("Unterminated '/*' comment");
  214. p += 2; continue;
  215. }
  216. }
  217. break;
  218. }
  219. }
  220. bool parseStringLiteral (juce_wchar quoteType)
  221. {
  222. if (quoteType != '"' && quoteType != '\'')
  223. return false;
  224. auto r = JSON::parseQuotedString (p, currentValue);
  225. if (r.failed()) location.throwError (r.getErrorMessage());
  226. return true;
  227. }
  228. bool parseHexLiteral()
  229. {
  230. if (*p != '0' || (p[1] != 'x' && p[1] != 'X')) return false;
  231. auto t = ++p;
  232. auto v = CharacterFunctions::getHexDigitValue (*++t);
  233. if (v < 0) return false;
  234. for (;;)
  235. {
  236. auto digit = CharacterFunctions::getHexDigitValue (*++t);
  237. if (digit < 0) break;
  238. v = v * 16 + digit;
  239. }
  240. currentValue = v; p = t;
  241. return true;
  242. }
  243. bool parseFloatLiteral()
  244. {
  245. int numDigits = 0;
  246. auto t = p;
  247. while (t.isDigit()) { ++t; ++numDigits; }
  248. const bool hasPoint = (*t == '.');
  249. if (hasPoint)
  250. while ((++t).isDigit()) ++numDigits;
  251. if (numDigits == 0)
  252. return false;
  253. auto c = *t;
  254. const bool hasExponent = (c == 'e' || c == 'E');
  255. if (hasExponent)
  256. {
  257. c = *++t;
  258. if (c == '+' || c == '-') ++t;
  259. if (! t.isDigit()) return false;
  260. while ((++t).isDigit()) {}
  261. }
  262. if (! (hasExponent || hasPoint)) return false;
  263. currentValue = CharacterFunctions::getDoubleValue (p); p = t;
  264. return true;
  265. }
  266. bool parseOctalLiteral()
  267. {
  268. auto t = p;
  269. int64 v = *t - '0';
  270. if (v != 0) return false; // first digit of octal must be 0
  271. for (;;)
  272. {
  273. auto digit = (int) (*++t - '0');
  274. if (isPositiveAndBelow (digit, 8)) v = v * 8 + digit;
  275. else if (isPositiveAndBelow (digit, 10)) location.throwError ("Decimal digit in octal constant");
  276. else break;
  277. }
  278. currentValue = v; p = t;
  279. return true;
  280. }
  281. bool parseDecimalLiteral()
  282. {
  283. int64 v = 0;
  284. for (;; ++p)
  285. {
  286. auto digit = (int) (*p - '0');
  287. if (isPositiveAndBelow (digit, 10)) v = v * 10 + digit;
  288. else break;
  289. }
  290. currentValue = v;
  291. return true;
  292. }
  293. };
  294. //==============================================================================
  295. //==============================================================================
  296. struct SyntaxTreeBuilder : private TokenIterator
  297. {
  298. SyntaxTreeBuilder (const String& code, const Array<NativeFunction>& nativeFns, uint32 defaultHeapSize, const Array<File>& searchPathsToUse)
  299. : TokenIterator (code), searchPaths (searchPathsToUse), nativeFunctions (nativeFns), heapSizeRequired (defaultHeapSize) {}
  300. void compile()
  301. {
  302. blockBeingParsed = allocate<BlockStatement> (location, nullptr, nullptr, false);
  303. parseCode();
  304. heapSizeRequired += arrayHeapSize;
  305. }
  306. void parseCode()
  307. {
  308. const auto programHash = location.program.hashCode64();
  309. if (includedSourceCode.contains (programHash))
  310. return;
  311. includedSourceCode.add (programHash);
  312. while (currentType != Token::eof)
  313. {
  314. if (matchIf (Token::hash))
  315. {
  316. parseCompilerDirective();
  317. continue;
  318. }
  319. const bool isConstVariable = matchIf (Token::const_);
  320. if (! matchesAnyTypeOrVoid())
  321. throwErrorExpecting ("a global variable or function");
  322. auto type = tokenToType (skip());
  323. auto name = parseIdentifier();
  324. if (matchIf (Token::openParen))
  325. {
  326. if (isConstVariable)
  327. location.throwError ("Return type of a function cannot be const");
  328. parseFunctionDeclaration (type, name);
  329. continue;
  330. }
  331. if (type == Type::void_)
  332. location.throwError ("A variable type cannot be 'void'");
  333. parseGlobalVariableDeclaraion (isConstVariable, type, name);
  334. }
  335. }
  336. void simplify()
  337. {
  338. for (auto f : functions)
  339. f->block->simplify (*this);
  340. }
  341. const Function* findFunction (FunctionID functionID) const noexcept
  342. {
  343. for (auto f : functions)
  344. if (f->functionID == functionID)
  345. return f;
  346. return nullptr;
  347. }
  348. const NativeFunction* findNativeFunction (FunctionID functionID) const noexcept
  349. {
  350. for (auto& f : nativeFunctions)
  351. if (f.functionID == functionID)
  352. return &f;
  353. return nullptr;
  354. }
  355. //==============================================================================
  356. BlockPtr blockBeingParsed = nullptr;
  357. Array<Function*> functions;
  358. Array<File> searchPaths;
  359. Array<int64> includedSourceCode;
  360. const Array<NativeFunction>& nativeFunctions;
  361. uint32 heapSizeRequired;
  362. uint32 arrayHeapSize = 0;
  363. template <typename Type, typename... Args>
  364. Type* allocate (Args... args) { auto o = new Type (args...); allAllocatedObjects.add (o); return o; }
  365. private:
  366. OwnedArray<AllocatedObject> allAllocatedObjects;
  367. //==============================================================================
  368. void parseCompilerDirective()
  369. {
  370. auto name = parseIdentifier();
  371. if (name == "heapsize")
  372. {
  373. match (Token::colon);
  374. heapSizeRequired = (((uint32) parseIntegerLiteral()) + 3) & ~3u;
  375. }
  376. else if (name == "include")
  377. {
  378. parseIncludeDirective();
  379. }
  380. else
  381. {
  382. location.throwError ("Unknown compiler directive");
  383. }
  384. }
  385. void parseIncludeDirective()
  386. {
  387. match (Token::literal);
  388. if (! currentValue.isString())
  389. {
  390. location.throwError ("Expected file path");
  391. return;
  392. }
  393. juce::File fileToInclude = resolveIncludePath (currentValue.toString());
  394. if (fileToInclude == File())
  395. return;
  396. searchPaths.add (fileToInclude);
  397. auto codeToInclude = fileToInclude.loadFileAsString();
  398. auto locationToRestore = location;
  399. auto currentTypeToRestore = currentType;
  400. auto currentValueToRestore = currentValue;
  401. auto pToRestore = p;
  402. location = CodeLocation (codeToInclude, fileToInclude);
  403. p = codeToInclude.getCharPointer();
  404. skip();
  405. parseCode();
  406. location = locationToRestore;
  407. currentType = currentTypeToRestore;
  408. currentValue = currentValueToRestore;
  409. p = pToRestore;
  410. }
  411. File resolveIncludePath (String include)
  412. {
  413. if (include.substring (include.length() - 11) != ".littlefoot")
  414. {
  415. location.throwError ("File extension must be .littlefoot");
  416. return {};
  417. }
  418. if (File::isAbsolutePath (include) && File (include).existsAsFile())
  419. return { include };
  420. auto fileName = include.fromLastOccurrenceOf ("/", false, false);
  421. for (auto path : searchPaths)
  422. {
  423. if (path == File())
  424. continue;
  425. if (! path.isDirectory())
  426. path = path.getParentDirectory();
  427. if (path.getChildFile (include).existsAsFile())
  428. return path.getChildFile (include);
  429. if (path.getChildFile (fileName).existsAsFile())
  430. return path.getChildFile (fileName);
  431. }
  432. location.throwError ("File not found: " + include);
  433. }
  434. //TODO: should there be a max array size?
  435. void parseGlobalVariableDeclaraion (bool isConst, Type type, String name)
  436. {
  437. for (;;)
  438. {
  439. if (matchIf (Token::openBracket))
  440. {
  441. int arraySize = 0;
  442. parseGlobalArray (arraySize, type, name, nullptr);
  443. arrayHeapSize += uint32 (arraySize * 4);
  444. }
  445. else
  446. {
  447. parseGlobalVariable (isConst, type, name);
  448. }
  449. if (matchIf (Token::comma))
  450. {
  451. name = parseIdentifier();
  452. continue;
  453. }
  454. match (Token::semicolon);
  455. break;
  456. }
  457. }
  458. void parseGlobalArray (int& arraySize, Type type, const String& name, Variable* parent)
  459. {
  460. const auto value = parseIntegerLiteral();
  461. match (Token::closeBracket);
  462. blockBeingParsed->addVariable ({ {}, type, true, false, {}, value, parent }, location);
  463. auto& newArray = blockBeingParsed->arrays.getReference (blockBeingParsed->arrays.size() - 1);
  464. if (parent != nullptr)
  465. parent->nextArray = &newArray;
  466. if (matchIf (Token::openBracket))
  467. {
  468. parseGlobalArray (arraySize, type, name, &newArray);
  469. arraySize *= value;
  470. }
  471. else
  472. {
  473. newArray.name = name;
  474. arraySize = value;
  475. }
  476. }
  477. void parseGlobalVariable (bool isConst, Type type, String name)
  478. {
  479. var constantInitialiser;
  480. if (isConst)
  481. constantInitialiser = parseConstantExpressionInitialiser (type);
  482. blockBeingParsed->addVariable ({ name, type, true, isConst, constantInitialiser, 0 }, location);
  483. }
  484. var parseConstantExpressionInitialiser (Type expectedType)
  485. {
  486. var result;
  487. match (Token::assign);
  488. auto e = parseExpression();
  489. if (auto literal = dynamic_cast<LiteralValue*> (e->simplify (*this)))
  490. {
  491. result = literal->value;
  492. if (getTypeOfVar (result) != expectedType)
  493. location.throwError ("Expected a constant expression of type " + getTypeName (expectedType));
  494. }
  495. else
  496. {
  497. location.throwError ("Expected a constant expression");
  498. }
  499. return result;
  500. }
  501. void parseFunctionDeclaration (Type returnType, const String& name)
  502. {
  503. auto f = allocate<Function>();
  504. while (matchesAnyType())
  505. {
  506. auto type = tokenToType (skip());
  507. f->arguments.add ({ parseIdentifier(), type, false, false, 0 });
  508. if (f->arguments.size() > 127)
  509. location.throwError ("Too many function arguments");
  510. if (currentType == Token::closeParen)
  511. break;
  512. match (Token::comma);
  513. }
  514. match (Token::closeParen);
  515. f->functionID = createFunctionID (name, returnType, f->getArgumentTypes());
  516. if (findFunction (f->functionID) != nullptr || findNativeFunction (f->functionID) != nullptr)
  517. location.throwError ("Duplicate function declaration");
  518. functions.add (f);
  519. f->block = parseBlock (true);
  520. f->returnType = returnType;
  521. if (! f->block->alwaysReturns())
  522. {
  523. if (returnType != Type::void_)
  524. location.throwError ("This function must return a value");
  525. f->block->statements.add (allocate<ReturnStatement> (location, f->block, nullptr));
  526. }
  527. }
  528. int parseIntegerLiteral()
  529. {
  530. auto e = parseExpression();
  531. if (auto literal = dynamic_cast<LiteralValue*> (e->simplify (*this)))
  532. {
  533. if (literal->value.isInt() || literal->value.isInt64())
  534. {
  535. auto value = static_cast<int> (literal->value);
  536. if (value > 0)
  537. return value;
  538. }
  539. }
  540. location.throwError ("Expected an integer constant");
  541. return 0;
  542. }
  543. BlockPtr parseBlock (bool isMainBlockOfFunction)
  544. {
  545. match (Token::openBrace);
  546. auto b = allocate<BlockStatement> (location, blockBeingParsed, functions.getLast(), isMainBlockOfFunction);
  547. auto lastBlock = blockBeingParsed;
  548. blockBeingParsed = b;
  549. while (! matchIf (Token::closeBrace))
  550. b->statements.add (parseStatement());
  551. blockBeingParsed = lastBlock;
  552. return b;
  553. }
  554. StatementPtr parseStatement()
  555. {
  556. if (currentType == Token::openBrace) return parseBlock (false);
  557. if (matchIf (Token::if_)) return parseIf();
  558. if (matchIf (Token::while_)) return parseDoOrWhileLoop (false);
  559. if (matchIf (Token::do_)) return parseDoOrWhileLoop (true);
  560. if (matchIf (Token::for_)) return parseForLoop();
  561. if (matchIf (Token::return_)) return parseReturn();
  562. if (matchIf (Token::break_)) return matchEndOfStatement (allocate<BreakStatement> (location, blockBeingParsed));
  563. if (matchIf (Token::continue_)) return matchEndOfStatement (allocate<ContinueStatement> (location, blockBeingParsed));
  564. if (matchIf (Token::semicolon)) return matchEndOfStatement (allocate<Statement> (location, blockBeingParsed));
  565. if (matchIf (Token::plusplus)) return matchEndOfStatement (parsePreIncDec (Token::plus));
  566. if (matchIf (Token::minusminus)) return matchEndOfStatement (parsePreIncDec (Token::minus));
  567. if (matchesAny (Token::openParen)) return matchEndOfStatement (parseFactor());
  568. if (matchIf (Token::const_)) return parseVariableDeclaration (true);
  569. if (matchesAnyType()) return parseVariableDeclaration (false);
  570. if (matchesAny (Token::identifier, Token::literal, Token::minus))
  571. return matchEndOfStatement (parseExpression());
  572. throwErrorExpecting ("a statement");
  573. return nullptr;
  574. }
  575. ExpPtr parseExpression()
  576. {
  577. auto lhs = parseLogicOperator();
  578. if (matchIf (Token::question)) return parseTernaryOperator (lhs);
  579. if (matchIf (Token::plusEquals)) return parseInPlaceOpExpression (lhs, Token::plus);
  580. if (matchIf (Token::minusEquals)) return parseInPlaceOpExpression (lhs, Token::minus);
  581. if (matchIf (Token::timesEquals)) return parseInPlaceOpExpression (lhs, Token::times);
  582. if (matchIf (Token::divideEquals)) return parseInPlaceOpExpression (lhs, Token::divide);
  583. if (matchIf (Token::moduloEquals)) return parseInPlaceOpExpression (lhs, Token::modulo);
  584. if (matchIf (Token::leftShiftEquals)) return parseInPlaceOpExpression (lhs, Token::leftShift);
  585. if (matchIf (Token::rightShiftEquals)) return parseInPlaceOpExpression (lhs, Token::rightShift);
  586. if (matchIf (Token::assign))
  587. {
  588. auto loc = location;
  589. return allocate<Assignment> (loc, blockBeingParsed, lhs, parseExpression(), false);
  590. }
  591. return lhs;
  592. }
  593. ExpPtr parseTernaryOperator (ExpPtr condition)
  594. {
  595. auto e = allocate<TernaryOp> (location, blockBeingParsed);
  596. e->condition = condition;
  597. e->trueBranch = parseExpression();
  598. match (Token::colon);
  599. e->falseBranch = parseExpression();
  600. return e;
  601. }
  602. ExpPtr parseLogicOperator()
  603. {
  604. for (auto a = parseComparator();;)
  605. {
  606. if (! matchesAny (Token::logicalAnd, Token::logicalOr, Token::bitwiseOr,
  607. Token::bitwiseAnd, Token::bitwiseXor))
  608. return a;
  609. auto loc = location;
  610. auto type = skip();
  611. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseComparator(), type);
  612. }
  613. }
  614. ExpPtr parseComparator()
  615. {
  616. for (auto a = parseShiftOperator();;)
  617. {
  618. if (! matchesAny (Token::equals, Token::notEquals, Token::lessThan,
  619. Token::lessThanOrEqual, Token::greaterThan, Token::greaterThanOrEqual))
  620. return a;
  621. auto loc = location;
  622. auto type = skip();
  623. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseShiftOperator(), type);
  624. }
  625. }
  626. ExpPtr parseShiftOperator()
  627. {
  628. for (auto a = parseAdditionSubtraction();;)
  629. {
  630. if (! matchesAny (Token::leftShift, Token::rightShift, Token::rightShiftUnsigned))
  631. return a;
  632. auto loc = location;
  633. auto type = skip();
  634. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseExpression(), type);
  635. }
  636. }
  637. ExpPtr parseAdditionSubtraction()
  638. {
  639. for (auto a = parseMultiplyDivide();;)
  640. {
  641. if (! matchesAny (Token::plus, Token::minus))
  642. return a;
  643. auto loc = location;
  644. auto type = skip();
  645. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseMultiplyDivide(), type);
  646. }
  647. }
  648. ExpPtr parseMultiplyDivide()
  649. {
  650. for (auto a = parseUnary();;)
  651. {
  652. if (! matchesAny (Token::times, Token::divide, Token::modulo))
  653. return a;
  654. auto loc = location;
  655. auto type = skip();
  656. a = allocate<BinaryOperator> (loc, blockBeingParsed, a, parseUnary(), type);
  657. }
  658. }
  659. ExpPtr parseUnary()
  660. {
  661. if (matchIf (Token::plusplus)) return parsePreIncDec (Token::plus);
  662. if (matchIf (Token::minusminus)) return parsePreIncDec (Token::minus);
  663. if (matchesAny (Token::minus, Token::logicalNot, Token::bitwiseNot))
  664. {
  665. auto loc = location;
  666. auto type = skip();
  667. return allocate<UnaryOp> (loc, blockBeingParsed, parseUnary(), type);
  668. }
  669. return parseFactor();
  670. }
  671. ExpPtr parseFactor()
  672. {
  673. if (currentType == Token::identifier) return parseSuffixes (allocate<Identifier> (location, blockBeingParsed, parseIdentifier()));
  674. if (matchIf (Token::openParen)) return parseSuffixes (matchCloseParen (parseExpression()));
  675. if (matchIf (Token::true_)) return parseSuffixes (allocate<LiteralValue> (location, blockBeingParsed, true));
  676. if (matchIf (Token::false_)) return parseSuffixes (allocate<LiteralValue> (location, blockBeingParsed, false));
  677. if (currentType == Token::literal)
  678. {
  679. auto lit = allocate<LiteralValue> (location, blockBeingParsed, currentValue);
  680. skip();
  681. return parseSuffixes (lit);
  682. }
  683. if (matchesAny (Token::int_, Token::float_, Token::bool_))
  684. return parseSuffixes (parseFunctionCall (skip()));
  685. throwErrorExpecting ("an expression");
  686. return nullptr;
  687. }
  688. ExpPtr parseSuffixes (ExpPtr input)
  689. {
  690. if (currentType == Token::openParen)
  691. {
  692. if (auto functionName = dynamic_cast<Identifier*> (input))
  693. return parseSuffixes (parseFunctionCall (functionName->name));
  694. location.throwError ("Malformed function call");
  695. return {};
  696. }
  697. if (matchIf (Token::openBracket)) return parseArraySubscript (input);
  698. if (matchIf (Token::plusplus)) return parsePostIncDec (input, Token::plus);
  699. if (matchIf (Token::minusminus)) return parsePostIncDec (input, Token::minus);
  700. return input;
  701. }
  702. ExpPtr parseArraySubscript (ExpPtr input)
  703. {
  704. auto s = allocate<ArraySubscript> (location, blockBeingParsed);
  705. s->object = input;
  706. s->index = parseExpression();
  707. match (Token::closeBracket);
  708. if (matchIf (Token::openBracket))
  709. return parseArraySubscript (s);
  710. return s;
  711. }
  712. ExpPtr parseInPlaceOpExpression (ExpPtr lhs, TokenType opType)
  713. {
  714. auto loc = location;
  715. auto rhs = parseExpression();
  716. return allocate<Assignment> (loc, blockBeingParsed, lhs,
  717. allocate<BinaryOperator> (location, blockBeingParsed, lhs, rhs, opType), false);
  718. }
  719. ExpPtr parsePreIncDec (TokenType opType)
  720. {
  721. auto lhs = parseFactor();
  722. auto one = allocate<LiteralValue> (location, blockBeingParsed, (int) 1);
  723. return allocate<Assignment> (location, blockBeingParsed, lhs,
  724. allocate<BinaryOperator> (location, blockBeingParsed, lhs, one, opType), false);
  725. }
  726. ExpPtr parsePostIncDec (ExpPtr lhs, TokenType opType)
  727. {
  728. auto one = allocate<LiteralValue> (location, blockBeingParsed, (int) 1);
  729. return allocate<Assignment> (location, blockBeingParsed, lhs,
  730. allocate<BinaryOperator> (location, blockBeingParsed, lhs, one, opType), true);
  731. }
  732. StatementPtr parseIf()
  733. {
  734. auto s = allocate<IfStatement> (location, blockBeingParsed);
  735. match (Token::openParen);
  736. s->condition = matchCloseParen (parseExpression());
  737. s->trueBranch = parseStatement();
  738. s->falseBranch = matchIf (Token::else_) ? parseStatement() : nullptr;
  739. return s;
  740. }
  741. StatementPtr parseReturn()
  742. {
  743. auto value = matchIf (Token::semicolon) ? nullptr : parseExpression();
  744. auto returnStatement = allocate<ReturnStatement> (location, blockBeingParsed, value);
  745. matchIf (Token::semicolon);
  746. return returnStatement;
  747. }
  748. StatementPtr parseVariableDeclaration (bool isConst)
  749. {
  750. if (isConst && ! matchesAnyType())
  751. throwErrorExpecting ("a type");
  752. auto type = tokenToType (skip());
  753. for (StatementPtr result = nullptr;;)
  754. {
  755. auto identifier = allocate<Identifier> (location, blockBeingParsed, parseIdentifier());
  756. auto loc = location;
  757. if (isConst)
  758. {
  759. auto constantValue = parseConstantExpressionInitialiser (type);
  760. blockBeingParsed->addVariable ({ identifier->getIdentifier(), type, false, true, constantValue }, loc);
  761. }
  762. else
  763. {
  764. blockBeingParsed->addVariable ({ identifier->getIdentifier(), type, false, false, {} }, loc);
  765. auto assignedValue = matchIf (Token::assign) ? parseExpression() : nullptr;
  766. if (auto literal = dynamic_cast<LiteralValue*> (assignedValue))
  767. if (static_cast<double> (literal->value) == 0)
  768. assignedValue = nullptr;
  769. if (assignedValue != nullptr || ! blockBeingParsed->isMainBlockOfFunction) // no need to assign 0 for variables in the outer scope
  770. {
  771. if (assignedValue == nullptr)
  772. assignedValue = allocate<LiteralValue> (loc, blockBeingParsed, (int) 0);
  773. auto assignment = allocate<Assignment> (loc, blockBeingParsed, identifier, assignedValue, false);
  774. if (result == nullptr)
  775. {
  776. result = assignment;
  777. }
  778. else
  779. {
  780. auto block = dynamic_cast<BlockPtr> (result);
  781. if (block == nullptr)
  782. {
  783. block = allocate<BlockStatement> (loc, blockBeingParsed, functions.getLast(), false);
  784. block->statements.add (result);
  785. result = block;
  786. }
  787. block->statements.add (assignment);
  788. }
  789. }
  790. }
  791. if (matchIf (Token::semicolon))
  792. return result != nullptr ? result : allocate<Statement> (location, blockBeingParsed);
  793. match (Token::comma);
  794. }
  795. }
  796. StatementPtr parseForLoop()
  797. {
  798. auto oldBlock = blockBeingParsed;
  799. auto block = allocate<BlockStatement> (location, oldBlock, functions.getLast(), false);
  800. blockBeingParsed = block;
  801. auto loopStatement = allocate<LoopStatement> (location, blockBeingParsed, false);
  802. block->statements.add (loopStatement);
  803. match (Token::openParen);
  804. loopStatement->initialiser = parseStatement();
  805. loopStatement->condition = matchIf (Token::semicolon) ? allocate<LiteralValue> (location, blockBeingParsed, true)
  806. : matchEndOfStatement (parseExpression());
  807. loopStatement->iterator = matchIf (Token::closeParen) ? allocate<Statement> (location, blockBeingParsed)
  808. : matchCloseParen (parseExpression());
  809. loopStatement->body = parseStatement();
  810. blockBeingParsed = oldBlock;
  811. return block;
  812. }
  813. StatementPtr parseDoOrWhileLoop (bool isDoLoop)
  814. {
  815. auto loopStatement = allocate<LoopStatement> (location, blockBeingParsed, isDoLoop);
  816. loopStatement->initialiser = allocate<Statement> (location, blockBeingParsed);
  817. loopStatement->iterator = allocate<Statement> (location, blockBeingParsed);
  818. if (isDoLoop)
  819. {
  820. loopStatement->body = parseBlock (false);
  821. match (Token::while_);
  822. }
  823. match (Token::openParen);
  824. loopStatement->condition = matchCloseParen (parseExpression());
  825. if (! isDoLoop)
  826. loopStatement->body = parseStatement();
  827. return loopStatement;
  828. }
  829. String parseIdentifier()
  830. {
  831. auto name = currentValue.toString();
  832. match (Token::identifier);
  833. return name;
  834. }
  835. ExpPtr parseFunctionCall (const String& name)
  836. {
  837. auto call = allocate<FunctionCall> (location, blockBeingParsed);
  838. call->functionName = name;
  839. match (Token::openParen);
  840. while (currentType != Token::closeParen)
  841. {
  842. call->arguments.add (parseExpression());
  843. if (currentType == Token::closeParen)
  844. break;
  845. match (Token::comma);
  846. }
  847. return matchCloseParen (call);
  848. }
  849. bool matchesAnyType() const noexcept { return matchesAny (Token::int_, Token::float_, Token::bool_); }
  850. bool matchesAnyTypeOrVoid() const noexcept { return matchesAnyType() || currentType == Token::void_; }
  851. ExpPtr matchCloseParen (ExpPtr e) { match (Token::closeParen); return e; }
  852. template<typename ExpType> ExpType matchEndOfStatement (ExpType e) { match (Token::semicolon); return e; }
  853. };
  854. //==============================================================================
  855. //==============================================================================
  856. struct CodeGenerator
  857. {
  858. CodeGenerator (Array<uint8>& output, SyntaxTreeBuilder& stb)
  859. : outputCode (output), syntaxTree (stb) {}
  860. void generateCode (BlockPtr outerBlock, uint32 heapSizeBytesRequired)
  861. {
  862. for (auto f : syntaxTree.functions)
  863. {
  864. f->address = createMarker();
  865. f->unwindAddress = createMarker();
  866. }
  867. emit ((int16) 0); // checksum
  868. emit ((int16) 0); // size
  869. emit ((int16) syntaxTree.functions.size());
  870. emit ((int16) outerBlock->variables.size());
  871. emit ((int16) heapSizeBytesRequired);
  872. for (auto f : syntaxTree.functions)
  873. emit (f->functionID, f->address);
  874. auto codeStart = outputCode.size();
  875. for (auto f : syntaxTree.functions)
  876. f->emit (*this);
  877. removeJumpsToNextInstruction (codeStart);
  878. resolveMarkers();
  879. Program::writeInt16 (outputCode.begin() + 2, (int16) outputCode.size());
  880. const Program program (outputCode.begin(), (uint32) outputCode.size());
  881. Program::writeInt16 (outputCode.begin(), (int16) program.calculateChecksum());
  882. jassert (program.checksumMatches());
  883. }
  884. //==============================================================================
  885. Array<uint8>& outputCode;
  886. SyntaxTreeBuilder& syntaxTree;
  887. struct Marker { int index = 0; };
  888. struct MarkerAndAddress { Marker marker; int address; };
  889. int nextMarker = 0;
  890. Array<MarkerAndAddress> markersToResolve, resolvedMarkers;
  891. Marker createMarker() noexcept { Marker m; m.index = ++nextMarker; return m; }
  892. void attachMarker (Marker m) { resolvedMarkers.add ({ m, outputCode.size() }); }
  893. int getResolvedMarkerAddress (Marker marker) const
  894. {
  895. for (auto m : resolvedMarkers)
  896. if (m.marker.index == marker.index)
  897. return m.address;
  898. jassertfalse;
  899. return 0;
  900. }
  901. Marker getMarkerAtAddress (int address) const noexcept
  902. {
  903. for (auto m : markersToResolve)
  904. if (m.address == address)
  905. return m.marker;
  906. jassertfalse;
  907. return {};
  908. }
  909. void resolveMarkers()
  910. {
  911. for (auto m : markersToResolve)
  912. Program::writeInt16 (outputCode.begin() + m.address, (int16) getResolvedMarkerAddress (m.marker));
  913. }
  914. void removeCode (int address, int size)
  915. {
  916. outputCode.removeRange (address, size);
  917. for (int i = markersToResolve.size(); --i >= 0;)
  918. {
  919. auto& m = markersToResolve.getReference (i);
  920. if (m.address >= address + size)
  921. m.address -= size;
  922. else if (m.address >= address)
  923. markersToResolve.remove (i);
  924. }
  925. for (auto& m : resolvedMarkers)
  926. if (m.address >= address + size)
  927. m.address -= size;
  928. }
  929. void removeJumpsToNextInstruction (int address)
  930. {
  931. while (address < outputCode.size())
  932. {
  933. auto op = (OpCode) outputCode.getUnchecked (address);
  934. auto opSize = 1 + Program::getNumExtraBytesForOpcode (op);
  935. if (op == OpCode::jump)
  936. {
  937. auto marker = getMarkerAtAddress (address + 1);
  938. if (marker.index != 0)
  939. {
  940. if (getResolvedMarkerAddress (marker) == address + opSize)
  941. {
  942. removeCode (address, opSize);
  943. continue;
  944. }
  945. }
  946. }
  947. address += opSize;
  948. }
  949. }
  950. Marker breakTarget, continueTarget;
  951. //==============================================================================
  952. void emit (OpCode op) { emit ((int8) op); }
  953. void emit (Marker m) { markersToResolve.add ({ m, outputCode.size() }); emit ((int16) 0); }
  954. void emit (int8 value) { outputCode.add ((uint8) value); }
  955. void emit (int16 value) { uint8 d[2]; Program::writeInt16 (d, value); outputCode.insertArray (-1, d, (int) sizeof (d)); }
  956. void emit (int32 value) { uint8 d[4]; Program::writeInt32 (d, value); outputCode.insertArray (-1, d, (int) sizeof (d)); }
  957. template <typename Arg1, typename... Args>
  958. void emit (Arg1 arg1, Args... args)
  959. {
  960. emit (arg1);
  961. emit (args...);
  962. }
  963. void emitPush (const var& value)
  964. {
  965. if (value.isDouble())
  966. {
  967. const float v = value;
  968. if (v == 0) emit (OpCode::push0);
  969. else emit (OpCode::push32, Program::floatToInt (v));
  970. }
  971. else
  972. {
  973. const int v = value;
  974. if (v == 0) emit (OpCode::push0);
  975. else if (v == 1) emit (OpCode::push1);
  976. else if (v > 0 && v < 128) emit (OpCode::push8, (int8) v);
  977. else if (v > 0 && v < 32768) emit (OpCode::push16, (int16) v);
  978. else emit (OpCode::push32, (int32) v);
  979. }
  980. }
  981. void emitCast (Type source, Type dest, const CodeLocation& location)
  982. {
  983. if (dest == source) return;
  984. if (dest == Type::void_) return emit (OpCode::drop);
  985. if (source == Type::bool_ && dest == Type::int_) return;
  986. if (source == Type::int_ && dest == Type::bool_) return emit (OpCode::testNZ_int32);
  987. if ((source == Type::int_ || source == Type::bool_) && dest == Type::float_) return emit (OpCode::int32ToFloat);
  988. location.throwError ("Cannot cast from " + getTypeName (source) + " to " + getTypeName (dest));
  989. }
  990. void emitVariableRead (Type sourceType, Type requiredType, int stackDepth, int index, const CodeLocation& location)
  991. {
  992. if (index < 0)
  993. {
  994. emit (OpCode::dupFromGlobal, (int16) ((-index) - 1));
  995. }
  996. else
  997. {
  998. index += stackDepth;
  999. if (index == 0)
  1000. emit (OpCode::dup);
  1001. else if (index < 8)
  1002. emit ((OpCode) ((int) OpCode::dupOffset_01 + index - 1));
  1003. else if (index >= 128)
  1004. emit (OpCode::dupOffset16, (int16) index);
  1005. else
  1006. emit (OpCode::dupOffset, (int8) index);
  1007. }
  1008. emitCast (sourceType, requiredType, location);
  1009. }
  1010. void emitArrayElementIndex (const Expression* target, BlockPtr parentBlock,
  1011. int stackDepth, const CodeLocation& errorLocation)
  1012. {
  1013. if (auto currentSubscript = dynamic_cast<const ArraySubscript*> (target))
  1014. {
  1015. const auto identifier = currentSubscript->getIdentifier();
  1016. auto array = parentBlock->getArray (identifier, errorLocation);
  1017. ExpPtr elementIndent = nullptr;
  1018. auto currentArray = &array;
  1019. while (currentSubscript != nullptr && currentArray != nullptr)
  1020. {
  1021. auto lhs = syntaxTree.allocate<LiteralValue> (errorLocation, parentBlock, parentBlock->getArrayElementSizeInBytes (*currentArray));
  1022. ExpPtr subscriptIndent = syntaxTree.allocate<BinaryOperator> (errorLocation, parentBlock, lhs, currentSubscript->index, Token::times);
  1023. if (elementIndent == nullptr)
  1024. elementIndent = subscriptIndent;
  1025. else
  1026. elementIndent = syntaxTree.allocate<BinaryOperator> (errorLocation, parentBlock, elementIndent, subscriptIndent, Token::plus);
  1027. currentSubscript = dynamic_cast<ArraySubscript*> (currentSubscript->object);
  1028. currentArray = currentArray->previousArray;
  1029. }
  1030. auto arrayStart = (int) (syntaxTree.heapSizeRequired - syntaxTree.arrayHeapSize) + parentBlock->getArrayStart (identifier, errorLocation);
  1031. auto lhs = syntaxTree.allocate<LiteralValue> (errorLocation, parentBlock, arrayStart);
  1032. elementIndent = syntaxTree.allocate<BinaryOperator> (errorLocation, parentBlock, lhs, elementIndent, Token::plus);
  1033. elementIndent = elementIndent->simplify (syntaxTree);
  1034. elementIndent->emit (*this, Type::int_, stackDepth);
  1035. }
  1036. else
  1037. {
  1038. errorLocation.throwError ("Cannot cast Expression to ArraySubscript");
  1039. }
  1040. }
  1041. };
  1042. //==============================================================================
  1043. //==============================================================================
  1044. struct Statement : public AllocatedObject
  1045. {
  1046. struct Visitor
  1047. {
  1048. virtual ~Visitor() {}
  1049. virtual void operator()(StatementPtr) = 0;
  1050. };
  1051. Statement (const CodeLocation& l, BlockPtr parent) noexcept : location (l), parentBlock (parent) {}
  1052. virtual void emit (CodeGenerator&, Type, int /*stackDepth*/) const {}
  1053. virtual bool alwaysReturns() const { return false; }
  1054. virtual void visitSubStatements (Visitor&) const {}
  1055. virtual Statement* simplify (SyntaxTreeBuilder&) { return this; }
  1056. CodeLocation location;
  1057. BlockPtr parentBlock;
  1058. };
  1059. struct Expression : public Statement
  1060. {
  1061. Expression (const CodeLocation& l, BlockPtr parent) noexcept : Statement (l, parent) {}
  1062. virtual Type getType (CodeGenerator&) const = 0;
  1063. virtual ExpPtr simplify (SyntaxTreeBuilder&) override { return this; }
  1064. virtual String getIdentifier() const { location.throwError ("This operator requires an assignable variable"); return {}; }
  1065. };
  1066. struct Variable
  1067. {
  1068. // VS2015 requires a constructor to avoid aggregate initialization
  1069. Variable (const String& n, Type t, bool isGlobalVar, bool isConstVar, const var& cv,
  1070. int nElements = 0, Variable* pArray = nullptr, Variable* nArray = nullptr)
  1071. : name (n), type (t), isGlobal (isGlobalVar), isConst (isConstVar), constantValue (cv),
  1072. numElements (nElements), previousArray (pArray), nextArray (nArray)
  1073. {
  1074. }
  1075. String name;
  1076. Type type;
  1077. bool isGlobal, isConst;
  1078. var constantValue;
  1079. int numElements = 0;
  1080. Variable* previousArray = nullptr;
  1081. Variable* nextArray = nullptr;
  1082. };
  1083. //==============================================================================
  1084. struct Function : public AllocatedObject
  1085. {
  1086. FunctionID functionID;
  1087. Type returnType;
  1088. Array<Variable> arguments;
  1089. BlockPtr block;
  1090. CodeGenerator::Marker address, unwindAddress;
  1091. void emit (CodeGenerator& cg) const
  1092. {
  1093. cg.attachMarker (address);
  1094. const int numLocals = getNumLocals();
  1095. for (int num = numLocals; num > 0;)
  1096. {
  1097. if (num == 1)
  1098. {
  1099. cg.emit (OpCode::push0);
  1100. --num;
  1101. }
  1102. else
  1103. {
  1104. int numToDo = jmin (127, num);
  1105. cg.emit (OpCode::pushMultiple0, (int8) numToDo);
  1106. num -= numToDo;
  1107. }
  1108. }
  1109. block->emit (cg, Type::void_, 0);
  1110. cg.attachMarker (unwindAddress);
  1111. const bool keepTop = returnType != Type::void_;
  1112. for (int num = numLocals; num > 0;)
  1113. {
  1114. if (num == 1 && ! keepTop)
  1115. {
  1116. cg.emit (OpCode::drop);
  1117. --num;
  1118. }
  1119. else
  1120. {
  1121. int numToDo = jmin (127, num);
  1122. cg.emit (OpCode::dropMultiple, (int8) (keepTop ? -numToDo : numToDo));
  1123. num -= numToDo;
  1124. }
  1125. }
  1126. cg.emit (keepTop ? OpCode::retValue : OpCode::retVoid, (int8) arguments.size());
  1127. }
  1128. Array<Type> getArgumentTypes() const
  1129. {
  1130. Array<Type> argTypes;
  1131. for (auto& arg : arguments)
  1132. argTypes.add (arg.type);
  1133. return argTypes;
  1134. }
  1135. int getNumLocals() const noexcept
  1136. {
  1137. return countMaxNumLocalVariables (block);
  1138. }
  1139. static int countMaxNumLocalVariables (StatementPtr s) noexcept
  1140. {
  1141. struct Counter : Statement::Visitor
  1142. {
  1143. void operator() (StatementPtr sub) override
  1144. {
  1145. num = jmax (num, countMaxNumLocalVariables (sub));
  1146. }
  1147. int num = 0;
  1148. };
  1149. Counter counter;
  1150. if (s != nullptr)
  1151. s->visitSubStatements (counter);
  1152. if (auto block = dynamic_cast<BlockPtr> (s))
  1153. counter.num += block->variables.size();
  1154. return counter.num;
  1155. }
  1156. };
  1157. //==============================================================================
  1158. struct BlockStatement : public Statement
  1159. {
  1160. BlockStatement (const CodeLocation& l, BlockPtr parent, Function* f, bool isMainFunctionBlock)
  1161. : Statement (l, parent), function (f), isMainBlockOfFunction (isMainFunctionBlock) {}
  1162. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1163. {
  1164. jassert (requiredType == Type::void_); ignoreUnused (requiredType);
  1165. jassert (function != nullptr);
  1166. for (auto s : statements)
  1167. s->emit (cg, Type::void_, stackDepth);
  1168. }
  1169. bool alwaysReturns() const override
  1170. {
  1171. return ! statements.isEmpty() && statements.getLast()->alwaysReturns();
  1172. }
  1173. void visitSubStatements (Statement::Visitor& visit) const override
  1174. {
  1175. for (auto s : statements)
  1176. visit (s);
  1177. }
  1178. Statement* simplify (SyntaxTreeBuilder& stb) override
  1179. {
  1180. for (int i = 0; i < statements.size(); ++i)
  1181. statements.set (i, statements.getReference(i)->simplify (stb));
  1182. return this;
  1183. }
  1184. // returns -ve values for globals
  1185. int getVariableDepth (const String& name, const CodeLocation& locationForError) const
  1186. {
  1187. auto index = indexOf (variables, name);
  1188. if (index >= 0)
  1189. return getNumVariablesInParentBlocks() + index;
  1190. if (! isMainBlockOfFunction)
  1191. return parentBlock->getVariableDepth (name, locationForError);
  1192. if (function != nullptr)
  1193. for (int i = function->arguments.size(); --i >= 0;)
  1194. if (function->arguments.getReference(i).name == name)
  1195. return i + 1 + function->getNumLocals();
  1196. index = indexOf (getGlobalVariables(), name);
  1197. if (index >= 0)
  1198. return -(index + 1);
  1199. locationForError.throwError ("Unknown variable '" + name + "'");
  1200. }
  1201. Variable getArray (const String& name, const CodeLocation& locationForError) const
  1202. {
  1203. for (const auto& array : getGlobalArrays())
  1204. if (array.name == name)
  1205. return array;
  1206. locationForError.throwError ("Unknown array '" + name + "'");
  1207. }
  1208. int getArraySizeInBytes (const Variable& array) const
  1209. {
  1210. return array.numElements * getArrayElementSizeInBytes (array);
  1211. }
  1212. int getArrayElementSizeInBytes (const Variable& array) const
  1213. {
  1214. if (array.nextArray != nullptr)
  1215. return getArraySizeInBytes (*array.nextArray);
  1216. return numBytesInType;
  1217. }
  1218. int getArrayStart (const String& name, const CodeLocation& locationForError) const
  1219. {
  1220. int start = 0;
  1221. for (const auto& array : getGlobalArrays())
  1222. {
  1223. if (array.name == name)
  1224. return start;
  1225. if (array.name.isNotEmpty())
  1226. start += getArraySizeInBytes (array);
  1227. }
  1228. locationForError.throwError ("Unknown array '" + name + "'");
  1229. }
  1230. int getNumVariablesInParentBlocks() const noexcept
  1231. {
  1232. return isMainBlockOfFunction ? 0 : (parentBlock->getNumVariablesInParentBlocks()
  1233. + parentBlock->variables.size());
  1234. }
  1235. const Array<Variable>& getGlobalVariables() const noexcept { return parentBlock != nullptr ? parentBlock->getGlobalVariables() : variables; }
  1236. const Array<Variable>& getGlobalConstants() const noexcept { return parentBlock != nullptr ? parentBlock->getGlobalConstants() : constants; }
  1237. const Array<Variable>& getGlobalArrays() const noexcept { return parentBlock != nullptr ? parentBlock->getGlobalArrays() : arrays; }
  1238. const Variable& getVariable (const String& name, const CodeLocation& locationForError) const
  1239. {
  1240. for (auto& v : constants)
  1241. if (v.name == name)
  1242. return v;
  1243. for (auto& v : variables)
  1244. if (v.name == name)
  1245. return v;
  1246. if (! isMainBlockOfFunction && parentBlock != nullptr)
  1247. return parentBlock->getVariable (name, locationForError);
  1248. if (function != nullptr)
  1249. for (auto& v : function->arguments)
  1250. if (v.name == name)
  1251. return v;
  1252. for (auto& v : getGlobalConstants())
  1253. if (v.name == name)
  1254. return v;
  1255. for (auto& v : getGlobalVariables())
  1256. if (v.name == name)
  1257. return v;
  1258. for (auto& v : getGlobalArrays())
  1259. if (v.name == name)
  1260. return v;
  1261. locationForError.throwError ("Unknown variable '" + name + "'");
  1262. }
  1263. void addVariable (Variable v, const CodeLocation& locationForError)
  1264. {
  1265. if (v.name.isNotEmpty() && (indexOf (variables, v.name) >= 0 || indexOf (constants, v.name) >= 0 || indexOf (arrays, v.name) >= 0))
  1266. locationForError.throwError ("Variable '" + v.name + "' already exists");
  1267. (v.numElements == 0 ? (v.isConst ? constants : variables) : arrays).add (v);
  1268. }
  1269. static int indexOf (const Array<Variable>& vars, const String& name) noexcept
  1270. {
  1271. for (int i = 0; i < vars.size(); ++i)
  1272. if (vars.getReference(i).name == name)
  1273. return i;
  1274. return -1;
  1275. }
  1276. Function* function;
  1277. Array<StatementPtr> statements;
  1278. Array<Variable> variables, constants, arrays;
  1279. bool isMainBlockOfFunction;
  1280. };
  1281. struct IfStatement : public Statement
  1282. {
  1283. IfStatement (const CodeLocation& l, BlockPtr parent) : Statement (l, parent) {}
  1284. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1285. {
  1286. jassert (requiredType == Type::void_); ignoreUnused (requiredType);
  1287. condition->emit (cg, Type::bool_, stackDepth);
  1288. auto endOfStatement = cg.createMarker();
  1289. if (falseBranch == nullptr)
  1290. {
  1291. cg.emit (OpCode::jumpIfFalse, endOfStatement);
  1292. trueBranch->emit (cg, Type::void_, stackDepth);
  1293. }
  1294. else
  1295. {
  1296. auto elseTarget = cg.createMarker();
  1297. cg.emit (OpCode::jumpIfFalse, elseTarget);
  1298. trueBranch->emit (cg, Type::void_, stackDepth);
  1299. cg.emit (OpCode::jump, endOfStatement);
  1300. cg.attachMarker (elseTarget);
  1301. falseBranch->emit (cg, Type::void_, stackDepth);
  1302. }
  1303. cg.attachMarker (endOfStatement);
  1304. }
  1305. bool alwaysReturns() const override
  1306. {
  1307. return trueBranch->alwaysReturns() && falseBranch != nullptr && falseBranch->alwaysReturns();
  1308. }
  1309. void visitSubStatements (Statement::Visitor& visit) const override
  1310. {
  1311. visit (condition); visit (trueBranch); visit (falseBranch);
  1312. }
  1313. Statement* simplify (SyntaxTreeBuilder& stb) override
  1314. {
  1315. condition = condition->simplify (stb);
  1316. trueBranch = trueBranch->simplify (stb);
  1317. falseBranch = falseBranch != nullptr ? falseBranch->simplify (stb) : nullptr;
  1318. if (auto literal = dynamic_cast<LiteralValue*> (condition))
  1319. return literal->value ? trueBranch : (falseBranch != nullptr ? falseBranch : stb.allocate<Statement> (location, parentBlock));
  1320. return this;
  1321. }
  1322. ExpPtr condition;
  1323. StatementPtr trueBranch, falseBranch;
  1324. };
  1325. struct TernaryOp : public Expression
  1326. {
  1327. TernaryOp (const CodeLocation& l, BlockPtr parent) : Expression (l, parent) {}
  1328. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1329. {
  1330. condition->emit (cg, Type::bool_, stackDepth);
  1331. auto endOfStatement = cg.createMarker();
  1332. auto elseTarget = cg.createMarker();
  1333. cg.emit (OpCode::jumpIfFalse, elseTarget);
  1334. trueBranch->emit (cg, requiredType, stackDepth);
  1335. cg.emit (OpCode::jump, endOfStatement);
  1336. cg.attachMarker (elseTarget);
  1337. falseBranch->emit (cg, requiredType, stackDepth);
  1338. cg.attachMarker (endOfStatement);
  1339. }
  1340. Type getType (CodeGenerator& cg) const override
  1341. {
  1342. auto type = trueBranch->getType (cg);
  1343. if (type == Type::void_) location.throwError ("The ternary operator cannot take void arguments");
  1344. if (type != falseBranch->getType (cg)) location.throwError ("Expected both branches of this ternary operator to have the same type");
  1345. return type;
  1346. }
  1347. void visitSubStatements (Statement::Visitor& visit) const override
  1348. {
  1349. visit (condition); visit (trueBranch); visit (falseBranch);
  1350. }
  1351. ExpPtr simplify (SyntaxTreeBuilder& stb) override
  1352. {
  1353. condition = condition->simplify (stb);
  1354. trueBranch = trueBranch->simplify (stb);
  1355. falseBranch = falseBranch->simplify (stb);
  1356. if (auto literal = dynamic_cast<LiteralValue*> (condition))
  1357. return literal->value ? trueBranch : falseBranch;
  1358. return this;
  1359. }
  1360. ExpPtr condition, trueBranch, falseBranch;
  1361. };
  1362. struct LoopStatement : public Statement
  1363. {
  1364. LoopStatement (const CodeLocation& l, BlockPtr parent, bool isDo) noexcept : Statement (l, parent), isDoLoop (isDo) {}
  1365. void emit (CodeGenerator& cg, Type, int stackDepth) const override
  1366. {
  1367. initialiser->emit (cg, Type::void_, stackDepth);
  1368. auto loopStart = cg.createMarker();
  1369. cg.attachMarker (loopStart);
  1370. auto oldBreakTarget = cg.breakTarget;
  1371. auto oldContinueTarget = cg.continueTarget;
  1372. cg.breakTarget = cg.createMarker();
  1373. cg.continueTarget = cg.createMarker();
  1374. if (isDoLoop)
  1375. {
  1376. body->emit (cg, Type::void_, stackDepth);
  1377. cg.attachMarker (cg.continueTarget);
  1378. condition->emit (cg, Type::bool_, stackDepth);
  1379. cg.emit (OpCode::jumpIfTrue, loopStart);
  1380. }
  1381. else
  1382. {
  1383. condition->emit (cg, Type::bool_, stackDepth);
  1384. cg.emit (OpCode::jumpIfFalse, cg.breakTarget);
  1385. body->emit (cg, Type::void_, stackDepth);
  1386. cg.attachMarker (cg.continueTarget);
  1387. iterator->emit (cg, Type::void_, stackDepth);
  1388. cg.emit (OpCode::jump, loopStart);
  1389. }
  1390. cg.attachMarker (cg.breakTarget);
  1391. cg.breakTarget = oldBreakTarget;
  1392. cg.continueTarget = oldContinueTarget;
  1393. }
  1394. StatementPtr simplify (SyntaxTreeBuilder& stb) override
  1395. {
  1396. initialiser = initialiser->simplify (stb);
  1397. iterator = iterator->simplify (stb);
  1398. body = body->simplify (stb);
  1399. condition = condition->simplify (stb);
  1400. return this;
  1401. }
  1402. void visitSubStatements (Statement::Visitor& visit) const override
  1403. {
  1404. visit (condition); visit (initialiser); visit (iterator); visit (body);
  1405. }
  1406. StatementPtr initialiser, iterator, body;
  1407. ExpPtr condition;
  1408. bool isDoLoop;
  1409. };
  1410. struct ReturnStatement : public Statement
  1411. {
  1412. ReturnStatement (const CodeLocation& l, BlockPtr parent, ExpPtr v) noexcept : Statement (l, parent), returnValue (v) {}
  1413. void emit (CodeGenerator& cg, Type, int stackDepth) const override
  1414. {
  1415. if (auto fn = parentBlock->function)
  1416. {
  1417. if (returnValue != nullptr)
  1418. returnValue->emit (cg, fn->returnType, stackDepth);
  1419. else if (fn->returnType != Type::void_)
  1420. location.throwError ("Cannot return a value from a void function");
  1421. cg.emit (OpCode::jump, fn->unwindAddress);
  1422. return;
  1423. }
  1424. location.throwError ("The return statement can only be used inside a function");
  1425. }
  1426. bool alwaysReturns() const override { return true; }
  1427. StatementPtr simplify (SyntaxTreeBuilder& stb) override
  1428. {
  1429. if (returnValue != nullptr)
  1430. returnValue = returnValue->simplify (stb);
  1431. return this;
  1432. }
  1433. void visitSubStatements (Statement::Visitor& visit) const override
  1434. {
  1435. visit (returnValue);
  1436. }
  1437. ExpPtr returnValue;
  1438. };
  1439. struct BreakStatement : public Statement
  1440. {
  1441. BreakStatement (const CodeLocation& l, BlockPtr parent) : Statement (l, parent) {}
  1442. void emit (CodeGenerator& cg, Type, int) const override
  1443. {
  1444. if (cg.breakTarget.index == 0)
  1445. location.throwError ("The break statement can only be used inside a loop");
  1446. cg.emit (OpCode::jump, cg.breakTarget);
  1447. }
  1448. };
  1449. struct ContinueStatement : public Statement
  1450. {
  1451. ContinueStatement (const CodeLocation& l, BlockPtr parent) : Statement (l, parent) {}
  1452. void emit (CodeGenerator& cg, Type, int) const override
  1453. {
  1454. if (cg.continueTarget.index == 0)
  1455. location.throwError ("The continue statement can only be used inside a loop");
  1456. cg.emit (OpCode::jump, cg.continueTarget);
  1457. }
  1458. };
  1459. struct LiteralValue : public Expression
  1460. {
  1461. LiteralValue (const CodeLocation& l, BlockPtr parent, const var& v) noexcept : Expression (l, parent), value (v) {}
  1462. void emit (CodeGenerator& cg, Type requiredType, int) const override
  1463. {
  1464. if (requiredType != Type::void_)
  1465. {
  1466. auto type = getType (cg);
  1467. if (type != requiredType && value != var ((int) 0))
  1468. {
  1469. if (type == Type::int_ && requiredType == Type::bool_) return cg.emitPush (static_cast<bool> (value));
  1470. if (type == Type::int_ && requiredType == Type::float_) return cg.emitPush (static_cast<float> (value));
  1471. if (! (type == Type::bool_ && requiredType == Type::int_))
  1472. location.throwError ("Cannot cast from " + getTypeName (type) + " to " + getTypeName (requiredType));
  1473. }
  1474. cg.emitPush (value);
  1475. }
  1476. }
  1477. Type getType (CodeGenerator&) const override
  1478. {
  1479. auto t = getTypeOfVar (value);
  1480. if (t == Type::void_)
  1481. location.throwError ("Unsupported literal type");
  1482. return t;
  1483. }
  1484. var value;
  1485. };
  1486. struct Identifier : public Expression
  1487. {
  1488. Identifier (const CodeLocation& l, BlockPtr parent, const String& n) noexcept : Expression (l, parent), name (n) {}
  1489. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1490. {
  1491. cg.emitVariableRead (getType (cg), requiredType, stackDepth,
  1492. parentBlock->getVariableDepth (name, location), location);
  1493. }
  1494. Type getType (CodeGenerator&) const override
  1495. {
  1496. return parentBlock->getVariable (name, location).type;
  1497. }
  1498. ExpPtr simplify (SyntaxTreeBuilder& stb) override
  1499. {
  1500. auto& v = parentBlock->getVariable (name, location);
  1501. if (v.isConst)
  1502. return stb.allocate<LiteralValue> (location, parentBlock, v.constantValue);
  1503. return this;
  1504. }
  1505. String getIdentifier() const override
  1506. {
  1507. return name;
  1508. }
  1509. String name;
  1510. };
  1511. struct UnaryOp : public Expression
  1512. {
  1513. UnaryOp (const CodeLocation& l, BlockPtr parent, ExpPtr a, TokenType op) noexcept
  1514. : Expression (l, parent), source (a), operation (op) {}
  1515. ExpPtr source;
  1516. TokenType operation;
  1517. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1518. {
  1519. auto sourceType = source->getType (cg);
  1520. if (operation == Token::minus)
  1521. {
  1522. cg.emitPush ((int) 0);
  1523. source->emit (cg, sourceType, stackDepth + 1);
  1524. cg.emit (sourceType == Type::float_ ? OpCode::sub_float : OpCode::sub_int32);
  1525. cg.emitCast (sourceType, requiredType, location);
  1526. }
  1527. else
  1528. {
  1529. if (sourceType == Type::float_)
  1530. location.throwError ("Cannot perform this operation on a float");
  1531. if (operation == Token::logicalNot)
  1532. {
  1533. source->emit (cg, sourceType, stackDepth);
  1534. cg.emit (OpCode::logicalNot);
  1535. cg.emitCast (Type::bool_, requiredType, location);
  1536. }
  1537. else if (operation == Token::bitwiseNot)
  1538. {
  1539. source->emit (cg, Type::int_, stackDepth);
  1540. cg.emit (OpCode::bitwiseNot);
  1541. cg.emitCast (Type::int_, requiredType, location);
  1542. }
  1543. }
  1544. }
  1545. Type getType (CodeGenerator& cg) const override
  1546. {
  1547. if (operation == Token::minus) return source->getType (cg);
  1548. if (operation == Token::logicalNot) return Type::bool_;
  1549. return Type::int_;
  1550. }
  1551. void visitSubStatements (Statement::Visitor& visit) const override
  1552. {
  1553. visit (source);
  1554. }
  1555. ExpPtr simplify (SyntaxTreeBuilder& stb) override
  1556. {
  1557. source = source->simplify (stb);
  1558. if (auto literal = dynamic_cast<LiteralValue*> (source))
  1559. {
  1560. auto type = getTypeOfVar (literal->value);
  1561. if (type == Type::int_ && operation == Token::minus) { literal->value = -static_cast<int> (literal->value); return literal; }
  1562. if (type == Type::int_ && operation == Token::bitwiseNot) { literal->value = ~static_cast<int> (literal->value); return literal; }
  1563. if (type == Type::int_ && operation == Token::logicalNot) { literal->value = ! static_cast<int> (literal->value); return literal; }
  1564. if (type == Type::bool_ && operation == Token::logicalNot) { literal->value = ! static_cast<bool> (literal->value); return literal; }
  1565. if (type == Type::float_ && operation == Token::minus) { literal->value = -static_cast<double> (literal->value); return literal; }
  1566. }
  1567. return this;
  1568. }
  1569. };
  1570. struct BinaryOperator : public Expression
  1571. {
  1572. BinaryOperator (const CodeLocation& l, BlockPtr parent, ExpPtr a, ExpPtr b, TokenType op) noexcept
  1573. : Expression (l, parent), lhs (a), rhs (b), operation (op) {}
  1574. ExpPtr lhs, rhs;
  1575. TokenType operation;
  1576. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1577. {
  1578. auto typeA = lhs->getType (cg);
  1579. auto typeB = rhs->getType (cg);
  1580. if (typeA == Type::float_ || typeB == Type::float_)
  1581. {
  1582. lhs->emit (cg, Type::float_, stackDepth);
  1583. rhs->emit (cg, Type::float_, stackDepth + 1);
  1584. if (operation == Token::plus) return emitOpAndCast (cg, requiredType, OpCode::add_float);
  1585. if (operation == Token::minus) return emitOpAndCast (cg, requiredType, OpCode::sub_float);
  1586. if (operation == Token::times) return emitOpAndCast (cg, requiredType, OpCode::mul_float);
  1587. if (operation == Token::divide) return emitOpAndCast (cg, requiredType, OpCode::div_float);
  1588. cg.emit (OpCode::sub_float);
  1589. if (operation == Token::equals) return emitOpAndCast (cg, requiredType, OpCode::testZE_float);
  1590. if (operation == Token::notEquals) return emitOpAndCast (cg, requiredType, OpCode::testNZ_float);
  1591. if (operation == Token::lessThan) return emitOpAndCast (cg, requiredType, OpCode::testLT_float);
  1592. if (operation == Token::lessThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testLE_float);
  1593. if (operation == Token::greaterThan) return emitOpAndCast (cg, requiredType, OpCode::testGT_float);
  1594. if (operation == Token::greaterThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testGE_float);
  1595. location.throwError ("The operator " + getTokenDescription (operation) + " cannot take floating point arguments");
  1596. }
  1597. auto type = (typeA == Type::bool_ || typeB == Type::bool_) ? Type::bool_
  1598. : Type::int_;
  1599. lhs->emit (cg, type, stackDepth);
  1600. rhs->emit (cg, type, stackDepth + 1);
  1601. if (operation == Token::plus) return emitOpAndCast (cg, requiredType, OpCode::add_int32);
  1602. if (operation == Token::minus) return emitOpAndCast (cg, requiredType, OpCode::sub_int32);
  1603. if (operation == Token::times) return emitOpAndCast (cg, requiredType, OpCode::mul_int32);
  1604. if (operation == Token::divide) return emitOpAndCast (cg, requiredType, OpCode::div_int32);
  1605. if (operation == Token::modulo) return emitOpAndCast (cg, requiredType, OpCode::mod_int32);
  1606. if (operation == Token::logicalOr) return emitOpAndCast (cg, requiredType, OpCode::logicalOr);
  1607. if (operation == Token::logicalAnd) return emitOpAndCast (cg, requiredType, OpCode::logicalAnd);
  1608. if (operation == Token::bitwiseOr) return emitOpAndCast (cg, requiredType, OpCode::bitwiseOr);
  1609. if (operation == Token::bitwiseAnd) return emitOpAndCast (cg, requiredType, OpCode::bitwiseAnd);
  1610. if (operation == Token::bitwiseXor) return emitOpAndCast (cg, requiredType, OpCode::bitwiseXor);
  1611. if (operation == Token::leftShift) return emitOpAndCast (cg, requiredType, OpCode::bitShiftLeft);
  1612. if (operation == Token::rightShift) return emitOpAndCast (cg, requiredType, OpCode::bitShiftRight);
  1613. cg.emit (OpCode::sub_int32);
  1614. if (operation == Token::equals) return emitOpAndCast (cg, requiredType, OpCode::testZE_int32);
  1615. if (operation == Token::notEquals) return emitOpAndCast (cg, requiredType, OpCode::testNZ_int32);
  1616. if (operation == Token::lessThan) return emitOpAndCast (cg, requiredType, OpCode::testLT_int32);
  1617. if (operation == Token::lessThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testLE_int32);
  1618. if (operation == Token::greaterThan) return emitOpAndCast (cg, requiredType, OpCode::testGT_int32);
  1619. if (operation == Token::greaterThanOrEqual) return emitOpAndCast (cg, requiredType, OpCode::testGE_int32);
  1620. location.throwError ("Unsupported operator");
  1621. jassertfalse;
  1622. }
  1623. void emitOpAndCast (CodeGenerator& cg, Type requiredType, OpCode op) const
  1624. {
  1625. cg.emit (op);
  1626. cg.emitCast (getType (cg), requiredType, location);
  1627. }
  1628. Type getResultType (Type typeA, Type typeB) const noexcept
  1629. {
  1630. if (operation == Token::logicalOr || operation == Token::logicalAnd
  1631. || operation == Token::equals || operation == Token::notEquals
  1632. || operation == Token::lessThan || operation == Token::lessThanOrEqual
  1633. || operation == Token::greaterThan || operation == Token::greaterThanOrEqual)
  1634. return Type::bool_;
  1635. if (operation == Token::plus || operation == Token::minus
  1636. || operation == Token::times || operation == Token::divide)
  1637. {
  1638. if (typeA == Type::float_ || typeB == Type::float_)
  1639. return Type::float_;
  1640. }
  1641. return Type::int_;
  1642. }
  1643. Type getType (CodeGenerator& cg) const override
  1644. {
  1645. return getResultType (lhs->getType (cg), rhs->getType (cg));
  1646. }
  1647. void visitSubStatements (Statement::Visitor& visit) const override
  1648. {
  1649. visit (lhs); visit (rhs);
  1650. }
  1651. ExpPtr simplifyFloat (double a, double b, LiteralValue* literal)
  1652. {
  1653. if (operation == Token::plus) { literal->value = a + b; return literal; }
  1654. if (operation == Token::minus) { literal->value = a - b; return literal; }
  1655. if (operation == Token::times) { literal->value = a * b; return literal; }
  1656. if (operation == Token::divide) { literal->value = a / b; return literal; }
  1657. if (operation == Token::equals) { literal->value = a == b; return literal; }
  1658. if (operation == Token::notEquals) { literal->value = a != b; return literal; }
  1659. if (operation == Token::lessThan) { literal->value = a < b; return literal; }
  1660. if (operation == Token::lessThanOrEqual) { literal->value = a <= b; return literal; }
  1661. if (operation == Token::greaterThan) { literal->value = a > b; return literal; }
  1662. if (operation == Token::greaterThanOrEqual) { literal->value = a >= b; return literal; }
  1663. return this;
  1664. }
  1665. ExpPtr simplifyBool (bool a, bool b, LiteralValue* literal)
  1666. {
  1667. if (operation == Token::logicalOr) { literal->value = a || b; return literal; }
  1668. if (operation == Token::logicalAnd) { literal->value = a && b; return literal; }
  1669. return this;
  1670. }
  1671. ExpPtr simplifyInt (int a, int b, LiteralValue* literal)
  1672. {
  1673. if (operation == Token::plus) { literal->value = a + b; return literal; }
  1674. if (operation == Token::minus) { literal->value = a - b; return literal; }
  1675. if (operation == Token::times) { literal->value = a * b; return literal; }
  1676. if (operation == Token::divide) { literal->value = a / b; return literal; }
  1677. if (operation == Token::equals) { literal->value = a == b; return literal; }
  1678. if (operation == Token::notEquals) { literal->value = a != b; return literal; }
  1679. if (operation == Token::lessThan) { literal->value = a < b; return literal; }
  1680. if (operation == Token::lessThanOrEqual) { literal->value = a <= b; return literal; }
  1681. if (operation == Token::greaterThan) { literal->value = a > b; return literal; }
  1682. if (operation == Token::greaterThanOrEqual) { literal->value = a >= b; return literal; }
  1683. if (operation == Token::modulo) { literal->value = a % b; return literal; }
  1684. if (operation == Token::logicalOr) { literal->value = a || b; return literal; }
  1685. if (operation == Token::logicalAnd) { literal->value = a && b; return literal; }
  1686. if (operation == Token::bitwiseOr) { literal->value = a | b; return literal; }
  1687. if (operation == Token::bitwiseAnd) { literal->value = a & b; return literal; }
  1688. if (operation == Token::bitwiseXor) { literal->value = a ^ b; return literal; }
  1689. if (operation == Token::leftShift) { literal->value = a << b; return literal; }
  1690. if (operation == Token::rightShift) { literal->value = a >> b; return literal; }
  1691. return this;
  1692. }
  1693. ExpPtr simplify (SyntaxTreeBuilder& stb) override
  1694. {
  1695. lhs = lhs->simplify (stb);
  1696. rhs = rhs->simplify (stb);
  1697. if (auto literal1 = dynamic_cast<LiteralValue*> (lhs))
  1698. {
  1699. if (auto literal2 = dynamic_cast<LiteralValue*> (rhs))
  1700. {
  1701. auto resultType = getResultType (getTypeOfVar (literal1->value),
  1702. getTypeOfVar (literal2->value));
  1703. if (resultType == Type::bool_) return simplifyBool (literal1->value, literal2->value, literal1);
  1704. if (resultType == Type::int_) return simplifyInt (literal1->value, literal2->value, literal1);
  1705. if (resultType == Type::float_) return simplifyFloat (literal1->value, literal2->value, literal1);
  1706. }
  1707. }
  1708. return this;
  1709. }
  1710. };
  1711. struct Assignment : public Expression
  1712. {
  1713. Assignment (const CodeLocation& l, BlockPtr parent, ExpPtr dest, ExpPtr source, bool isPost) noexcept
  1714. : Expression (l, parent), target (dest), newValue (source), isPostAssignment (isPost) {}
  1715. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1716. {
  1717. auto variableType = getType (cg);
  1718. if (isPostAssignment && requiredType != Type::void_)
  1719. {
  1720. target->emit (cg, requiredType, stackDepth);
  1721. ++stackDepth;
  1722. requiredType = Type::void_;
  1723. }
  1724. newValue->emit (cg, variableType, stackDepth);
  1725. if (auto a = dynamic_cast<ArraySubscript*> (target))
  1726. {
  1727. cg.emitArrayElementIndex (a, parentBlock, stackDepth, location);
  1728. cg.emit (OpCode::setHeapInt);
  1729. }
  1730. else
  1731. {
  1732. auto index = parentBlock->getVariableDepth (target->getIdentifier(), location);
  1733. if (requiredType != Type::void_)
  1734. {
  1735. cg.emit (OpCode::dup);
  1736. ++stackDepth;
  1737. }
  1738. if (index < 0)
  1739. {
  1740. cg.emit (OpCode::dropToGlobal, (int16) ((-index) - 1));
  1741. }
  1742. else
  1743. {
  1744. index += stackDepth;
  1745. if (index >= 128)
  1746. cg.emit (OpCode::dropToStack16, (int16) index);
  1747. else
  1748. cg.emit (OpCode::dropToStack, (int8) index);
  1749. }
  1750. if (requiredType != Type::void_)
  1751. cg.emitCast (variableType, requiredType, location);
  1752. }
  1753. }
  1754. Type getType (CodeGenerator&) const override
  1755. {
  1756. return parentBlock->getVariable (target->getIdentifier(), location).type;
  1757. }
  1758. void visitSubStatements (Statement::Visitor& visit) const override
  1759. {
  1760. visit (newValue);
  1761. }
  1762. ExpPtr simplify (SyntaxTreeBuilder& stb) override
  1763. {
  1764. newValue = newValue->simplify (stb);
  1765. return this;
  1766. }
  1767. ExpPtr target, newValue;
  1768. bool isPostAssignment;
  1769. };
  1770. struct FunctionCall : public Expression
  1771. {
  1772. FunctionCall (const CodeLocation& l, BlockPtr parent) noexcept : Expression (l, parent) {}
  1773. void emit (CodeGenerator& cg, Type requiredType, int stackDepth) const override
  1774. {
  1775. if (functionName == Token::int_) return emitCast (cg, Type::int_, stackDepth);
  1776. if (functionName == Token::float_) return emitCast (cg, Type::float_, stackDepth);
  1777. if (functionName == Token::bool_) return emitCast (cg, Type::bool_, stackDepth);
  1778. auto functionID = getFunctionID (cg);
  1779. if (auto fn = cg.syntaxTree.findFunction (functionID))
  1780. {
  1781. emitArgs (cg, fn->getArgumentTypes(), stackDepth);
  1782. cg.emit (OpCode::call, fn->address);
  1783. cg.emitCast (fn->returnType, requiredType, location);
  1784. return;
  1785. }
  1786. if (auto nativeFn = cg.syntaxTree.findNativeFunction (functionID))
  1787. {
  1788. emitArgs (cg, getArgTypesFromFunctionName (nativeFn->nameAndArguments), stackDepth);
  1789. cg.emit (OpCode::callNative, nativeFn->functionID);
  1790. cg.emitCast (nativeFn->returnType, requiredType, location);
  1791. return;
  1792. }
  1793. if (auto b = findBuiltInFunction (functionID))
  1794. {
  1795. emitArgs (cg, getArgTypesFromFunctionName (b->name), stackDepth);
  1796. cg.emit (b->op);
  1797. cg.emitCast (b->returnType, requiredType, location);
  1798. return;
  1799. }
  1800. throwCannotFindFunctionError (cg, requiredType);
  1801. }
  1802. Type getType (CodeGenerator& cg) const override
  1803. {
  1804. if (arguments.size() == 1)
  1805. {
  1806. if (functionName == Token::float_) return Type::float_;
  1807. if (functionName == Token::int_) return Type::int_;
  1808. if (functionName == Token::bool_) return Type::bool_;
  1809. }
  1810. auto functionID = getFunctionID (cg);
  1811. if (auto fn = cg.syntaxTree.findFunction (functionID))
  1812. return fn->returnType;
  1813. if (auto nativeFn = cg.syntaxTree.findNativeFunction (functionID))
  1814. return nativeFn->returnType;
  1815. if (auto b = findBuiltInFunction (functionID))
  1816. return b->returnType;
  1817. throwCannotFindFunctionError (cg, Type::void_);
  1818. return {};
  1819. }
  1820. struct BuiltInFunction { OpCode op; Type returnType; const char* name; };
  1821. const BuiltInFunction* findBuiltInFunction (FunctionID functionID) const noexcept
  1822. {
  1823. static constexpr const BuiltInFunction builtIns[] =
  1824. {
  1825. { OpCode::getHeapByte, Type::int_, "getHeapByte/ii" },
  1826. { OpCode::getHeapInt, Type::int_, "getHeapInt/ii" },
  1827. { OpCode::getHeapBits, Type::int_, "getHeapBits/iii" },
  1828. { OpCode::setHeapByte, Type::void_, "setHeapByte/vii" },
  1829. { OpCode::setHeapInt, Type::void_, "setHeapInt/vii" }
  1830. };
  1831. for (auto& b : builtIns)
  1832. if (functionID == NativeFunction::createID (b.name))
  1833. return &b;
  1834. return nullptr;
  1835. }
  1836. void emitArgs (CodeGenerator& cg, const Array<Type>& argTypes, int stackDepth) const
  1837. {
  1838. for (int i = arguments.size(); --i >= 0;)
  1839. {
  1840. auto argType = argTypes[i];
  1841. auto argValue = arguments.getUnchecked(i);
  1842. if (argValue->getType (cg) != argType)
  1843. location.throwError ("Argument " + String (i + 1) + " requires an expression of type " + getTypeName (argType));
  1844. argValue->emit (cg, argType, stackDepth++);
  1845. }
  1846. }
  1847. void emitCast (CodeGenerator& cg, Type destType, int stackDepth) const
  1848. {
  1849. if (arguments.size() != 1)
  1850. location.throwError (getTypeName (destType) + " cast operation requires a single argument");
  1851. auto* arg = arguments.getReference (0);
  1852. const auto sourceType = arg->getType (cg);
  1853. arg->emit (cg, sourceType, stackDepth);
  1854. const bool sourceIsFloat = (sourceType == Type::float_);
  1855. const bool destIsFloat = (destType == Type::float_);
  1856. if (sourceIsFloat != destIsFloat)
  1857. cg.emit (destIsFloat ? OpCode::int32ToFloat : OpCode::floatToInt32);
  1858. }
  1859. FunctionID getFunctionID (CodeGenerator& cg) const
  1860. {
  1861. Array<Type> argTypes;
  1862. for (auto arg : arguments)
  1863. argTypes.add (arg->getType (cg));
  1864. return createFunctionID (functionName, Type::void_, argTypes); // NB: the ID ignores the return type so void is OK
  1865. }
  1866. void throwCannotFindFunctionError (CodeGenerator& cg, Type returnType) const
  1867. {
  1868. StringArray args;
  1869. for (auto arg : arguments)
  1870. args.add (getTypeName (arg->getType (cg)));
  1871. auto desc = getTypeName (returnType) + " " + functionName
  1872. + "(" + args.joinIntoString (", ") + ")";
  1873. location.throwError ("Cannot find matching function: " + desc.quoted());
  1874. }
  1875. void visitSubStatements (Statement::Visitor& visit) const override
  1876. {
  1877. for (auto& arg : arguments)
  1878. visit (arg);
  1879. }
  1880. ExpPtr simplify (SyntaxTreeBuilder& stb) override
  1881. {
  1882. for (auto& arg : arguments)
  1883. arg = arg->simplify (stb);
  1884. return this;
  1885. }
  1886. String functionName;
  1887. Array<ExpPtr> arguments;
  1888. };
  1889. struct ArraySubscript : public Expression
  1890. {
  1891. ArraySubscript (const CodeLocation& l, BlockPtr parent) noexcept : Expression (l, parent) {}
  1892. void emit (CodeGenerator& cg, Type /*requiredType*/, int stackDepth) const override
  1893. {
  1894. cg.emitArrayElementIndex (this, parentBlock, stackDepth, location);
  1895. cg.emit (OpCode::getHeapInt);
  1896. }
  1897. void visitSubStatements (Statement::Visitor& visit) const override
  1898. {
  1899. visit (object); visit (index);
  1900. }
  1901. ExpPtr simplify (SyntaxTreeBuilder& stb) override
  1902. {
  1903. object = object->simplify (stb);
  1904. index = index->simplify (stb);
  1905. return this;
  1906. }
  1907. Type getType (CodeGenerator& cg) const override
  1908. {
  1909. return object->getType (cg);
  1910. }
  1911. String getIdentifier() const override
  1912. {
  1913. if (auto i = dynamic_cast<Identifier*> (object))
  1914. return i->name;
  1915. if (auto s = dynamic_cast<ArraySubscript*> (object))
  1916. return s->getIdentifier();
  1917. location.throwError ("This operator requires an assignable variable");
  1918. return {};
  1919. }
  1920. ExpPtr object, index;
  1921. };
  1922. //==============================================================================
  1923. static Array<Type> getArgTypesFromFunctionName (const char* nameAndTypes)
  1924. {
  1925. Array<Type> types;
  1926. auto args = String (nameAndTypes).fromFirstOccurrenceOf ("/", false, false).substring (1);
  1927. for (int i = 0; i < args.length(); ++i)
  1928. types.add (static_cast<Type> (args[i]));
  1929. return types;
  1930. }
  1931. static FunctionID createFunctionID (String name, Type returnType, const Array<Type>& types)
  1932. {
  1933. name << "/" << (char) returnType;
  1934. for (auto t : types)
  1935. name << (char) t;
  1936. return NativeFunction::createID (name.toRawUTF8());
  1937. }
  1938. static String getTokenDescription (TokenType t) { return t[0] == '$' ? String (t + 1) : ("'" + String (t) + "'"); }
  1939. static String getTypeName (Type t) noexcept
  1940. {
  1941. if (t == Type::int_) return "int";
  1942. if (t == Type::bool_) return "bool";
  1943. if (t == Type::float_) return "float";
  1944. return "void";
  1945. }
  1946. static Type tokenToType (TokenType t) noexcept
  1947. {
  1948. if (t == Token::int_) return Type::int_;
  1949. if (t == Token::bool_) return Type::bool_;
  1950. if (t == Token::float_) return Type::float_;
  1951. return Type::void_;
  1952. }
  1953. static Type getTypeOfVar (const var& v) noexcept
  1954. {
  1955. if (v.isInt() || v.isInt64()) return Type::int_;
  1956. if (v.isDouble()) return Type::float_;
  1957. if (v.isBool()) return Type::bool_;
  1958. return Type::void_;
  1959. }
  1960. #endif // ! DOXYGEN
  1961. };
  1962. }
  1963. #if JUCE_MSVC
  1964. #pragma warning (pop)
  1965. #endif