From 229a8364441edfb4a3314ad2e70da954e00748c8 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 10 Dec 2022 19:26:30 +0800 Subject: [PATCH] up --- plugins/flutter/CHANGELOG.md | 5 +- plugins/flutter/pubspec.yaml | 2 +- plugins/flutter/src/pocketpy.h | 77 +++++--- plugins/godot/godot-cpp | 2 +- .../com.bl.pocketpy/Plugins/iOS/pocketpy.h | 77 +++++--- src/compiler.h | 47 +++-- src/error.h | 24 ++- src/parser.h | 6 - tests/dna2.py | 185 ++++++++++++++++++ 9 files changed, 331 insertions(+), 94 deletions(-) create mode 100644 tests/dna2.py diff --git a/plugins/flutter/CHANGELOG.md b/plugins/flutter/CHANGELOG.md index d74eb5a5..e081d019 100644 --- a/plugins/flutter/CHANGELOG.md +++ b/plugins/flutter/CHANGELOG.md @@ -17,6 +17,7 @@ The initial version. Hello, world! + Fix a bug about comment and indentation + Fix a bug about compile error line number -## 0.4.8+3 +## 0.4.8+4 -+ Downgrade to `sdk>=2.17.0` \ No newline at end of file ++ Downgrade to `sdk>=2.17.0` ++ Fix some bugs about compile error \ No newline at end of file diff --git a/plugins/flutter/pubspec.yaml b/plugins/flutter/pubspec.yaml index 54874ae9..b48f1233 100644 --- a/plugins/flutter/pubspec.yaml +++ b/plugins/flutter/pubspec.yaml @@ -1,6 +1,6 @@ name: pocketpy description: A lightweight Python interpreter for game engines. -version: 0.4.8+3 +version: 0.4.8+4 homepage: https://pocketpy.dev repository: https://github.com/blueloveth/pocketpy diff --git a/plugins/flutter/src/pocketpy.h b/plugins/flutter/src/pocketpy.h index c0c12916..7c223451 100644 --- a/plugins/flutter/src/pocketpy.h +++ b/plugins/flutter/src/pocketpy.h @@ -2904,14 +2904,14 @@ struct SourceMetadata { std::vector lineStarts; CompileMode mode; - _Str getLine(int lineno) const { - if(lineno == -1) return ""; + std::pair getLine(int lineno) const { + if(lineno == -1) return {nullptr, nullptr}; lineno -= 1; if(lineno < 0) lineno = 0; const char* _start = lineStarts.at(lineno); const char* i = _start; while(*i != '\n' && *i != '\0') i++; - return _Str(_start, i-_start); + return {_start, i}; } SourceMetadata(const char* source, _Str filename, CompileMode mode) { @@ -2924,12 +2924,24 @@ struct SourceMetadata { this->mode = mode; } - _Str snapshot(int lineno){ + _Str snapshot(int lineno, const char* cursor=nullptr){ _StrStream ss; ss << " " << "File \"" << filename << "\", line " << lineno << '\n'; - _Str line = getLine(lineno).__lstrip(); - if(line.empty()) line = ""; + std::pair pair = getLine(lineno); + _Str line = ""; + int removedSpaces = 0; + if(pair.first && pair.second){ + line = _Str(pair.first, pair.second-pair.first).__lstrip(); + removedSpaces = pair.second - pair.first - line.size(); + if(line.empty()) line = ""; + } ss << " " << line << '\n'; + if(cursor && line != "" && cursor >= pair.first && cursor <= pair.second){ + int column = cursor - pair.first - removedSpaces; + if(column >= 0){ + ss << " " << std::string(column, ' ') << "^\n"; + } + } return ss.str(); } @@ -3301,12 +3313,6 @@ struct Parser { return c; } - inline bool isNameStart(char c){ - if(isalpha(c) || c=='_') return true; - if(!isascii(c)) return true; - return false; - } - int eatName() { current_char--; while(true){ @@ -5090,6 +5096,7 @@ public: std::stack<_Code> codes; std::stack loops; bool isCompilingClass = false; + int lexingCnt = 0; VM* vm; emhash8::HashMap<_TokenType, GrammarRule> rules; @@ -5233,8 +5240,14 @@ public: } } + void lexToken(){ + lexingCnt++; + _lexToken(); + lexingCnt--; + } + // Lex the next token and set it as the next token. - void lexToken() { + void _lexToken() { parser->previous = parser->current; parser->current = parser->nextToken(); @@ -5324,11 +5337,17 @@ public: } if (isdigit(c)) { eatNumber(); - } else if (parser->isNameStart(c)) { - int ret = parser->eatName(); - if(ret!=0) syntaxError("@id is illegal, err " + std::to_string(ret)); - } else { - syntaxError("unknown character: " + std::string(1, c)); + return; + } + + switch (parser->eatName()) + { + case 0: break; + case 1: syntaxError("invalid char: " + std::string(1, c)); + case 2: syntaxError("invalid utf8 sequence: " + std::string(1, c)); + case 3: syntaxError("@id contains invalid char"); break; + case 4: syntaxError("invalid JSON token"); break; + default: UNREACHABLE(); } return; } @@ -6091,21 +6110,19 @@ __LISTCOMP: /***** Error Reporter *****/ _Str getLineSnapshot(){ int lineno = parser->current.line; + const char* cursor = parser->current.start; + // if error occurs in lexing, lineno should be `parser->current_line` + if(lexingCnt > 0){ + lineno = parser->current_line; + cursor = parser->current_char; + } if(parser->peekChar() == '\n') lineno--; - return parser->src->snapshot(lineno); + return parser->src->snapshot(lineno, cursor); } - void syntaxError(_Str msg){ - throw CompileError("SyntaxError", msg, getLineSnapshot()); - } - - void indentationError(_Str msg){ - throw CompileError("IndentationError", msg, getLineSnapshot()); - } - - void unexpectedError(_Str msg){ - throw CompileError("UnexpectedError", msg, getLineSnapshot()); - } + void syntaxError(_Str msg){ throw CompileError("SyntaxError", msg, getLineSnapshot()); } + void indentationError(_Str msg){ throw CompileError("IndentationError", msg, getLineSnapshot()); } + void unexpectedError(_Str msg){ throw CompileError("UnexpectedError", msg, getLineSnapshot()); } }; _Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) { diff --git a/plugins/godot/godot-cpp b/plugins/godot/godot-cpp index 70637fe5..c645191b 160000 --- a/plugins/godot/godot-cpp +++ b/plugins/godot/godot-cpp @@ -1 +1 @@ -Subproject commit 70637fe5198a3dc5d130781987b3cf2b46de3efc +Subproject commit c645191b67d056996ee4d0d6a387758c16edf7e2 diff --git a/plugins/unity/com.bl.pocketpy/Plugins/iOS/pocketpy.h b/plugins/unity/com.bl.pocketpy/Plugins/iOS/pocketpy.h index c0c12916..7c223451 100644 --- a/plugins/unity/com.bl.pocketpy/Plugins/iOS/pocketpy.h +++ b/plugins/unity/com.bl.pocketpy/Plugins/iOS/pocketpy.h @@ -2904,14 +2904,14 @@ struct SourceMetadata { std::vector lineStarts; CompileMode mode; - _Str getLine(int lineno) const { - if(lineno == -1) return ""; + std::pair getLine(int lineno) const { + if(lineno == -1) return {nullptr, nullptr}; lineno -= 1; if(lineno < 0) lineno = 0; const char* _start = lineStarts.at(lineno); const char* i = _start; while(*i != '\n' && *i != '\0') i++; - return _Str(_start, i-_start); + return {_start, i}; } SourceMetadata(const char* source, _Str filename, CompileMode mode) { @@ -2924,12 +2924,24 @@ struct SourceMetadata { this->mode = mode; } - _Str snapshot(int lineno){ + _Str snapshot(int lineno, const char* cursor=nullptr){ _StrStream ss; ss << " " << "File \"" << filename << "\", line " << lineno << '\n'; - _Str line = getLine(lineno).__lstrip(); - if(line.empty()) line = ""; + std::pair pair = getLine(lineno); + _Str line = ""; + int removedSpaces = 0; + if(pair.first && pair.second){ + line = _Str(pair.first, pair.second-pair.first).__lstrip(); + removedSpaces = pair.second - pair.first - line.size(); + if(line.empty()) line = ""; + } ss << " " << line << '\n'; + if(cursor && line != "" && cursor >= pair.first && cursor <= pair.second){ + int column = cursor - pair.first - removedSpaces; + if(column >= 0){ + ss << " " << std::string(column, ' ') << "^\n"; + } + } return ss.str(); } @@ -3301,12 +3313,6 @@ struct Parser { return c; } - inline bool isNameStart(char c){ - if(isalpha(c) || c=='_') return true; - if(!isascii(c)) return true; - return false; - } - int eatName() { current_char--; while(true){ @@ -5090,6 +5096,7 @@ public: std::stack<_Code> codes; std::stack loops; bool isCompilingClass = false; + int lexingCnt = 0; VM* vm; emhash8::HashMap<_TokenType, GrammarRule> rules; @@ -5233,8 +5240,14 @@ public: } } + void lexToken(){ + lexingCnt++; + _lexToken(); + lexingCnt--; + } + // Lex the next token and set it as the next token. - void lexToken() { + void _lexToken() { parser->previous = parser->current; parser->current = parser->nextToken(); @@ -5324,11 +5337,17 @@ public: } if (isdigit(c)) { eatNumber(); - } else if (parser->isNameStart(c)) { - int ret = parser->eatName(); - if(ret!=0) syntaxError("@id is illegal, err " + std::to_string(ret)); - } else { - syntaxError("unknown character: " + std::string(1, c)); + return; + } + + switch (parser->eatName()) + { + case 0: break; + case 1: syntaxError("invalid char: " + std::string(1, c)); + case 2: syntaxError("invalid utf8 sequence: " + std::string(1, c)); + case 3: syntaxError("@id contains invalid char"); break; + case 4: syntaxError("invalid JSON token"); break; + default: UNREACHABLE(); } return; } @@ -6091,21 +6110,19 @@ __LISTCOMP: /***** Error Reporter *****/ _Str getLineSnapshot(){ int lineno = parser->current.line; + const char* cursor = parser->current.start; + // if error occurs in lexing, lineno should be `parser->current_line` + if(lexingCnt > 0){ + lineno = parser->current_line; + cursor = parser->current_char; + } if(parser->peekChar() == '\n') lineno--; - return parser->src->snapshot(lineno); + return parser->src->snapshot(lineno, cursor); } - void syntaxError(_Str msg){ - throw CompileError("SyntaxError", msg, getLineSnapshot()); - } - - void indentationError(_Str msg){ - throw CompileError("IndentationError", msg, getLineSnapshot()); - } - - void unexpectedError(_Str msg){ - throw CompileError("UnexpectedError", msg, getLineSnapshot()); - } + void syntaxError(_Str msg){ throw CompileError("SyntaxError", msg, getLineSnapshot()); } + void indentationError(_Str msg){ throw CompileError("IndentationError", msg, getLineSnapshot()); } + void unexpectedError(_Str msg){ throw CompileError("UnexpectedError", msg, getLineSnapshot()); } }; _Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) { diff --git a/src/compiler.h b/src/compiler.h index 6144b701..aa83a718 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -27,6 +27,7 @@ public: std::stack<_Code> codes; std::stack loops; bool isCompilingClass = false; + int lexingCnt = 0; VM* vm; emhash8::HashMap<_TokenType, GrammarRule> rules; @@ -170,8 +171,14 @@ public: } } + void lexToken(){ + lexingCnt++; + _lexToken(); + lexingCnt--; + } + // Lex the next token and set it as the next token. - void lexToken() { + void _lexToken() { parser->previous = parser->current; parser->current = parser->nextToken(); @@ -261,11 +268,17 @@ public: } if (isdigit(c)) { eatNumber(); - } else if (parser->isNameStart(c)) { - int ret = parser->eatName(); - if(ret!=0) syntaxError("@id is illegal, err " + std::to_string(ret)); - } else { - syntaxError("unknown character: " + std::string(1, c)); + return; + } + + switch (parser->eatName()) + { + case 0: break; + case 1: syntaxError("invalid char: " + std::string(1, c)); + case 2: syntaxError("invalid utf8 sequence: " + std::string(1, c)); + case 3: syntaxError("@id contains invalid char"); break; + case 4: syntaxError("invalid JSON token"); break; + default: UNREACHABLE(); } return; } @@ -1028,21 +1041,19 @@ __LISTCOMP: /***** Error Reporter *****/ _Str getLineSnapshot(){ int lineno = parser->current.line; + const char* cursor = parser->current.start; + // if error occurs in lexing, lineno should be `parser->current_line` + if(lexingCnt > 0){ + lineno = parser->current_line; + cursor = parser->current_char; + } if(parser->peekChar() == '\n') lineno--; - return parser->src->snapshot(lineno); + return parser->src->snapshot(lineno, cursor); } - void syntaxError(_Str msg){ - throw CompileError("SyntaxError", msg, getLineSnapshot()); - } - - void indentationError(_Str msg){ - throw CompileError("IndentationError", msg, getLineSnapshot()); - } - - void unexpectedError(_Str msg){ - throw CompileError("UnexpectedError", msg, getLineSnapshot()); - } + void syntaxError(_Str msg){ throw CompileError("SyntaxError", msg, getLineSnapshot()); } + void indentationError(_Str msg){ throw CompileError("IndentationError", msg, getLineSnapshot()); } + void unexpectedError(_Str msg){ throw CompileError("UnexpectedError", msg, getLineSnapshot()); } }; _Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) { diff --git a/src/error.h b/src/error.h index c28ceb04..7994d1fd 100644 --- a/src/error.h +++ b/src/error.h @@ -21,14 +21,14 @@ struct SourceMetadata { std::vector lineStarts; CompileMode mode; - _Str getLine(int lineno) const { - if(lineno == -1) return ""; + std::pair getLine(int lineno) const { + if(lineno == -1) return {nullptr, nullptr}; lineno -= 1; if(lineno < 0) lineno = 0; const char* _start = lineStarts.at(lineno); const char* i = _start; while(*i != '\n' && *i != '\0') i++; - return _Str(_start, i-_start); + return {_start, i}; } SourceMetadata(const char* source, _Str filename, CompileMode mode) { @@ -41,12 +41,24 @@ struct SourceMetadata { this->mode = mode; } - _Str snapshot(int lineno){ + _Str snapshot(int lineno, const char* cursor=nullptr){ _StrStream ss; ss << " " << "File \"" << filename << "\", line " << lineno << '\n'; - _Str line = getLine(lineno).__lstrip(); - if(line.empty()) line = ""; + std::pair pair = getLine(lineno); + _Str line = ""; + int removedSpaces = 0; + if(pair.first && pair.second){ + line = _Str(pair.first, pair.second-pair.first).__lstrip(); + removedSpaces = pair.second - pair.first - line.size(); + if(line.empty()) line = ""; + } ss << " " << line << '\n'; + if(cursor && line != "" && cursor >= pair.first && cursor <= pair.second){ + int column = cursor - pair.first - removedSpaces; + if(column >= 0){ + ss << " " << std::string(column, ' ') << "^\n"; + } + } return ss.str(); } diff --git a/src/parser.h b/src/parser.h index 2d69f5b8..269de0bd 100644 --- a/src/parser.h +++ b/src/parser.h @@ -179,12 +179,6 @@ struct Parser { return c; } - inline bool isNameStart(char c){ - if(isalpha(c) || c=='_') return true; - if(!isascii(c)) return true; - return false; - } - int eatName() { current_char--; while(true){ diff --git a/tests/dna2.py b/tests/dna2.py new file mode 100644 index 00000000..dd511ce5 --- /dev/null +++ b/tests/dna2.py @@ -0,0 +1,185 @@ +import random + +def f(x): + if x >= 5 : + return x+5 + else : + return -x+5 + +def create_init_DNA(min,max): +# out: DNA(['0','1',....]) + ret = random.randint(min,max) + return int_to_bin(ret) + +def int_to_bin(x): +# in: int_DNA(int) +# out: DNA + ret = [] + if x >= 0: + ret.append(0) + else: + ret.append(1) + x = -x + for i in [32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1] : + if x>=i : + ret.append(1) + x -= i + else : + ret.append(0) + return ret + +def bin_to_int(x): +# in: DNA +# out: int_DNA(int) + ret = 0 + new_x = x[:] + flag = -(int(new_x[0])*2-1) + mul = 1 + new_x = reversed(new_x) + new_x.pop() + for i in new_x : + ret += flag * int(i) * mul + mul *= 2 + return ret + +def reversed(x): + ret = [] + for i in range(0,len(x)): + ret.append(x[-i-1]) + return ret + +def create_DNAs(num,min,max): +# in: num(int) +# out: DNAs([DNA,DNA,...]) + ret = [] + for i in range(num): + ret.append(create_init_DNA(min,max)) + return ret + +def bins_to_ints(x): +# in: DNAs +# out: int_DNAs([int,int,...]) + ret = [] + for i in x: + ret.append(bin_to_int(i)) + return ret + +def ints_to_bins(x): +# in: int_DNAs +# out: DNAs + ret = [] + for i in x: + ret.append(int_to_bin(i)) + return ret + +def create_probabilitys(x): +# in: DNAs +# out: probabilitys([float,float...]) + scores = survival_scores(x) + mid = [] + ret = [] + sum = 0 + for i in scores: + sum+=i + for i in scores: + mid.append(1/(i+0.0/sum)) + sum = 0 + for i in mid: + sum+=i + for i in mid: + ret.append(i/sum) + return ret + +def survival_scores(x): +# in: DNAs +# out: survival_scores[f(int_DNA),...] + ret = [] + for i in x: + ret.append(f(bin_to_int(i)/100)) + return ret + +def choose_DNA(DNAs,probabilitys): +# in: DNAs,probabilitys +# out: choosen_DNA(DNA) +# probabilitys是由若干(0,1)之间的浮点数组成的数组,这些浮点数的和为1 + i = 0 # i记录取出元素的位置 + ran = random.random() + max_sum = 0 + for max in probabilitys : + max_sum += max + if i != 0 : + min_sum += probabilitys[i-1] + else : + min_sum = 0 + if (ran < max_sum) and (ran >= min_sum) : + return DNAs[i] + i += 1 + +def mating_DNAs(DNAs,num=None): +# in: DNAs,num(int)交配组DNA数量 +# out: mating_DNAs(DNAs)交配组 + num = num or len(DNAs) + ret = [] + for i in range(num) : + ret.append(choose_DNA(DNAs,create_probabilitys(DNAs))) + return ret + +def son_DNA(DNAs): +# in: mating_DNAs(DNAs)交配组 +# out: son_DNA(DNA)交叉互换后产生的子代 + father = DNAs[random.randint(0,len(DNAs)-1)] + mother = DNAs[random.randint(0,len(DNAs)-1)] + pos = random.randint(0,len(DNAs[0])-1) + son_DNA = [] + son_DNA += father[0:pos] + son_DNA += mother[pos+1:-1] + return son_DNA + +def mutation(DNA,part_rate): +# in: son_DNA(DNA)交叉互换后的子代,part_rate(float)碱基对变异概率 +# out: mut_DNA(DNA)变异后的子代 + ret = DNA[:] + for i in range(len(ret)): + k = random.random() + if k < part_rate : + ret[i] = str(-int(ret[i])+1) + return ret + +def next_DNAs(DNAs,father_rate,part_rate,mut_rate,num): +# in: mating_DNAs(DNAs),father_rate(float)父代保留占比,part_rate(float)碱基对突变概率,mut_rate(float)生物变异概率,num(int)下一代数量 +# out: next_DNAs(DNAs) + ret = [] + pro_DNAs = create_probabilitys(DNAs) + father_num = int(father_rate*num+0.5) + son_num = num - father_num + i = 1 + for pro in reversed(sorted(pro_DNAs)): + if i > father_num: + break + ret.append(DNAs[pro_DNAs.index(pro)]) + i += 1 + for s in range(son_num): + k = random.random() + son_DNA=(mating_DNAs(DNAs)[0]) + if k < mut_rate : + son_DNA = mutation(son_DNA,part_rate) + ret.append(son_DNA) + return ret + +def iterate(DNAs,father_rate,part_rate,mut_rate,iter_num,population): +# in: DNAs父代,father_rate(float)每一次迭代保留父代的占比, num(int)迭代次数,population(int)种群数量 +# out: DNAs子代 + ret = eval(repr(DNAs)) + for i in range(iter_num): + ret = next_DNAs(ret,father_rate,part_rate,mut_rate,population) + return ret + + +def 百分比化(a): + b = str(a*100)[0:5] + return f'{b}%' + +a = create_DNAs(5,-9999,9999) + + +