diff options
| author | Li Jin <dragon-fly@qq.com> | 2026-01-15 17:07:11 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2026-01-15 17:07:11 +0800 |
| commit | fced0c4f4101ad7c8d81432a0e8c45d38b72616c (patch) | |
| tree | ed673461c7ef3c614cb5d56905c437f6a6b27454 /src | |
| parent | 4177d237e3ed642b2bba5bec13127a44d2b0524d (diff) | |
| download | yuescript-fced0c4f4101ad7c8d81432a0e8c45d38b72616c.tar.gz yuescript-fced0c4f4101ad7c8d81432a0e8c45d38b72616c.tar.bz2 yuescript-fced0c4f4101ad7c8d81432a0e8c45d38b72616c.zip | |
Added `import global` syntax.
Diffstat (limited to 'src')
| -rw-r--r-- | src/yuescript/yue_ast.cpp | 3 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 5 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 78 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 16 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.h | 1 |
5 files changed, 83 insertions, 20 deletions
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index 14d8db8..c9fd23f 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -326,6 +326,9 @@ std::string ImportGlobal_t::to_string(void* ud) const { | |||
| 326 | } | 326 | } |
| 327 | return item; | 327 | return item; |
| 328 | } | 328 | } |
| 329 | std::string ImportAllGlobal_t::to_string(void*) const { | ||
| 330 | return "global"s; | ||
| 331 | } | ||
| 329 | std::string Import_t::to_string(void* ud) const { | 332 | std::string Import_t::to_string(void* ud) const { |
| 330 | if (ast_is<FromImport_t>(content)) { | 333 | if (ast_is<FromImport_t>(content)) { |
| 331 | return content->to_string(ud); | 334 | return content->to_string(ud); |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index ba4186d..af2355a 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -233,6 +233,9 @@ AST_NODE(ImportAs) | |||
| 233 | AST_MEMBER(ImportAs, &literal, &target) | 233 | AST_MEMBER(ImportAs, &literal, &target) |
| 234 | AST_END(ImportAs) | 234 | AST_END(ImportAs) |
| 235 | 235 | ||
| 236 | AST_LEAF(ImportAllGlobal) | ||
| 237 | AST_END(ImportAllGlobal) | ||
| 238 | |||
| 236 | AST_NODE(ImportGlobal) | 239 | AST_NODE(ImportGlobal) |
| 237 | ast_ptr<true, Seperator_t> sep; | 240 | ast_ptr<true, Seperator_t> sep; |
| 238 | ast_list<true, UnicodeName_t> segs; | 241 | ast_list<true, UnicodeName_t> segs; |
| @@ -241,7 +244,7 @@ AST_NODE(ImportGlobal) | |||
| 241 | AST_END(ImportGlobal) | 244 | AST_END(ImportGlobal) |
| 242 | 245 | ||
| 243 | AST_NODE(Import) | 246 | AST_NODE(Import) |
| 244 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t, ImportGlobal_t> content; | 247 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t, ImportGlobal_t, ImportAllGlobal_t> content; |
| 245 | AST_MEMBER(Import, &content) | 248 | AST_MEMBER(Import, &content) |
| 246 | AST_END(Import) | 249 | AST_END(Import) |
| 247 | 250 | ||
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index cffa7a8..10f8719 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 78 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | const std::string_view version = "0.30.4"sv; | 81 | const std::string_view version = "0.31.0"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
| @@ -434,6 +434,14 @@ private: | |||
| 434 | Global = 2, | 434 | Global = 2, |
| 435 | GlobalConst = 3 | 435 | GlobalConst = 3 |
| 436 | }; | 436 | }; |
| 437 | struct Scope; | ||
| 438 | struct ImportedGlobal { | ||
| 439 | std::string* globalCodeLine = nullptr; | ||
| 440 | Scope* importingScope = nullptr; | ||
| 441 | std::string indent; | ||
| 442 | std::string nl; | ||
| 443 | std::unordered_set<std::string> globals; | ||
| 444 | }; | ||
| 437 | struct Scope { | 445 | struct Scope { |
| 438 | GlobalMode mode = GlobalMode::None; | 446 | GlobalMode mode = GlobalMode::None; |
| 439 | bool lastStatement = false; | 447 | bool lastStatement = false; |
| @@ -442,8 +450,10 @@ private: | |||
| 442 | #endif | 450 | #endif |
| 443 | std::unique_ptr<std::unordered_map<std::string, VarType>> vars; | 451 | std::unique_ptr<std::unordered_map<std::string, VarType>> vars; |
| 444 | std::unique_ptr<std::unordered_set<std::string>> allows; | 452 | std::unique_ptr<std::unordered_set<std::string>> allows; |
| 453 | std::unique_ptr<ImportedGlobal> importedGlobal; | ||
| 445 | }; | 454 | }; |
| 446 | std::list<Scope> _scopes; | 455 | std::list<Scope> _scopes; |
| 456 | ImportedGlobal* _importedGlobal = nullptr; | ||
| 447 | static const std::string Empty; | 457 | static const std::string Empty; |
| 448 | 458 | ||
| 449 | enum class MemType { | 459 | enum class MemType { |
| @@ -1612,7 +1622,12 @@ private: | |||
| 1612 | 1622 | ||
| 1613 | std::string globalVar(std::string_view var, ast_node* x, AccessType accessType) { | 1623 | std::string globalVar(std::string_view var, ast_node* x, AccessType accessType) { |
| 1614 | std::string str(var); | 1624 | std::string str(var); |
| 1615 | if (_config.lintGlobalVariable) { | 1625 | if (_importedGlobal) { |
| 1626 | if (_importedGlobal->globals.find(str) == _importedGlobal->globals.end() && !isSolidDefined(str)) { | ||
| 1627 | _importedGlobal->globals.insert(str); | ||
| 1628 | _importedGlobal->importingScope->vars->insert_or_assign(str, VarType::LocalConst); | ||
| 1629 | } | ||
| 1630 | } else if (_config.lintGlobalVariable) { | ||
| 1616 | if (!isLocal(str)) { | 1631 | if (!isLocal(str)) { |
| 1617 | auto key = str + ':' + std::to_string(x->m_begin.m_line) + ':' + std::to_string(x->m_begin.m_col); | 1632 | auto key = str + ':' + std::to_string(x->m_begin.m_line) + ':' + std::to_string(x->m_begin.m_col); |
| 1618 | if (_globals.find(key) == _globals.end()) { | 1633 | if (_globals.find(key) == _globals.end()) { |
| @@ -4617,13 +4632,21 @@ private: | |||
| 4617 | switch (item->get_id()) { | 4632 | switch (item->get_id()) { |
| 4618 | case id<Variable_t>(): { | 4633 | case id<Variable_t>(): { |
| 4619 | transformVariable(static_cast<Variable_t*>(item), out); | 4634 | transformVariable(static_cast<Variable_t*>(item), out); |
| 4620 | if (_config.lintGlobalVariable && accessType != AccessType::None && !isLocal(out.back())) { | 4635 | if (accessType != AccessType::None) { |
| 4621 | auto key = out.back() + ':' + std::to_string(item->m_begin.m_line) + ':' + std::to_string(item->m_begin.m_col); | 4636 | if (_importedGlobal) { |
| 4622 | if (_globals.find(key) == _globals.end()) { | 4637 | const auto& str = out.back(); |
| 4623 | if (accessType == AccessType::Read && _funcLevel > 1) { | 4638 | if (_importedGlobal->globals.find(str) == _importedGlobal->globals.end() && !isSolidDefined(str)) { |
| 4624 | accessType = AccessType::Capture; | 4639 | _importedGlobal->globals.insert(str); |
| 4640 | _importedGlobal->importingScope->vars->insert_or_assign(str, VarType::LocalConst); | ||
| 4641 | } | ||
| 4642 | } else if (_config.lintGlobalVariable && !isLocal(out.back())) { | ||
| 4643 | auto key = out.back() + ':' + std::to_string(item->m_begin.m_line) + ':' + std::to_string(item->m_begin.m_col); | ||
| 4644 | if (_globals.find(key) == _globals.end()) { | ||
| 4645 | if (accessType == AccessType::Read && _funcLevel > 1) { | ||
| 4646 | accessType = AccessType::Capture; | ||
| 4647 | } | ||
| 4648 | _globals[key] = {out.back(), item->m_begin.m_line, item->m_begin.m_col, accessType, isSolidDefined(out.back())}; | ||
| 4625 | } | 4649 | } |
| 4626 | _globals[key] = {out.back(), item->m_begin.m_line, item->m_begin.m_col, accessType, isSolidDefined(out.back())}; | ||
| 4627 | } | 4650 | } |
| 4628 | } | 4651 | } |
| 4629 | break; | 4652 | break; |
| @@ -5299,7 +5322,23 @@ private: | |||
| 5299 | } | 5322 | } |
| 5300 | auto transformNode = [&]() { | 5323 | auto transformNode = [&]() { |
| 5301 | currentScope().lastStatement = (node == lastStmt) && currentScope().mode == GlobalMode::None; | 5324 | currentScope().lastStatement = (node == lastStmt) && currentScope().mode == GlobalMode::None; |
| 5302 | transformStatement(static_cast<Statement_t*>(node), temp); | 5325 | auto stmt = static_cast<Statement_t*>(node); |
| 5326 | if (auto importNode = stmt->content.as<Import_t>(); | ||
| 5327 | importNode && importNode->content.is<ImportAllGlobal_t>()) { | ||
| 5328 | if (_importedGlobal) { | ||
| 5329 | throw CompileError("import global redeclared in same scope"sv, importNode); | ||
| 5330 | } else { | ||
| 5331 | auto& scope = currentScope(); | ||
| 5332 | scope.importedGlobal = std::make_unique<ImportedGlobal>(); | ||
| 5333 | _importedGlobal = scope.importedGlobal.get(); | ||
| 5334 | _importedGlobal->importingScope = &scope; | ||
| 5335 | _importedGlobal->indent = indent(); | ||
| 5336 | _importedGlobal->nl = nl(stmt); | ||
| 5337 | _importedGlobal->globalCodeLine = &temp.emplace_back(); | ||
| 5338 | } | ||
| 5339 | } else { | ||
| 5340 | transformStatement(stmt, temp); | ||
| 5341 | } | ||
| 5303 | if (isRoot && !_rootDefs.empty()) { | 5342 | if (isRoot && !_rootDefs.empty()) { |
| 5304 | auto last = std::move(temp.back()); | 5343 | auto last = std::move(temp.back()); |
| 5305 | temp.pop_back(); | 5344 | temp.pop_back(); |
| @@ -5338,6 +5377,14 @@ private: | |||
| 5338 | transformNode(); | 5377 | transformNode(); |
| 5339 | } | 5378 | } |
| 5340 | } | 5379 | } |
| 5380 | if (auto importedGlobal = currentScope().importedGlobal.get()) { | ||
| 5381 | str_list globalCodes; | ||
| 5382 | for (const auto& global : importedGlobal->globals) { | ||
| 5383 | globalCodes.emplace_back(importedGlobal->indent + "local "s + global + " = "s + global + importedGlobal->nl); | ||
| 5384 | } | ||
| 5385 | *importedGlobal->globalCodeLine = join(globalCodes); | ||
| 5386 | _importedGlobal = nullptr; | ||
| 5387 | } | ||
| 5341 | out.push_back(join(temp)); | 5388 | out.push_back(join(temp)); |
| 5342 | } else { | 5389 | } else { |
| 5343 | out.push_back(Empty); | 5390 | out.push_back(Empty); |
| @@ -9313,7 +9360,12 @@ private: | |||
| 9313 | } else { | 9360 | } else { |
| 9314 | out.push_back(name + " = "s + name); | 9361 | out.push_back(name + " = "s + name); |
| 9315 | } | 9362 | } |
| 9316 | if (_config.lintGlobalVariable && !isLocal(name)) { | 9363 | if (_importedGlobal) { |
| 9364 | if (_importedGlobal->globals.find(name) == _importedGlobal->globals.end() && !isSolidDefined(name)) { | ||
| 9365 | _importedGlobal->globals.insert(name); | ||
| 9366 | _importedGlobal->importingScope->vars->insert_or_assign(name, VarType::LocalConst); | ||
| 9367 | } | ||
| 9368 | } else if (_config.lintGlobalVariable && !isLocal(name)) { | ||
| 9317 | auto key = name + ':' + std::to_string(pair->name->m_begin.m_line) + ':' + std::to_string(pair->name->m_begin.m_col); | 9369 | auto key = name + ':' + std::to_string(pair->name->m_begin.m_line) + ':' + std::to_string(pair->name->m_begin.m_col); |
| 9318 | if (_globals.find(key) == _globals.end()) { | 9370 | if (_globals.find(key) == _globals.end()) { |
| 9319 | _globals[key] = {name, pair->name->m_begin.m_line, pair->name->m_begin.m_col, _funcLevel > 1 ? AccessType::Capture : AccessType::Read, isSolidDefined(name)}; | 9371 | _globals[key] = {name, pair->name->m_begin.m_line, pair->name->m_begin.m_col, _funcLevel > 1 ? AccessType::Capture : AccessType::Read, isSolidDefined(name)}; |
| @@ -10348,8 +10400,10 @@ private: | |||
| 10348 | } | 10400 | } |
| 10349 | assignment->action.set(assign); | 10401 | assignment->action.set(assign); |
| 10350 | transformAssignment(assignment, out); | 10402 | transformAssignment(assignment, out); |
| 10351 | for (const auto& name : varNames) { | 10403 | if (global->constAttrib) { |
| 10352 | markVarGlobalConst(name); | 10404 | for (const auto& name : varNames) { |
| 10405 | markVarGlobalConst(name); | ||
| 10406 | } | ||
| 10353 | } | 10407 | } |
| 10354 | } else { | 10408 | } else { |
| 10355 | for (auto name : values->nameList->names.objects()) { | 10409 | for (auto name : values->nameList->names.objects()) { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 1dfe978..6990e31 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -464,7 +464,9 @@ YueParser::YueParser() { | |||
| 464 | 464 | ||
| 465 | ImportGlobal = Seperator >> UnicodeName >> *('.' >> UnicodeName) >> space >> not_(',' | key("from")) >> -(key("as") >> space >> must_variable); | 465 | ImportGlobal = Seperator >> UnicodeName >> *('.' >> UnicodeName) >> space >> not_(',' | key("from")) >> -(key("as") >> space >> must_variable); |
| 466 | 466 | ||
| 467 | Import = key("import") >> space >> (ImportGlobal | ImportAs | ImportFrom | invalid_import_syntax_error) | FromImport; | 467 | ImportAllGlobal = key("global"); |
| 468 | |||
| 469 | Import = key("import") >> space >> (ImportAllGlobal | ImportGlobal | ImportAs | ImportFrom | invalid_import_syntax_error) | FromImport; | ||
| 468 | 470 | ||
| 469 | Label = "::" >> (and_(LuaKeyword >> "::") >> keyword_as_label_error | UnicodeName >> "::"); | 471 | Label = "::" >> (and_(LuaKeyword >> "::") >> keyword_as_label_error | UnicodeName >> "::"); |
| 470 | 472 | ||
| @@ -982,7 +984,7 @@ YueParser::YueParser() { | |||
| 982 | return true; | 984 | return true; |
| 983 | }) | | 985 | }) | |
| 984 | invalid_export_syntax_error | 986 | invalid_export_syntax_error |
| 985 | ) >> not_(space >> StatementAppendix); | 987 | ); |
| 986 | 988 | ||
| 987 | VariablePair = ':' >> Variable; | 989 | VariablePair = ':' >> Variable; |
| 988 | 990 | ||
| @@ -1125,14 +1127,14 @@ YueParser::YueParser() { | |||
| 1125 | StatementAppendix = (IfLine | WhileLine | CompFor) >> space; | 1127 | StatementAppendix = (IfLine | WhileLine | CompFor) >> space; |
| 1126 | Statement = | 1128 | Statement = |
| 1127 | ( | 1129 | ( |
| 1128 | Import | While | Repeat | For | | 1130 | Import | Export | Global | Macro | MacroInPlace | Label |
| 1129 | Return | Local | Global | Export | Macro | | 1131 | ) | ( |
| 1130 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | | 1132 | Local | While | Repeat | For | Return | |
| 1133 | BreakLoop | Goto | ShortTabAppending | | ||
| 1131 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | | 1134 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | |
| 1132 | StatementAppendix >> empty_block_error | | 1135 | StatementAppendix >> empty_block_error | |
| 1133 | and_(key("else") | key("elseif") | key("when")) >> dangling_clause_error | 1136 | and_(key("else") | key("elseif") | key("when")) >> dangling_clause_error |
| 1134 | ) >> space >> | 1137 | ) >> space >> -StatementAppendix; |
| 1135 | -StatementAppendix; | ||
| 1136 | 1138 | ||
| 1137 | StatementSep = white >> (set("('\"") | "[[" | "[="); | 1139 | StatementSep = white >> (set("('\"") | "[[" | "[="); |
| 1138 | 1140 | ||
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index acb56d0..c516ccd 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -352,6 +352,7 @@ private: | |||
| 352 | AST_RULE(ImportTabLit); | 352 | AST_RULE(ImportTabLit); |
| 353 | AST_RULE(ImportAs); | 353 | AST_RULE(ImportAs); |
| 354 | AST_RULE(ImportGlobal); | 354 | AST_RULE(ImportGlobal); |
| 355 | AST_RULE(ImportAllGlobal); | ||
| 355 | AST_RULE(Import); | 356 | AST_RULE(Import); |
| 356 | AST_RULE(Label); | 357 | AST_RULE(Label); |
| 357 | AST_RULE(Goto); | 358 | AST_RULE(Goto); |
