diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/MoonP/moon_ast.h | 26 | ||||
| -rw-r--r-- | src/MoonP/moon_compiler.cpp | 192 | ||||
| -rw-r--r-- | src/MoonP/moon_parser.cpp | 74 | ||||
| -rw-r--r-- | src/MoonP/moon_parser.h | 19 | ||||
| -rw-r--r-- | src/moonp.cpp | 6 |
5 files changed, 240 insertions, 77 deletions
diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h index dd01165..9fab215 100644 --- a/src/MoonP/moon_ast.h +++ b/src/MoonP/moon_ast.h | |||
| @@ -500,18 +500,28 @@ AST_NODE(ClassDecl) | |||
| 500 | AST_MEMBER(ClassDecl, &name, &extend, &body) | 500 | AST_MEMBER(ClassDecl, &name, &extend, &body) |
| 501 | AST_END(ClassDecl) | 501 | AST_END(ClassDecl) |
| 502 | 502 | ||
| 503 | AST_NODE(export_values) | 503 | AST_NODE(global_values) |
| 504 | ast_ptr<true, NameList_t> nameList; | 504 | ast_ptr<true, NameList_t> nameList; |
| 505 | ast_ptr<false, ExpListLow_t> valueList; | 505 | ast_ptr<false, ExpListLow_t> valueList; |
| 506 | AST_MEMBER(export_values, &nameList, &valueList) | 506 | AST_MEMBER(global_values, &nameList, &valueList) |
| 507 | AST_END(export_values) | 507 | AST_END(global_values) |
| 508 | 508 | ||
| 509 | AST_LEAF(export_op) | 509 | AST_LEAF(global_op) |
| 510 | AST_END(export_op) | 510 | AST_END(global_op) |
| 511 | |||
| 512 | AST_NODE(Global) | ||
| 513 | ast_sel<true, ClassDecl_t, global_op_t, global_values_t> item; | ||
| 514 | AST_MEMBER(Global, &item) | ||
| 515 | AST_END(Global) | ||
| 516 | |||
| 517 | AST_LEAF(export_default) | ||
| 518 | AST_END(export_default) | ||
| 511 | 519 | ||
| 512 | AST_NODE(Export) | 520 | AST_NODE(Export) |
| 513 | ast_sel<true, ClassDecl_t, export_op_t, export_values_t> item; | 521 | ast_ptr<false, export_default_t> def; |
| 514 | AST_MEMBER(Export, &item) | 522 | ast_sel<true, ExpList_t, Exp_t> target; |
| 523 | ast_ptr<false, Assign_t> assign; | ||
| 524 | AST_MEMBER(Export, &def, &target, &assign) | ||
| 515 | AST_END(Export) | 525 | AST_END(Export) |
| 516 | 526 | ||
| 517 | AST_NODE(FnArgDef) | 527 | AST_NODE(FnArgDef) |
| @@ -601,7 +611,7 @@ AST_END(BreakLoop) | |||
| 601 | 611 | ||
| 602 | AST_NODE(Statement) | 612 | AST_NODE(Statement) |
| 603 | ast_sel<true, Import_t, While_t, For_t, ForEach_t, | 613 | ast_sel<true, Import_t, While_t, For_t, ForEach_t, |
| 604 | Return_t, Local_t, Export_t, BreakLoop_t, | 614 | Return_t, Local_t, Global_t, Export_t, BreakLoop_t, |
| 605 | Backcall_t, ExpListAssign_t> content; | 615 | Backcall_t, ExpListAssign_t> content; |
| 606 | ast_ptr<false, statement_appendix_t> appendix; | 616 | ast_ptr<false, statement_appendix_t> appendix; |
| 607 | AST_MEMBER(Statement, &content, &appendix) | 617 | AST_MEMBER(Statement, &content, &appendix) |
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp index 83b91e6..1adfec9 100644 --- a/src/MoonP/moon_compiler.cpp +++ b/src/MoonP/moon_compiler.cpp | |||
| @@ -32,7 +32,7 @@ inline std::string s(std::string_view sv) { | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | const char* moonScriptVersion() { | 34 | const char* moonScriptVersion() { |
| 35 | return "0.5.0-r0.1.5"; | 35 | return "0.5.0-r0.2.0"; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | class MoonCompilerImpl { | 38 | class MoonCompilerImpl { |
| @@ -45,7 +45,10 @@ public: | |||
| 45 | try { | 45 | try { |
| 46 | str_list out; | 46 | str_list out; |
| 47 | pushScope(); | 47 | pushScope(); |
| 48 | transformBlock(_info.node.to<File_t>()->block, out, config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common); | 48 | enableReturn.push(_info.moduleName.empty()); |
| 49 | transformBlock(_info.node.to<File_t>()->block, out, | ||
| 50 | config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common, | ||
| 51 | nullptr, true); | ||
| 49 | popScope(); | 52 | popScope(); |
| 50 | if (config.lintGlobalVariable) { | 53 | if (config.lintGlobalVariable) { |
| 51 | globals = std::make_unique<std::list<GlobalVar>>(); | 54 | globals = std::make_unique<std::list<GlobalVar>>(); |
| @@ -86,6 +89,7 @@ private: | |||
| 86 | MoonParser _parser; | 89 | MoonParser _parser; |
| 87 | ParseInfo _info; | 90 | ParseInfo _info; |
| 88 | int _indentOffset = 0; | 91 | int _indentOffset = 0; |
| 92 | std::stack<bool> enableReturn; | ||
| 89 | std::list<std::unique_ptr<input>> _codeCache; | 93 | std::list<std::unique_ptr<input>> _codeCache; |
| 90 | std::stack<std::string> _withVars; | 94 | std::stack<std::string> _withVars; |
| 91 | std::stack<std::string> _continueVars; | 95 | std::stack<std::string> _continueVars; |
| @@ -98,16 +102,16 @@ private: | |||
| 98 | Capital = 1, | 102 | Capital = 1, |
| 99 | Any = 2 | 103 | Any = 2 |
| 100 | }; | 104 | }; |
| 101 | enum class ExportMode { | 105 | enum class GlobalMode { |
| 102 | None = 0, | 106 | None = 0, |
| 103 | Capital = 1, | 107 | Capital = 1, |
| 104 | Any = 2 | 108 | Any = 2 |
| 105 | }; | 109 | }; |
| 106 | struct Scope { | 110 | struct Scope { |
| 107 | ExportMode mode = ExportMode::None; | 111 | GlobalMode mode = GlobalMode::None; |
| 108 | std::unique_ptr<std::unordered_set<std::string>> vars; | 112 | std::unique_ptr<std::unordered_set<std::string>> vars; |
| 109 | std::unique_ptr<std::unordered_set<std::string>> allows; | 113 | std::unique_ptr<std::unordered_set<std::string>> allows; |
| 110 | std::unique_ptr<std::unordered_set<std::string>> exports; | 114 | std::unique_ptr<std::unordered_set<std::string>> globals; |
| 111 | }; | 115 | }; |
| 112 | std::list<Scope> _scopes; | 116 | std::list<Scope> _scopes; |
| 113 | static const std::string Empty; | 117 | static const std::string Empty; |
| @@ -153,11 +157,11 @@ private: | |||
| 153 | 157 | ||
| 154 | bool isDefined(const std::string& name) const { | 158 | bool isDefined(const std::string& name) const { |
| 155 | bool isDefined = false; | 159 | bool isDefined = false; |
| 156 | int mode = int(std::isupper(name[0]) ? ExportMode::Capital : ExportMode::Any); | 160 | int mode = int(std::isupper(name[0]) ? GlobalMode::Capital : GlobalMode::Any); |
| 157 | const auto& current = _scopes.back(); | 161 | const auto& current = _scopes.back(); |
| 158 | if (int(current.mode) >= mode) { | 162 | if (int(current.mode) >= mode) { |
| 159 | if (current.exports) { | 163 | if (current.globals) { |
| 160 | if (current.exports->find(name) != current.exports->end()) { | 164 | if (current.globals->find(name) != current.globals->end()) { |
| 161 | isDefined = true; | 165 | isDefined = true; |
| 162 | current.vars->insert(name); | 166 | current.vars->insert(name); |
| 163 | } | 167 | } |
| @@ -202,17 +206,17 @@ private: | |||
| 202 | scope.allows = std::make_unique<std::unordered_set<std::string>>(); | 206 | scope.allows = std::make_unique<std::unordered_set<std::string>>(); |
| 203 | } | 207 | } |
| 204 | 208 | ||
| 205 | void markVarExported(ExportMode mode, bool specified) { | 209 | void markVarGlobal(GlobalMode mode, bool specified) { |
| 206 | auto& scope = _scopes.back(); | 210 | auto& scope = _scopes.back(); |
| 207 | scope.mode = mode; | 211 | scope.mode = mode; |
| 208 | if (specified && !scope.exports) { | 212 | if (specified && !scope.globals) { |
| 209 | scope.exports = std::make_unique<std::unordered_set<std::string>>(); | 213 | scope.globals = std::make_unique<std::unordered_set<std::string>>(); |
| 210 | } | 214 | } |
| 211 | } | 215 | } |
| 212 | 216 | ||
| 213 | void addExportedVar(const std::string& name) { | 217 | void addGlobalVar(const std::string& name) { |
| 214 | auto& scope = _scopes.back(); | 218 | auto& scope = _scopes.back(); |
| 215 | scope.exports->insert(name); | 219 | scope.globals->insert(name); |
| 216 | } | 220 | } |
| 217 | 221 | ||
| 218 | void addToAllowList(const std::string& name) { | 222 | void addToAllowList(const std::string& name) { |
| @@ -457,6 +461,20 @@ private: | |||
| 457 | return Empty; | 461 | return Empty; |
| 458 | } | 462 | } |
| 459 | 463 | ||
| 464 | Variable_t* variableFrom(Exp_t* exp) { | ||
| 465 | BLOCK_START | ||
| 466 | auto value = singleValueFrom(exp); | ||
| 467 | BREAK_IF(!value); | ||
| 468 | auto chainValue = value->getByPath<ChainValue_t>(); | ||
| 469 | BREAK_IF(!chainValue); | ||
| 470 | BREAK_IF(chainValue->items.size() != 1); | ||
| 471 | auto callable = ast_cast<Callable_t>(chainValue->items.front()); | ||
| 472 | BREAK_IF(!callable); | ||
| 473 | return callable->item.as<Variable_t>(); | ||
| 474 | BLOCK_END | ||
| 475 | return nullptr; | ||
| 476 | } | ||
| 477 | |||
| 460 | bool isAssignable(const node_container& chainItems) const { | 478 | bool isAssignable(const node_container& chainItems) const { |
| 461 | if (chainItems.size() == 1) { | 479 | if (chainItems.size() == 1) { |
| 462 | auto firstItem = chainItems.back(); | 480 | auto firstItem = chainItems.back(); |
| @@ -647,6 +665,7 @@ private: | |||
| 647 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(content), out); break; | 665 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(content), out); break; |
| 648 | case id<Return_t>(): transformReturn(static_cast<Return_t*>(content), out); break; | 666 | case id<Return_t>(): transformReturn(static_cast<Return_t*>(content), out); break; |
| 649 | case id<Local_t>(): transformLocal(static_cast<Local_t*>(content), out); break; | 667 | case id<Local_t>(): transformLocal(static_cast<Local_t*>(content), out); break; |
| 668 | case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break; | ||
| 650 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; | 669 | case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; |
| 651 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; | 670 | case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; |
| 652 | case id<ExpListAssign_t>(): { | 671 | case id<ExpListAssign_t>(): { |
| @@ -693,7 +712,7 @@ private: | |||
| 693 | break; | 712 | break; |
| 694 | } | 713 | } |
| 695 | } | 714 | } |
| 696 | throw std::logic_error(_info.errorMessage("Expression list must appear at the end of body or block."sv, expList)); | 715 | throw std::logic_error(_info.errorMessage("Expression list is not supported here."sv, expList)); |
| 697 | } | 716 | } |
| 698 | break; | 717 | break; |
| 699 | } | 718 | } |
| @@ -749,8 +768,8 @@ private: | |||
| 749 | return preDefs; | 768 | return preDefs; |
| 750 | } | 769 | } |
| 751 | 770 | ||
| 752 | str_list transformAssignDefs(ExpList_t* expList) { | 771 | str_list transformAssignDefs(ExpList_t* expList, bool markDefined = true) { |
| 753 | str_list preDefs; | 772 | str_list defs; |
| 754 | for (auto exp_ : expList->exprs.objects()) { | 773 | for (auto exp_ : expList->exprs.objects()) { |
| 755 | auto exp = static_cast<Exp_t*>(exp_); | 774 | auto exp = static_cast<Exp_t*>(exp_); |
| 756 | if (auto value = singleValueFrom(exp)) { | 775 | if (auto value = singleValueFrom(exp)) { |
| @@ -766,8 +785,8 @@ private: | |||
| 766 | if (self->name.is<self_t>()) name = "self"sv; | 785 | if (self->name.is<self_t>()) name = "self"sv; |
| 767 | } | 786 | } |
| 768 | BREAK_IF(name.empty()); | 787 | BREAK_IF(name.empty()); |
| 769 | if (addToScope(name)) { | 788 | if (!markDefined || addToScope(name)) { |
| 770 | preDefs.push_back(name); | 789 | defs.push_back(name); |
| 771 | } | 790 | } |
| 772 | BLOCK_END | 791 | BLOCK_END |
| 773 | } | 792 | } |
| @@ -775,7 +794,7 @@ private: | |||
| 775 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); | 794 | throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); |
| 776 | } | 795 | } |
| 777 | } | 796 | } |
| 778 | return preDefs; | 797 | return defs; |
| 779 | } | 798 | } |
| 780 | 799 | ||
| 781 | std::string getPredefine(const str_list& defs) { | 800 | std::string getPredefine(const str_list& defs) { |
| @@ -1650,6 +1669,7 @@ private: | |||
| 1650 | } | 1669 | } |
| 1651 | 1670 | ||
| 1652 | void transformFunLit(FunLit_t* funLit, str_list& out) { | 1671 | void transformFunLit(FunLit_t* funLit, str_list& out) { |
| 1672 | enableReturn.push(true); | ||
| 1653 | str_list temp; | 1673 | str_list temp; |
| 1654 | bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; | 1674 | bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; |
| 1655 | pushScope(); | 1675 | pushScope(); |
| @@ -1698,6 +1718,7 @@ private: | |||
| 1698 | } | 1718 | } |
| 1699 | } | 1719 | } |
| 1700 | out.push_back(clearBuf()); | 1720 | out.push_back(clearBuf()); |
| 1721 | enableReturn.pop(); | ||
| 1701 | } | 1722 | } |
| 1702 | 1723 | ||
| 1703 | void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 1724 | void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| @@ -1711,7 +1732,7 @@ private: | |||
| 1711 | } | 1732 | } |
| 1712 | } | 1733 | } |
| 1713 | 1734 | ||
| 1714 | void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 1735 | void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool isRoot = false) { |
| 1715 | const auto& nodes = block->statements.objects(); | 1736 | const auto& nodes = block->statements.objects(); |
| 1716 | LocalMode mode = LocalMode::None; | 1737 | LocalMode mode = LocalMode::None; |
| 1717 | Local_t* any = nullptr, *capital = nullptr; | 1738 | Local_t* any = nullptr, *capital = nullptr; |
| @@ -1768,7 +1789,7 @@ private: | |||
| 1768 | args->swap(a, arg); | 1789 | args->swap(a, arg); |
| 1769 | findPlaceHolder = true; | 1790 | findPlaceHolder = true; |
| 1770 | } else { | 1791 | } else { |
| 1771 | throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place."sv, a)); | 1792 | throw std::logic_error(_info.errorMessage("Backcall placeholder can be used only in one place."sv, a)); |
| 1772 | } | 1793 | } |
| 1773 | } | 1794 | } |
| 1774 | } | 1795 | } |
| @@ -1792,9 +1813,10 @@ private: | |||
| 1792 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | 1813 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); |
| 1793 | expListAssign->expList.set(expList); | 1814 | expListAssign->expList.set(expList); |
| 1794 | newStmt->content.set(expListAssign); | 1815 | newStmt->content.set(expListAssign); |
| 1816 | newStmt->appendix.set(stmt->appendix); | ||
| 1795 | newBlock->statements.push_back(newStmt); | 1817 | newBlock->statements.push_back(newStmt); |
| 1796 | } | 1818 | } |
| 1797 | transformBlock(newBlock, out, usage, assignList); | 1819 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 1798 | return; | 1820 | return; |
| 1799 | } | 1821 | } |
| 1800 | if (auto local = stmt->content.as<Local_t>()) { | 1822 | if (auto local = stmt->content.as<Local_t>()) { |
| @@ -1838,6 +1860,15 @@ private: | |||
| 1838 | } | 1860 | } |
| 1839 | } | 1861 | } |
| 1840 | } | 1862 | } |
| 1863 | if (info.second) { | ||
| 1864 | auto defs = transformAssignDefs(info.second->expList, false); | ||
| 1865 | for (const auto& def : defs) { | ||
| 1866 | if (std::isupper(def[0]) && capital) { capital->decls.push_back(def); | ||
| 1867 | } else if (any) { | ||
| 1868 | any->decls.push_back(def); | ||
| 1869 | } | ||
| 1870 | } | ||
| 1871 | } | ||
| 1841 | BLOCK_START | 1872 | BLOCK_START |
| 1842 | auto assign = assignment->action.as<Assign_t>(); | 1873 | auto assign = assignment->action.as<Assign_t>(); |
| 1843 | BREAK_IF(!assign); | 1874 | BREAK_IF(!assign); |
| @@ -1865,10 +1896,14 @@ private: | |||
| 1865 | } | 1896 | } |
| 1866 | } | 1897 | } |
| 1867 | } | 1898 | } |
| 1899 | if (isRoot && !_info.moduleName.empty()) { | ||
| 1900 | block->statements.push_front(toAst<Statement_t>(_info.moduleName + s(_info.exportDefault ? "=nil"sv : "={}"sv), block)); | ||
| 1901 | } | ||
| 1868 | switch (usage) { | 1902 | switch (usage) { |
| 1869 | case ExpUsage::Closure: | 1903 | case ExpUsage::Closure: |
| 1870 | case ExpUsage::Return: { | 1904 | case ExpUsage::Return: { |
| 1871 | BLOCK_START | 1905 | BLOCK_START |
| 1906 | BREAK_IF(isRoot && !_info.moduleName.empty()); | ||
| 1872 | BREAK_IF(nodes.empty()); | 1907 | BREAK_IF(nodes.empty()); |
| 1873 | auto last = static_cast<Statement_t*>(nodes.back()); | 1908 | auto last = static_cast<Statement_t*>(nodes.back()); |
| 1874 | auto x = last; | 1909 | auto x = last; |
| @@ -1920,9 +1955,17 @@ private: | |||
| 1920 | } else { | 1955 | } else { |
| 1921 | out.push_back(Empty); | 1956 | out.push_back(Empty); |
| 1922 | } | 1957 | } |
| 1958 | if (isRoot && !_info.moduleName.empty()) { | ||
| 1959 | out.back().append(indent() + s("return "sv) + _info.moduleName + nlr(block)); | ||
| 1960 | } | ||
| 1923 | } | 1961 | } |
| 1924 | 1962 | ||
| 1925 | void transformReturn(Return_t* returnNode, str_list& out) { | 1963 | void transformReturn(Return_t* returnNode, str_list& out) { |
| 1964 | if (!enableReturn.top()) { | ||
| 1965 | ast_node* target = returnNode->valueList.get(); | ||
| 1966 | if (!target) target = returnNode; | ||
| 1967 | throw std::logic_error(_info.errorMessage("Illegal return statement here."sv, target)); | ||
| 1968 | } | ||
| 1926 | if (auto valueList = returnNode->valueList.get()) { | 1969 | if (auto valueList = returnNode->valueList.get()) { |
| 1927 | if (valueList->exprs.size() == 1) { | 1970 | if (valueList->exprs.size() == 1) { |
| 1928 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); | 1971 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); |
| @@ -3797,33 +3840,33 @@ private: | |||
| 3797 | out.push_back(_parser.toString(const_value)); | 3840 | out.push_back(_parser.toString(const_value)); |
| 3798 | } | 3841 | } |
| 3799 | 3842 | ||
| 3800 | void transformExport(Export_t* exportNode, str_list& out) { | 3843 | void transformGlobal(Global_t* global, str_list& out) { |
| 3801 | auto x = exportNode; | 3844 | auto x = global; |
| 3802 | auto item = exportNode->item.get(); | 3845 | auto item = global->item.get(); |
| 3803 | switch (item->getId()) { | 3846 | switch (item->getId()) { |
| 3804 | case id<ClassDecl_t>(): { | 3847 | case id<ClassDecl_t>(): { |
| 3805 | auto classDecl = static_cast<ClassDecl_t*>(item); | 3848 | auto classDecl = static_cast<ClassDecl_t*>(item); |
| 3806 | if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { | 3849 | if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { |
| 3807 | markVarExported(ExportMode::Any, true); | 3850 | markVarGlobal(GlobalMode::Any, true); |
| 3808 | addExportedVar(_parser.toString(classDecl->name->item)); | 3851 | addGlobalVar(_parser.toString(classDecl->name->item)); |
| 3809 | } | 3852 | } |
| 3810 | transformClassDecl(classDecl, out, ExpUsage::Common); | 3853 | transformClassDecl(classDecl, out, ExpUsage::Common); |
| 3811 | break; | 3854 | break; |
| 3812 | } | 3855 | } |
| 3813 | case id<export_op_t>(): | 3856 | case id<global_op_t>(): |
| 3814 | if (_parser.toString(item) == "*"sv) { | 3857 | if (_parser.toString(item) == "*"sv) { |
| 3815 | markVarExported(ExportMode::Any, false); | 3858 | markVarGlobal(GlobalMode::Any, false); |
| 3816 | } else { | 3859 | } else { |
| 3817 | markVarExported(ExportMode::Capital, false); | 3860 | markVarGlobal(GlobalMode::Capital, false); |
| 3818 | } | 3861 | } |
| 3819 | break; | 3862 | break; |
| 3820 | case id<export_values_t>(): { | 3863 | case id<global_values_t>(): { |
| 3821 | markVarExported(ExportMode::Any, true); | 3864 | markVarGlobal(GlobalMode::Any, true); |
| 3822 | auto values = exportNode->item.to<export_values_t>(); | 3865 | auto values = global->item.to<global_values_t>(); |
| 3823 | if (values->valueList) { | 3866 | if (values->valueList) { |
| 3824 | auto expList = x->new_ptr<ExpList_t>(); | 3867 | auto expList = x->new_ptr<ExpList_t>(); |
| 3825 | for (auto name : values->nameList->names.objects()) { | 3868 | for (auto name : values->nameList->names.objects()) { |
| 3826 | addExportedVar(_parser.toString(name)); | 3869 | addGlobalVar(_parser.toString(name)); |
| 3827 | auto callable = x->new_ptr<Callable_t>(); | 3870 | auto callable = x->new_ptr<Callable_t>(); |
| 3828 | callable->item.set(name); | 3871 | callable->item.set(name); |
| 3829 | auto chainValue = x->new_ptr<ChainValue_t>(); | 3872 | auto chainValue = x->new_ptr<ChainValue_t>(); |
| @@ -3842,7 +3885,7 @@ private: | |||
| 3842 | transformAssignment(assignment, out); | 3885 | transformAssignment(assignment, out); |
| 3843 | } else { | 3886 | } else { |
| 3844 | for (auto name : values->nameList->names.objects()) { | 3887 | for (auto name : values->nameList->names.objects()) { |
| 3845 | addExportedVar(_parser.toString(name)); | 3888 | addGlobalVar(_parser.toString(name)); |
| 3846 | } | 3889 | } |
| 3847 | } | 3890 | } |
| 3848 | break; | 3891 | break; |
| @@ -3851,6 +3894,85 @@ private: | |||
| 3851 | } | 3894 | } |
| 3852 | } | 3895 | } |
| 3853 | 3896 | ||
| 3897 | void transformExport(Export_t* exportNode, str_list& out) { | ||
| 3898 | auto x = exportNode; | ||
| 3899 | if (_scopes.size() > 1) { | ||
| 3900 | throw std::logic_error(_info.errorMessage("Can not do module export outside root block."sv, x)); | ||
| 3901 | } | ||
| 3902 | if (exportNode->assign) { | ||
| 3903 | auto expList = exportNode->target.to<ExpList_t>(); | ||
| 3904 | if (expList->exprs.size() != exportNode->assign->values.size()) { | ||
| 3905 | throw std::logic_error(_info.errorMessage("Left and right expressions must be matched in export statement."sv, x)); | ||
| 3906 | } | ||
| 3907 | for (auto _exp : expList->exprs.objects()) { | ||
| 3908 | auto exp = static_cast<Exp_t*>(_exp); | ||
| 3909 | if (!variableFrom(exp) && | ||
| 3910 | !exp->getByPath<Value_t, SimpleValue_t, TableLit_t>() && | ||
| 3911 | !exp->getByPath<Value_t, simple_table_t>()) { | ||
| 3912 | throw std::logic_error(_info.errorMessage("Left hand expressions must be variables in export statement."sv, x)); | ||
| 3913 | } | ||
| 3914 | } | ||
| 3915 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 3916 | assignment->expList.set(expList); | ||
| 3917 | assignment->action.set(exportNode->assign); | ||
| 3918 | transformAssignment(assignment, out); | ||
| 3919 | str_list names = transformAssignDefs(expList, false); | ||
| 3920 | auto info = extractDestructureInfo(assignment, true); | ||
| 3921 | if (!info.first.empty()) { | ||
| 3922 | for (const auto& destruct : info.first) | ||
| 3923 | for (const auto& item : destruct.items) | ||
| 3924 | if (item.isVariable) | ||
| 3925 | names.push_back(item.name); | ||
| 3926 | } | ||
| 3927 | if (_info.exportDefault) { | ||
| 3928 | out.back().append(indent() + _info.moduleName + s(" = "sv) + names.back() + nlr(exportNode)); | ||
| 3929 | } else { | ||
| 3930 | str_list lefts, rights; | ||
| 3931 | for (const auto& name : names) { | ||
| 3932 | lefts.push_back(_info.moduleName + s("[\""sv) + name + s("\"]"sv)); | ||
| 3933 | rights.push_back(name); | ||
| 3934 | } | ||
| 3935 | out.back().append(indent() + join(lefts,", "sv) + s(" = "sv) + join(rights, ", "sv) + nlr(exportNode)); | ||
| 3936 | } | ||
| 3937 | } else { | ||
| 3938 | if (_info.exportDefault) { | ||
| 3939 | auto exp = exportNode->target.to<Exp_t>(); | ||
| 3940 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 3941 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName, x)); | ||
| 3942 | auto assign = x->new_ptr<Assign_t>(); | ||
| 3943 | assign->values.push_back(exp); | ||
| 3944 | assignment->action.set(assign); | ||
| 3945 | transformAssignment(assignment, out); | ||
| 3946 | } else { | ||
| 3947 | str_list temp; | ||
| 3948 | auto expList = exportNode->target.to<ExpList_t>(); | ||
| 3949 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 3950 | auto assignList = toAst<ExpList_t>(_info.moduleName + s("[#"sv) + _info.moduleName + s("+1]"sv), x); | ||
| 3951 | assignment->expList.set(assignList); | ||
| 3952 | for (auto exp : expList->exprs.objects()) { | ||
| 3953 | if (auto classDecl = exp->getByPath<Value_t, SimpleValue_t, ClassDecl_t>()) { | ||
| 3954 | if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { | ||
| 3955 | transformClassDecl(classDecl, temp, ExpUsage::Common); | ||
| 3956 | auto name = _parser.toString(classDecl->name->item); | ||
| 3957 | assignment->expList.set(toAst<ExpList_t>(_info.moduleName + s("[\""sv) + name + s("\"]"sv), x)); | ||
| 3958 | auto assign = x->new_ptr<Assign_t>(); | ||
| 3959 | assign->values.push_back(toAst<Exp_t>(name, x)); | ||
| 3960 | assignment->action.set(assign); | ||
| 3961 | transformAssignment(assignment, temp); | ||
| 3962 | assignment->expList.set(assignList); | ||
| 3963 | continue; | ||
| 3964 | } | ||
| 3965 | } | ||
| 3966 | auto assign = x->new_ptr<Assign_t>(); | ||
| 3967 | assign->values.push_back(exp); | ||
| 3968 | assignment->action.set(assign); | ||
| 3969 | transformAssignment(assignment, temp); | ||
| 3970 | } | ||
| 3971 | out.push_back(join(temp)); | ||
| 3972 | } | ||
| 3973 | } | ||
| 3974 | } | ||
| 3975 | |||
| 3854 | void transformTable(ast_node* table, const node_container& pairs, str_list& out) { | 3976 | void transformTable(ast_node* table, const node_container& pairs, str_list& out) { |
| 3855 | if (pairs.empty()) { | 3977 | if (pairs.empty()) { |
| 3856 | out.push_back(s("{ }"sv)); | 3978 | out.push_back(s("{ }"sv)); |
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp index fecf869..baa8eff 100644 --- a/src/MoonP/moon_parser.cpp +++ b/src/MoonP/moon_parser.cpp | |||
| @@ -28,8 +28,8 @@ std::unordered_set<std::string> Keywords = { | |||
| 28 | "repeat", "return", "then", "true", "until", | 28 | "repeat", "return", "then", "true", "until", |
| 29 | "while", // Lua keywords | 29 | "while", // Lua keywords |
| 30 | "as", "class", "continue", "export", "extends", | 30 | "as", "class", "continue", "export", "extends", |
| 31 | "from", "import", "switch", "unless", "using", | 31 | "from", "global", "import", "switch", "unless", |
| 32 | "when", "with" // Moon keywords | 32 | "using", "when", "with" // Moon keywords |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | MoonParser::MoonParser() { | 35 | MoonParser::MoonParser() { |
| @@ -74,9 +74,15 @@ MoonParser::MoonParser() { | |||
| 74 | Variable = pl::user(Name, [](const item_t& item) { | 74 | Variable = pl::user(Name, [](const item_t& item) { |
| 75 | State* st = reinterpret_cast<State*>(item.user_data); | 75 | State* st = reinterpret_cast<State*>(item.user_data); |
| 76 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); | 76 | for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); |
| 77 | auto it = Keywords.find(st->buffer); | 77 | auto isValid = Keywords.find(st->buffer) == Keywords.end(); |
| 78 | if (isValid) { | ||
| 79 | if (st->buffer == st->moduleName) { | ||
| 80 | st->moduleFix++; | ||
| 81 | st->moduleName = std::string("_module_"sv) + std::to_string(st->moduleFix); | ||
| 82 | } | ||
| 83 | } | ||
| 78 | st->buffer.clear(); | 84 | st->buffer.clear(); |
| 79 | return it == Keywords.end(); | 85 | return isValid; |
| 80 | }); | 86 | }); |
| 81 | 87 | ||
| 82 | LuaKeyword = pl::user(Name, [](const item_t& item) { | 88 | LuaKeyword = pl::user(Name, [](const item_t& item) { |
| @@ -153,7 +159,7 @@ MoonParser::MoonParser() { | |||
| 153 | return true; | 159 | return true; |
| 154 | }); | 160 | }); |
| 155 | 161 | ||
| 156 | InBlock = Advance >> Block >> PopIndent; | 162 | InBlock = Advance >> ensure(Block, PopIndent); |
| 157 | 163 | ||
| 158 | local_flag = expr('*') | expr('^'); | 164 | local_flag = expr('*') | expr('^'); |
| 159 | Local = key("local") >> ((Space >> local_flag) | NameList); | 165 | Local = key("local") >> ((Space >> local_flag) | NameList); |
| @@ -211,21 +217,18 @@ MoonParser::MoonParser() { | |||
| 211 | DisableDo >> ensure(for_in, PopDo) >> | 217 | DisableDo >> ensure(for_in, PopDo) >> |
| 212 | -key("do") >> Body; | 218 | -key("do") >> Body; |
| 213 | 219 | ||
| 214 | Do = pl::user(key("do") >> Body, [](const item_t& item) | 220 | Do = pl::user(key("do"), [](const item_t& item) { |
| 215 | { | ||
| 216 | State* st = reinterpret_cast<State*>(item.user_data); | 221 | State* st = reinterpret_cast<State*>(item.user_data); |
| 217 | return st->doStack.empty() || st->doStack.top(); | 222 | return st->doStack.empty() || st->doStack.top(); |
| 218 | }); | 223 | }) >> Body; |
| 219 | 224 | ||
| 220 | DisableDo = pl::user(true_(), [](const item_t& item) | 225 | DisableDo = pl::user(true_(), [](const item_t& item) { |
| 221 | { | ||
| 222 | State* st = reinterpret_cast<State*>(item.user_data); | 226 | State* st = reinterpret_cast<State*>(item.user_data); |
| 223 | st->doStack.push(false); | 227 | st->doStack.push(false); |
| 224 | return true; | 228 | return true; |
| 225 | }); | 229 | }); |
| 226 | 230 | ||
| 227 | PopDo = pl::user(true_(), [](const item_t& item) | 231 | PopDo = pl::user(true_(), [](const item_t& item) { |
| 228 | { | ||
| 229 | State* st = reinterpret_cast<State*>(item.user_data); | 232 | State* st = reinterpret_cast<State*>(item.user_data); |
| 230 | st->doStack.pop(); | 233 | st->doStack.pop(); |
| 231 | return true; | 234 | return true; |
| @@ -312,11 +315,7 @@ MoonParser::MoonParser() { | |||
| 312 | 315 | ||
| 313 | LuaStringContent = *(not_(LuaStringClose) >> Any); | 316 | LuaStringContent = *(not_(LuaStringClose) >> Any); |
| 314 | 317 | ||
| 315 | LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) { | 318 | LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose; |
| 316 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 317 | st->stringOpen = -1; | ||
| 318 | return true; | ||
| 319 | }); | ||
| 320 | 319 | ||
| 321 | Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); | 320 | Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); |
| 322 | Callable = Space >> Variable | SelfName | VarArg | Parens; | 321 | Callable = Space >> Variable | SelfName | VarArg | Parens; |
| @@ -392,9 +391,30 @@ MoonParser::MoonParser() { | |||
| 392 | -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> | 391 | -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> |
| 393 | -ClassBlock; | 392 | -ClassBlock; |
| 394 | 393 | ||
| 395 | export_values = NameList >> -(sym('=') >> ExpListLow); | 394 | global_values = NameList >> -(sym('=') >> ExpListLow); |
| 396 | export_op = expr('*') | expr('^'); | 395 | global_op = expr('*') | expr('^'); |
| 397 | Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); | 396 | Global = key("global") >> (ClassDecl | (Space >> global_op) | global_values); |
| 397 | |||
| 398 | export_default = key("default"); | ||
| 399 | |||
| 400 | Export = pl::user(key("export"), [](const item_t& item) { | ||
| 401 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 402 | st->exportCount++; | ||
| 403 | return true; | ||
| 404 | }) >> ((pl::user(export_default, [](const item_t& item) { | ||
| 405 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 406 | bool isValid = !st->exportDefault && st->exportCount == 1; | ||
| 407 | st->exportDefault = true; | ||
| 408 | return isValid; | ||
| 409 | }) >> Exp) | ||
| 410 | | (pl::user(true_(), [](const item_t& item) { | ||
| 411 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 412 | if (st->exportDefault && st->exportCount > 1) { | ||
| 413 | return false; | ||
| 414 | } else { | ||
| 415 | return true; | ||
| 416 | } | ||
| 417 | }) >> ExpList >> -Assign)) >> not_(Space >> statement_appendix); | ||
| 398 | 418 | ||
| 399 | variable_pair = sym(':') >> Variable; | 419 | variable_pair = sym(':') >> Variable; |
| 400 | 420 | ||
| @@ -479,12 +499,12 @@ MoonParser::MoonParser() { | |||
| 479 | statement_appendix = (if_else_line | unless_line | CompInner) >> Space; | 499 | statement_appendix = (if_else_line | unless_line | CompInner) >> Space; |
| 480 | Statement = ( | 500 | Statement = ( |
| 481 | Import | While | For | ForEach | | 501 | Import | While | For | ForEach | |
| 482 | Return | Local | Export | Space >> BreakLoop | | 502 | Return | Local | Global | Export | Space >> BreakLoop | |
| 483 | Backcall | ExpListAssign | 503 | Backcall | ExpListAssign |
| 484 | ) >> Space >> | 504 | ) >> Space >> |
| 485 | -statement_appendix; | 505 | -statement_appendix; |
| 486 | 506 | ||
| 487 | Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; | 507 | Body = Space >> Break >> *EmptyLine >> InBlock | Statement; |
| 488 | 508 | ||
| 489 | empty_line_stop = Space >> and_(Stop); | 509 | empty_line_stop = Space >> and_(Stop); |
| 490 | Line = CheckIndent >> Statement | empty_line_stop; | 510 | Line = CheckIndent >> Statement | empty_line_stop; |
| @@ -498,7 +518,7 @@ ParseInfo MoonParser::parse(std::string_view codes, rule& r) { | |||
| 498 | ParseInfo res; | 518 | ParseInfo res; |
| 499 | try { | 519 | try { |
| 500 | res.codes = std::make_unique<input>(); | 520 | res.codes = std::make_unique<input>(); |
| 501 | *(res.codes) = _converter.from_bytes(codes.begin(), codes.end()); | 521 | *(res.codes) = _converter.from_bytes(&codes.front(), &codes.back() + 1); |
| 502 | } catch (const std::range_error&) { | 522 | } catch (const std::range_error&) { |
| 503 | res.error = "Invalid text encoding."sv; | 523 | res.error = "Invalid text encoding."sv; |
| 504 | return res; | 524 | return res; |
| @@ -507,6 +527,10 @@ ParseInfo MoonParser::parse(std::string_view codes, rule& r) { | |||
| 507 | try { | 527 | try { |
| 508 | State state; | 528 | State state; |
| 509 | res.node.set(pl::parse(*(res.codes), r, errors, &state)); | 529 | res.node.set(pl::parse(*(res.codes), r, errors, &state)); |
| 530 | if (state.exportCount > 0) { | ||
| 531 | res.moduleName = std::move(state.moduleName); | ||
| 532 | res.exportDefault = state.exportDefault; | ||
| 533 | } | ||
| 510 | } catch (const std::logic_error& err) { | 534 | } catch (const std::logic_error& err) { |
| 511 | res.error = err.what(); | 535 | res.error = err.what(); |
| 512 | return res; | 536 | return res; |
| @@ -538,7 +562,7 @@ std::string MoonParser::toString(input::iterator begin, input::iterator end) { | |||
| 538 | } | 562 | } |
| 539 | 563 | ||
| 540 | input MoonParser::encode(std::string_view codes) { | 564 | input MoonParser::encode(std::string_view codes) { |
| 541 | return _converter.from_bytes(codes.begin(), codes.end()); | 565 | return _converter.from_bytes(&codes.front(), &codes.back() + 1); |
| 542 | } | 566 | } |
| 543 | 567 | ||
| 544 | std::string MoonParser::decode(const input& codes) { | 568 | std::string MoonParser::decode(const input& codes) { |
| @@ -572,7 +596,6 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
| 572 | count++; | 596 | count++; |
| 573 | } | 597 | } |
| 574 | } | 598 | } |
| 575 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); | ||
| 576 | int oldCol = loc->m_begin.m_col; | 599 | int oldCol = loc->m_begin.m_col; |
| 577 | int col = std::max(0, oldCol - 1); | 600 | int col = std::max(0, oldCol - 1); |
| 578 | auto it = begin; | 601 | auto it = begin; |
| @@ -582,6 +605,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc | |||
| 582 | } | 605 | } |
| 583 | ++it; | 606 | ++it; |
| 584 | } | 607 | } |
| 608 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); | ||
| 585 | Utils::replace(line, "\t"sv, " "sv); | 609 | Utils::replace(line, "\t"sv, " "sv); |
| 586 | std::ostringstream buf; | 610 | std::ostringstream buf; |
| 587 | buf << loc->m_begin.m_line << ": "sv << msg << | 611 | buf << loc->m_begin.m_line << ": "sv << msg << |
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h index 12f735b..eefcba5 100644 --- a/src/MoonP/moon_parser.h +++ b/src/MoonP/moon_parser.h | |||
| @@ -26,6 +26,8 @@ struct ParseInfo { | |||
| 26 | ast_ptr<false, ast_node> node; | 26 | ast_ptr<false, ast_node> node; |
| 27 | std::string error; | 27 | std::string error; |
| 28 | std::unique_ptr<input> codes; | 28 | std::unique_ptr<input> codes; |
| 29 | bool exportDefault = false; | ||
| 30 | std::string moduleName; | ||
| 29 | std::string errorMessage(std::string_view msg, const input_range* loc) const; | 31 | std::string errorMessage(std::string_view msg, const input_range* loc) const; |
| 30 | }; | 32 | }; |
| 31 | 33 | ||
| @@ -72,10 +74,13 @@ protected: | |||
| 72 | struct State { | 74 | struct State { |
| 73 | State() { | 75 | State() { |
| 74 | indents.push(0); | 76 | indents.push(0); |
| 75 | stringOpen = -1; | ||
| 76 | } | 77 | } |
| 78 | bool exportDefault = false; | ||
| 79 | int exportCount = 0; | ||
| 80 | int moduleFix = 0; | ||
| 81 | size_t stringOpen = 0; | ||
| 82 | std::string moduleName = "_module_0"; | ||
| 77 | std::string buffer; | 83 | std::string buffer; |
| 78 | size_t stringOpen; | ||
| 79 | std::stack<int> indents; | 84 | std::stack<int> indents; |
| 80 | std::stack<bool> doStack; | 85 | std::stack<bool> doStack; |
| 81 | }; | 86 | }; |
| @@ -124,8 +129,8 @@ private: | |||
| 124 | rule ImportNameList; | 129 | rule ImportNameList; |
| 125 | rule import_literal_chain; | 130 | rule import_literal_chain; |
| 126 | rule WithExp; | 131 | rule WithExp; |
| 127 | rule PopDo; | ||
| 128 | rule DisableDo; | 132 | rule DisableDo; |
| 133 | rule PopDo; | ||
| 129 | rule SwitchElse; | 134 | rule SwitchElse; |
| 130 | rule SwitchBlock; | 135 | rule SwitchBlock; |
| 131 | rule IfElseIf; | 136 | rule IfElseIf; |
| @@ -181,9 +186,9 @@ private: | |||
| 181 | AST_RULE(SelfName) | 186 | AST_RULE(SelfName) |
| 182 | AST_RULE(KeyName) | 187 | AST_RULE(KeyName) |
| 183 | AST_RULE(VarArg) | 188 | AST_RULE(VarArg) |
| 184 | AST_RULE(local_flag) | ||
| 185 | AST_RULE(Seperator) | 189 | AST_RULE(Seperator) |
| 186 | AST_RULE(NameList) | 190 | AST_RULE(NameList) |
| 191 | AST_RULE(local_flag) | ||
| 187 | AST_RULE(Local) | 192 | AST_RULE(Local) |
| 188 | AST_RULE(colon_import_name) | 193 | AST_RULE(colon_import_name) |
| 189 | AST_RULE(import_literal_inner) | 194 | AST_RULE(import_literal_inner) |
| @@ -249,8 +254,10 @@ private: | |||
| 249 | AST_RULE(class_member_list) | 254 | AST_RULE(class_member_list) |
| 250 | AST_RULE(ClassBlock) | 255 | AST_RULE(ClassBlock) |
| 251 | AST_RULE(ClassDecl) | 256 | AST_RULE(ClassDecl) |
| 252 | AST_RULE(export_values) | 257 | AST_RULE(global_values) |
| 253 | AST_RULE(export_op) | 258 | AST_RULE(global_op) |
| 259 | AST_RULE(Global) | ||
| 260 | AST_RULE(export_default) | ||
| 254 | AST_RULE(Export) | 261 | AST_RULE(Export) |
| 255 | AST_RULE(variable_pair) | 262 | AST_RULE(variable_pair) |
| 256 | AST_RULE(normal_pair) | 263 | AST_RULE(normal_pair) |
diff --git a/src/moonp.cpp b/src/moonp.cpp index ade1a1b..8026d50 100644 --- a/src/moonp.cpp +++ b/src/moonp.cpp | |||
| @@ -81,10 +81,10 @@ int main(int narg, const char** args) { | |||
| 81 | if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') { | 81 | if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') { |
| 82 | targetPath.append("/"); | 82 | targetPath.append("/"); |
| 83 | } | 83 | } |
| 84 | std::list<std::future<std::result_of_t<std::decay_t<int()>()>>> results; | 84 | std::list<std::future<int>> results; |
| 85 | for (const auto& file : files) { | 85 | for (const auto& file : files) { |
| 86 | auto task = std::async(std::launch::async, [=]() { | 86 | auto task = std::async(std::launch::async, [=]() { |
| 87 | std::ifstream input(file, input.in); | 87 | std::ifstream input(file, std::ios::in); |
| 88 | if (input) { | 88 | if (input) { |
| 89 | std::string s( | 89 | std::string s( |
| 90 | (std::istreambuf_iterator<char>(input)), | 90 | (std::istreambuf_iterator<char>(input)), |
| @@ -135,7 +135,7 @@ int main(int narg, const char** args) { | |||
| 135 | } else { | 135 | } else { |
| 136 | targetFile = resultFile; | 136 | targetFile = resultFile; |
| 137 | } | 137 | } |
| 138 | std::ofstream output(targetFile, output.trunc | output.out); | 138 | std::ofstream output(targetFile, std::ios::trunc | std::ios::out); |
| 139 | if (output) { | 139 | if (output) { |
| 140 | const auto& codes = std::get<0>(result); | 140 | const auto& codes = std::get<0>(result); |
| 141 | output.write(codes.c_str(), codes.size()); | 141 | output.write(codes.c_str(), codes.size()); |
