aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-05-07 17:06:00 +0800
committerLi Jin <dragon-fly@qq.com>2021-05-07 17:06:00 +0800
commit4c9209b131936ad97c73a7c0e71042fe24369a8e (patch)
tree4e0ea3a2e9b4cdf3cb8e1ddc8b974faaddcab94b
parentc46703c3d7c756608ca050143703483368ebf466 (diff)
downloadyuescript-4c9209b131936ad97c73a7c0e71042fe24369a8e.tar.gz
yuescript-4c9209b131936ad97c73a7c0e71042fe24369a8e.tar.bz2
yuescript-4c9209b131936ad97c73a7c0e71042fe24369a8e.zip
fix variable type check functions.
-rw-r--r--src/yuescript/yue_compiler.cpp71
1 files changed, 39 insertions, 32 deletions
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 78fb5e2..4646288 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -59,7 +59,7 @@ inline std::string s(std::string_view sv) {
59 return std::string(sv); 59 return std::string(sv);
60} 60}
61 61
62const std::string_view version = "0.7.12"sv; 62const std::string_view version = "0.7.13"sv;
63const std::string_view extension = "yue"sv; 63const std::string_view extension = "yue"sv;
64 64
65class YueCompilerImpl { 65class YueCompilerImpl {
@@ -216,9 +216,14 @@ private:
216 Capital = 1, 216 Capital = 1,
217 Any = 2 217 Any = 2
218 }; 218 };
219 enum class VarType {
220 Local = 0,
221 Const = 1,
222 Global = 2
223 };
219 struct Scope { 224 struct Scope {
220 GlobalMode mode = GlobalMode::None; 225 GlobalMode mode = GlobalMode::None;
221 std::unique_ptr<std::unordered_map<std::string,bool>> vars; 226 std::unique_ptr<std::unordered_map<std::string,VarType>> vars;
222 std::unique_ptr<std::unordered_set<std::string>> allows; 227 std::unique_ptr<std::unordered_set<std::string>> allows;
223 std::unique_ptr<std::unordered_set<std::string>> globals; 228 std::unique_ptr<std::unordered_set<std::string>> globals;
224 }; 229 };
@@ -257,7 +262,7 @@ private:
257 262
258 void pushScope() { 263 void pushScope() {
259 _scopes.emplace_back(); 264 _scopes.emplace_back();
260 _scopes.back().vars = std::make_unique<std::unordered_map<std::string,bool>>(); 265 _scopes.back().vars = std::make_unique<std::unordered_map<std::string,VarType>>();
261 } 266 }
262 267
263 void popScope() { 268 void popScope() {
@@ -272,11 +277,11 @@ private:
272 if (current.globals) { 277 if (current.globals) {
273 if (current.globals->find(name) != current.globals->end()) { 278 if (current.globals->find(name) != current.globals->end()) {
274 isDefined = true; 279 isDefined = true;
275 current.vars->insert_or_assign(name, false); 280 current.vars->insert_or_assign(name, VarType::Global);
276 } 281 }
277 } else { 282 } else {
278 isDefined = true; 283 isDefined = true;
279 current.vars->insert_or_assign(name, false); 284 current.vars->insert_or_assign(name, VarType::Global);
280 } 285 }
281 } 286 }
282 decltype(_scopes.back().allows.get()) allows = nullptr; 287 decltype(_scopes.back().allows.get()) allows = nullptr;
@@ -298,11 +303,12 @@ private:
298 return isDefined; 303 return isDefined;
299 } 304 }
300 305
301 bool isSolidDefined(const std::string& name) const { 306 bool isLocal(const std::string& name) const {
302 bool isDefined = false; 307 bool isDefined = false;
303 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { 308 for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) {
304 auto vars = it->vars.get(); 309 auto vars = it->vars.get();
305 if (vars->find(name) != vars->end()) { 310 auto vit = vars->find(name);
311 if (vit != vars->end() && vit->second != VarType::Global) {
306 isDefined = true; 312 isDefined = true;
307 break; 313 break;
308 } 314 }
@@ -324,7 +330,7 @@ private:
324 auto vars = it->vars.get(); 330 auto vars = it->vars.get();
325 auto vit = vars->find(name); 331 auto vit = vars->find(name);
326 if (vit != vars->end()) { 332 if (vit != vars->end()) {
327 isConst = vit->second; 333 isConst = (vit->second == VarType::Const);
328 break; 334 break;
329 } 335 }
330 if (checkShadowScopeOnly && it->allows) break; 336 if (checkShadowScopeOnly && it->allows) break;
@@ -340,7 +346,7 @@ private:
340 346
341 void markVarConst(const std::string& name) { 347 void markVarConst(const std::string& name) {
342 auto& scope = _scopes.back(); 348 auto& scope = _scopes.back();
343 scope.vars->insert_or_assign(name, true); 349 scope.vars->insert_or_assign(name, VarType::Const);
344 } 350 }
345 351
346 void markVarShadowed() { 352 void markVarShadowed() {
@@ -348,16 +354,17 @@ private:
348 scope.allows = std::make_unique<std::unordered_set<std::string>>(); 354 scope.allows = std::make_unique<std::unordered_set<std::string>>();
349 } 355 }
350 356
351 void markVarGlobal(GlobalMode mode, bool specified) { 357 void markVarsGlobal(GlobalMode mode) {
352 auto& scope = _scopes.back(); 358 auto& scope = _scopes.back();
353 scope.mode = mode; 359 scope.mode = mode;
354 if (specified && !scope.globals) {
355 scope.globals = std::make_unique<std::unordered_set<std::string>>();
356 }
357 } 360 }
358 361
359 void addGlobalVar(const std::string& name) { 362 void addGlobalVar(const std::string& name, ast_node* x) {
363 if (isLocal(name)) throw std::logic_error(_info.errorMessage("can not declare a local variable to be global"sv, x));
360 auto& scope = _scopes.back(); 364 auto& scope = _scopes.back();
365 if (!scope.globals) {
366 scope.globals = std::make_unique<std::unordered_set<std::string>>();
367 }
361 scope.globals->insert(name); 368 scope.globals->insert(name);
362 } 369 }
363 370
@@ -368,7 +375,7 @@ private:
368 375
369 void forceAddToScope(const std::string& name) { 376 void forceAddToScope(const std::string& name) {
370 auto& scope = _scopes.back(); 377 auto& scope = _scopes.back();
371 scope.vars->insert_or_assign(name, false); 378 scope.vars->insert_or_assign(name, VarType::Local);
372 } 379 }
373 380
374 Scope& currentScope() { 381 Scope& currentScope() {
@@ -379,7 +386,7 @@ private:
379 bool defined = isDefined(name); 386 bool defined = isDefined(name);
380 if (!defined) { 387 if (!defined) {
381 auto& scope = currentScope(); 388 auto& scope = currentScope();
382 scope.vars->insert_or_assign(name, false); 389 scope.vars->insert_or_assign(name, VarType::Local);
383 } 390 }
384 return !defined; 391 return !defined;
385 } 392 }
@@ -390,7 +397,7 @@ private:
390 do { 397 do {
391 newName = s(name) + std::to_string(index); 398 newName = s(name) + std::to_string(index);
392 index++; 399 index++;
393 } while (isSolidDefined(newName)); 400 } while (isLocal(newName));
394 return newName; 401 return newName;
395 } 402 }
396 403
@@ -2105,7 +2112,7 @@ private:
2105 switch (item->getId()) { 2112 switch (item->getId()) {
2106 case id<Variable_t>(): { 2113 case id<Variable_t>(): {
2107 transformVariable(static_cast<Variable_t*>(item), out); 2114 transformVariable(static_cast<Variable_t*>(item), out);
2108 if (_config.lintGlobalVariable && !isSolidDefined(out.back())) { 2115 if (_config.lintGlobalVariable && !isLocal(out.back())) {
2109 if (_globals.find(out.back()) == _globals.end()) { 2116 if (_globals.find(out.back()) == _globals.end()) {
2110 _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col}; 2117 _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col};
2111 } 2118 }
@@ -4060,7 +4067,7 @@ private:
4060 case id<star_exp_t>(): { 4067 case id<star_exp_t>(): {
4061 auto star_exp = static_cast<star_exp_t*>(loopTarget); 4068 auto star_exp = static_cast<star_exp_t*>(loopTarget);
4062 auto listVar = singleVariableFrom(star_exp->value); 4069 auto listVar = singleVariableFrom(star_exp->value);
4063 if (!isSolidDefined(listVar)) listVar.clear(); 4070 if (!isLocal(listVar)) listVar.clear();
4064 auto indexVar = getUnusedName("_index_"sv); 4071 auto indexVar = getUnusedName("_index_"sv);
4065 varAfter.push_back(indexVar); 4072 varAfter.push_back(indexVar);
4066 auto value = singleValueFrom(star_exp->value); 4073 auto value = singleValueFrom(star_exp->value);
@@ -4076,7 +4083,7 @@ private:
4076 if (listVar.empty() && chainList.size() == 2) { 4083 if (listVar.empty() && chainList.size() == 2) {
4077 if (auto var = chainList.front()->getByPath<Variable_t>()) { 4084 if (auto var = chainList.front()->getByPath<Variable_t>()) {
4078 listVar = _parser.toString(var); 4085 listVar = _parser.toString(var);
4079 if (!isSolidDefined(listVar)) listVar.clear(); 4086 if (!isLocal(listVar)) listVar.clear();
4080 } 4087 }
4081 } 4088 }
4082 chainList.pop_back(); 4089 chainList.pop_back();
@@ -4439,7 +4446,7 @@ private:
4439 4446
4440 void transform_variable_pair(variable_pair_t* pair, str_list& out) { 4447 void transform_variable_pair(variable_pair_t* pair, str_list& out) {
4441 auto name = _parser.toString(pair->name); 4448 auto name = _parser.toString(pair->name);
4442 if (_config.lintGlobalVariable && !isSolidDefined(name)) { 4449 if (_config.lintGlobalVariable && !isLocal(name)) {
4443 if (_globals.find(name) == _globals.end()) { 4450 if (_globals.find(name) == _globals.end()) {
4444 _globals[name] = {pair->name->m_begin.m_line, pair->name->m_begin.m_col}; 4451 _globals[name] = {pair->name->m_begin.m_line, pair->name->m_begin.m_col};
4445 } 4452 }
@@ -4938,7 +4945,7 @@ private:
4938 if (vars.front().empty()) { 4945 if (vars.front().empty()) {
4939 if (with->assigns->values.objects().size() == 1) { 4946 if (with->assigns->values.objects().size() == 1) {
4940 auto var = singleVariableFrom(with->assigns->values.objects().front()); 4947 auto var = singleVariableFrom(with->assigns->values.objects().front());
4941 if (!var.empty() && isSolidDefined(var)) { 4948 if (!var.empty() && isLocal(var)) {
4942 withVar = var; 4949 withVar = var;
4943 } 4950 }
4944 } 4951 }
@@ -4984,7 +4991,7 @@ private:
4984 } 4991 }
4985 } else { 4992 } else {
4986 withVar = singleVariableFrom(with->valueList); 4993 withVar = singleVariableFrom(with->valueList);
4987 if (withVar.empty() || !isSolidDefined(withVar)) { 4994 if (withVar.empty() || !isLocal(withVar)) {
4988 withVar = getUnusedName("_with_"sv); 4995 withVar = getUnusedName("_with_"sv);
4989 auto assignment = x->new_ptr<ExpListAssign_t>(); 4996 auto assignment = x->new_ptr<ExpListAssign_t>();
4990 assignment->expList.set(toAst<ExpList_t>(withVar, x)); 4997 assignment->expList.set(toAst<ExpList_t>(withVar, x));
@@ -5086,26 +5093,26 @@ private:
5086 case id<ClassDecl_t>(): { 5093 case id<ClassDecl_t>(): {
5087 auto classDecl = static_cast<ClassDecl_t*>(item); 5094 auto classDecl = static_cast<ClassDecl_t*>(item);
5088 if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { 5095 if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) {
5089 markVarGlobal(GlobalMode::Any, true); 5096 markVarsGlobal(GlobalMode::Any);
5090 addGlobalVar(_parser.toString(classDecl->name->item)); 5097 addGlobalVar(_parser.toString(classDecl->name->item), classDecl->name->item);
5091 } 5098 }
5092 transformClassDecl(classDecl, out, ExpUsage::Common); 5099 transformClassDecl(classDecl, out, ExpUsage::Common);
5093 break; 5100 break;
5094 } 5101 }
5095 case id<global_op_t>(): 5102 case id<global_op_t>():
5096 if (_parser.toString(item) == "*"sv) { 5103 if (_parser.toString(item) == "*"sv) {
5097 markVarGlobal(GlobalMode::Any, false); 5104 markVarsGlobal(GlobalMode::Any);
5098 } else { 5105 } else {
5099 markVarGlobal(GlobalMode::Capital, false); 5106 markVarsGlobal(GlobalMode::Capital);
5100 } 5107 }
5101 break; 5108 break;
5102 case id<global_values_t>(): { 5109 case id<global_values_t>(): {
5103 markVarGlobal(GlobalMode::Any, true); 5110 markVarsGlobal(GlobalMode::Any);
5104 auto values = global->item.to<global_values_t>(); 5111 auto values = global->item.to<global_values_t>();
5105 if (values->valueList) { 5112 if (values->valueList) {
5106 auto expList = x->new_ptr<ExpList_t>(); 5113 auto expList = x->new_ptr<ExpList_t>();
5107 for (auto name : values->nameList->names.objects()) { 5114 for (auto name : values->nameList->names.objects()) {
5108 addGlobalVar(_parser.toString(name)); 5115 addGlobalVar(_parser.toString(name), name);
5109 auto callable = x->new_ptr<Callable_t>(); 5116 auto callable = x->new_ptr<Callable_t>();
5110 callable->item.set(name); 5117 callable->item.set(name);
5111 auto chainValue = x->new_ptr<ChainValue_t>(); 5118 auto chainValue = x->new_ptr<ChainValue_t>();
@@ -5128,7 +5135,7 @@ private:
5128 transformAssignment(assignment, out); 5135 transformAssignment(assignment, out);
5129 } else { 5136 } else {
5130 for (auto name : values->nameList->names.objects()) { 5137 for (auto name : values->nameList->names.objects()) {
5131 addGlobalVar(_parser.toString(name)); 5138 addGlobalVar(_parser.toString(name), name);
5132 } 5139 }
5133 } 5140 }
5134 break; 5141 break;
@@ -5810,7 +5817,7 @@ private:
5810 _enableReturn.push(true); 5817 _enableReturn.push(true);
5811 } 5818 }
5812 auto objVar = singleVariableFrom(switchNode->target); 5819 auto objVar = singleVariableFrom(switchNode->target);
5813 if (objVar.empty()) { 5820 if (objVar.empty() || !isLocal(objVar)) {
5814 objVar = getUnusedName("_exp_"sv); 5821 objVar = getUnusedName("_exp_"sv);
5815 addToScope(objVar); 5822 addToScope(objVar);
5816 transformExp(switchNode->target, temp, ExpUsage::Closure); 5823 transformExp(switchNode->target, temp, ExpUsage::Closure);
@@ -5921,7 +5928,7 @@ private:
5921 } 5928 }
5922 str_list temp; 5929 str_list temp;
5923 auto varStr = join(vars, ", "sv); 5930 auto varStr = join(vars, ", "sv);
5924 temp.push_back(s("local "sv) + varStr + nll(x)); 5931 temp.push_back(indent() + s("local "sv) + varStr + nll(x));
5925 auto varList = toAst<ExpList_t>(varStr, x); 5932 auto varList = toAst<ExpList_t>(varStr, x);
5926 auto assignment = x->new_ptr<ExpListAssign_t>(); 5933 auto assignment = x->new_ptr<ExpListAssign_t>();
5927 assignment->expList.set(varList); 5934 assignment->expList.set(varList);