aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2026-01-15 17:07:11 +0800
committerLi Jin <dragon-fly@qq.com>2026-01-15 17:07:11 +0800
commitfced0c4f4101ad7c8d81432a0e8c45d38b72616c (patch)
treeed673461c7ef3c614cb5d56905c437f6a6b27454 /src
parent4177d237e3ed642b2bba5bec13127a44d2b0524d (diff)
downloadyuescript-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.cpp3
-rw-r--r--src/yuescript/yue_ast.h5
-rw-r--r--src/yuescript/yue_compiler.cpp78
-rw-r--r--src/yuescript/yue_parser.cpp16
-rw-r--r--src/yuescript/yue_parser.h1
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}
329std::string ImportAllGlobal_t::to_string(void*) const {
330 return "global"s;
331}
329std::string Import_t::to_string(void* ud) const { 332std::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)
234AST_END(ImportAs) 234AST_END(ImportAs)
235 235
236AST_LEAF(ImportAllGlobal)
237AST_END(ImportAllGlobal)
238
236AST_NODE(ImportGlobal) 239AST_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)
241AST_END(ImportGlobal) 244AST_END(ImportGlobal)
242 245
243AST_NODE(Import) 246AST_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)
246AST_END(Import) 249AST_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
81const std::string_view version = "0.30.4"sv; 81const std::string_view version = "0.31.0"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class 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);