mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 20:10:17 +00:00
up
This commit is contained in:
parent
83ad8274ef
commit
229a836444
@ -17,6 +17,7 @@ The initial version. Hello, world!
|
|||||||
+ Fix a bug about comment and indentation
|
+ Fix a bug about comment and indentation
|
||||||
+ Fix a bug about compile error line number
|
+ Fix a bug about compile error line number
|
||||||
|
|
||||||
## 0.4.8+3
|
## 0.4.8+4
|
||||||
|
|
||||||
+ Downgrade to `sdk>=2.17.0`
|
+ Downgrade to `sdk>=2.17.0`
|
||||||
|
+ Fix some bugs about compile error
|
@ -1,6 +1,6 @@
|
|||||||
name: pocketpy
|
name: pocketpy
|
||||||
description: A lightweight Python interpreter for game engines.
|
description: A lightweight Python interpreter for game engines.
|
||||||
version: 0.4.8+3
|
version: 0.4.8+4
|
||||||
homepage: https://pocketpy.dev
|
homepage: https://pocketpy.dev
|
||||||
repository: https://github.com/blueloveth/pocketpy
|
repository: https://github.com/blueloveth/pocketpy
|
||||||
|
|
||||||
|
@ -2904,14 +2904,14 @@ struct SourceMetadata {
|
|||||||
std::vector<const char*> lineStarts;
|
std::vector<const char*> lineStarts;
|
||||||
CompileMode mode;
|
CompileMode mode;
|
||||||
|
|
||||||
_Str getLine(int lineno) const {
|
std::pair<const char*,const char*> getLine(int lineno) const {
|
||||||
if(lineno == -1) return "<?>";
|
if(lineno == -1) return {nullptr, nullptr};
|
||||||
lineno -= 1;
|
lineno -= 1;
|
||||||
if(lineno < 0) lineno = 0;
|
if(lineno < 0) lineno = 0;
|
||||||
const char* _start = lineStarts.at(lineno);
|
const char* _start = lineStarts.at(lineno);
|
||||||
const char* i = _start;
|
const char* i = _start;
|
||||||
while(*i != '\n' && *i != '\0') i++;
|
while(*i != '\n' && *i != '\0') i++;
|
||||||
return _Str(_start, i-_start);
|
return {_start, i};
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMetadata(const char* source, _Str filename, CompileMode mode) {
|
SourceMetadata(const char* source, _Str filename, CompileMode mode) {
|
||||||
@ -2924,12 +2924,24 @@ struct SourceMetadata {
|
|||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Str snapshot(int lineno){
|
_Str snapshot(int lineno, const char* cursor=nullptr){
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
|
ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
|
||||||
_Str line = getLine(lineno).__lstrip();
|
std::pair<const char*,const char*> pair = getLine(lineno);
|
||||||
if(line.empty()) line = "<?>";
|
_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';
|
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();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3301,12 +3313,6 @@ struct Parser {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isNameStart(char c){
|
|
||||||
if(isalpha(c) || c=='_') return true;
|
|
||||||
if(!isascii(c)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int eatName() {
|
int eatName() {
|
||||||
current_char--;
|
current_char--;
|
||||||
while(true){
|
while(true){
|
||||||
@ -5090,6 +5096,7 @@ public:
|
|||||||
std::stack<_Code> codes;
|
std::stack<_Code> codes;
|
||||||
std::stack<Loop> loops;
|
std::stack<Loop> loops;
|
||||||
bool isCompilingClass = false;
|
bool isCompilingClass = false;
|
||||||
|
int lexingCnt = 0;
|
||||||
VM* vm;
|
VM* vm;
|
||||||
|
|
||||||
emhash8::HashMap<_TokenType, GrammarRule> rules;
|
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.
|
// Lex the next token and set it as the next token.
|
||||||
void lexToken() {
|
void _lexToken() {
|
||||||
parser->previous = parser->current;
|
parser->previous = parser->current;
|
||||||
parser->current = parser->nextToken();
|
parser->current = parser->nextToken();
|
||||||
|
|
||||||
@ -5324,11 +5337,17 @@ public:
|
|||||||
}
|
}
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
eatNumber();
|
eatNumber();
|
||||||
} else if (parser->isNameStart(c)) {
|
return;
|
||||||
int ret = parser->eatName();
|
}
|
||||||
if(ret!=0) syntaxError("@id is illegal, err " + std::to_string(ret));
|
|
||||||
} else {
|
switch (parser->eatName())
|
||||||
syntaxError("unknown character: " + std::string(1, c));
|
{
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -6091,21 +6110,19 @@ __LISTCOMP:
|
|||||||
/***** Error Reporter *****/
|
/***** Error Reporter *****/
|
||||||
_Str getLineSnapshot(){
|
_Str getLineSnapshot(){
|
||||||
int lineno = parser->current.line;
|
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--;
|
if(parser->peekChar() == '\n') lineno--;
|
||||||
return parser->src->snapshot(lineno);
|
return parser->src->snapshot(lineno, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syntaxError(_Str msg){
|
void syntaxError(_Str msg){ throw CompileError("SyntaxError", msg, getLineSnapshot()); }
|
||||||
throw CompileError("SyntaxError", msg, getLineSnapshot());
|
void indentationError(_Str msg){ throw CompileError("IndentationError", msg, getLineSnapshot()); }
|
||||||
}
|
void unexpectedError(_Str msg){ throw CompileError("UnexpectedError", 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) {
|
_Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 70637fe5198a3dc5d130781987b3cf2b46de3efc
|
Subproject commit c645191b67d056996ee4d0d6a387758c16edf7e2
|
@ -2904,14 +2904,14 @@ struct SourceMetadata {
|
|||||||
std::vector<const char*> lineStarts;
|
std::vector<const char*> lineStarts;
|
||||||
CompileMode mode;
|
CompileMode mode;
|
||||||
|
|
||||||
_Str getLine(int lineno) const {
|
std::pair<const char*,const char*> getLine(int lineno) const {
|
||||||
if(lineno == -1) return "<?>";
|
if(lineno == -1) return {nullptr, nullptr};
|
||||||
lineno -= 1;
|
lineno -= 1;
|
||||||
if(lineno < 0) lineno = 0;
|
if(lineno < 0) lineno = 0;
|
||||||
const char* _start = lineStarts.at(lineno);
|
const char* _start = lineStarts.at(lineno);
|
||||||
const char* i = _start;
|
const char* i = _start;
|
||||||
while(*i != '\n' && *i != '\0') i++;
|
while(*i != '\n' && *i != '\0') i++;
|
||||||
return _Str(_start, i-_start);
|
return {_start, i};
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMetadata(const char* source, _Str filename, CompileMode mode) {
|
SourceMetadata(const char* source, _Str filename, CompileMode mode) {
|
||||||
@ -2924,12 +2924,24 @@ struct SourceMetadata {
|
|||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Str snapshot(int lineno){
|
_Str snapshot(int lineno, const char* cursor=nullptr){
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
|
ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
|
||||||
_Str line = getLine(lineno).__lstrip();
|
std::pair<const char*,const char*> pair = getLine(lineno);
|
||||||
if(line.empty()) line = "<?>";
|
_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';
|
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();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3301,12 +3313,6 @@ struct Parser {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isNameStart(char c){
|
|
||||||
if(isalpha(c) || c=='_') return true;
|
|
||||||
if(!isascii(c)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int eatName() {
|
int eatName() {
|
||||||
current_char--;
|
current_char--;
|
||||||
while(true){
|
while(true){
|
||||||
@ -5090,6 +5096,7 @@ public:
|
|||||||
std::stack<_Code> codes;
|
std::stack<_Code> codes;
|
||||||
std::stack<Loop> loops;
|
std::stack<Loop> loops;
|
||||||
bool isCompilingClass = false;
|
bool isCompilingClass = false;
|
||||||
|
int lexingCnt = 0;
|
||||||
VM* vm;
|
VM* vm;
|
||||||
|
|
||||||
emhash8::HashMap<_TokenType, GrammarRule> rules;
|
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.
|
// Lex the next token and set it as the next token.
|
||||||
void lexToken() {
|
void _lexToken() {
|
||||||
parser->previous = parser->current;
|
parser->previous = parser->current;
|
||||||
parser->current = parser->nextToken();
|
parser->current = parser->nextToken();
|
||||||
|
|
||||||
@ -5324,11 +5337,17 @@ public:
|
|||||||
}
|
}
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
eatNumber();
|
eatNumber();
|
||||||
} else if (parser->isNameStart(c)) {
|
return;
|
||||||
int ret = parser->eatName();
|
}
|
||||||
if(ret!=0) syntaxError("@id is illegal, err " + std::to_string(ret));
|
|
||||||
} else {
|
switch (parser->eatName())
|
||||||
syntaxError("unknown character: " + std::string(1, c));
|
{
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -6091,21 +6110,19 @@ __LISTCOMP:
|
|||||||
/***** Error Reporter *****/
|
/***** Error Reporter *****/
|
||||||
_Str getLineSnapshot(){
|
_Str getLineSnapshot(){
|
||||||
int lineno = parser->current.line;
|
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--;
|
if(parser->peekChar() == '\n') lineno--;
|
||||||
return parser->src->snapshot(lineno);
|
return parser->src->snapshot(lineno, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syntaxError(_Str msg){
|
void syntaxError(_Str msg){ throw CompileError("SyntaxError", msg, getLineSnapshot()); }
|
||||||
throw CompileError("SyntaxError", msg, getLineSnapshot());
|
void indentationError(_Str msg){ throw CompileError("IndentationError", msg, getLineSnapshot()); }
|
||||||
}
|
void unexpectedError(_Str msg){ throw CompileError("UnexpectedError", 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) {
|
_Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) {
|
||||||
|
@ -27,6 +27,7 @@ public:
|
|||||||
std::stack<_Code> codes;
|
std::stack<_Code> codes;
|
||||||
std::stack<Loop> loops;
|
std::stack<Loop> loops;
|
||||||
bool isCompilingClass = false;
|
bool isCompilingClass = false;
|
||||||
|
int lexingCnt = 0;
|
||||||
VM* vm;
|
VM* vm;
|
||||||
|
|
||||||
emhash8::HashMap<_TokenType, GrammarRule> rules;
|
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.
|
// Lex the next token and set it as the next token.
|
||||||
void lexToken() {
|
void _lexToken() {
|
||||||
parser->previous = parser->current;
|
parser->previous = parser->current;
|
||||||
parser->current = parser->nextToken();
|
parser->current = parser->nextToken();
|
||||||
|
|
||||||
@ -261,11 +268,17 @@ public:
|
|||||||
}
|
}
|
||||||
if (isdigit(c)) {
|
if (isdigit(c)) {
|
||||||
eatNumber();
|
eatNumber();
|
||||||
} else if (parser->isNameStart(c)) {
|
return;
|
||||||
int ret = parser->eatName();
|
}
|
||||||
if(ret!=0) syntaxError("@id is illegal, err " + std::to_string(ret));
|
|
||||||
} else {
|
switch (parser->eatName())
|
||||||
syntaxError("unknown character: " + std::string(1, c));
|
{
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -1028,21 +1041,19 @@ __LISTCOMP:
|
|||||||
/***** Error Reporter *****/
|
/***** Error Reporter *****/
|
||||||
_Str getLineSnapshot(){
|
_Str getLineSnapshot(){
|
||||||
int lineno = parser->current.line;
|
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--;
|
if(parser->peekChar() == '\n') lineno--;
|
||||||
return parser->src->snapshot(lineno);
|
return parser->src->snapshot(lineno, cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void syntaxError(_Str msg){
|
void syntaxError(_Str msg){ throw CompileError("SyntaxError", msg, getLineSnapshot()); }
|
||||||
throw CompileError("SyntaxError", msg, getLineSnapshot());
|
void indentationError(_Str msg){ throw CompileError("IndentationError", msg, getLineSnapshot()); }
|
||||||
}
|
void unexpectedError(_Str msg){ throw CompileError("UnexpectedError", 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) {
|
_Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_MODE, bool noThrow=true) {
|
||||||
|
24
src/error.h
24
src/error.h
@ -21,14 +21,14 @@ struct SourceMetadata {
|
|||||||
std::vector<const char*> lineStarts;
|
std::vector<const char*> lineStarts;
|
||||||
CompileMode mode;
|
CompileMode mode;
|
||||||
|
|
||||||
_Str getLine(int lineno) const {
|
std::pair<const char*,const char*> getLine(int lineno) const {
|
||||||
if(lineno == -1) return "<?>";
|
if(lineno == -1) return {nullptr, nullptr};
|
||||||
lineno -= 1;
|
lineno -= 1;
|
||||||
if(lineno < 0) lineno = 0;
|
if(lineno < 0) lineno = 0;
|
||||||
const char* _start = lineStarts.at(lineno);
|
const char* _start = lineStarts.at(lineno);
|
||||||
const char* i = _start;
|
const char* i = _start;
|
||||||
while(*i != '\n' && *i != '\0') i++;
|
while(*i != '\n' && *i != '\0') i++;
|
||||||
return _Str(_start, i-_start);
|
return {_start, i};
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceMetadata(const char* source, _Str filename, CompileMode mode) {
|
SourceMetadata(const char* source, _Str filename, CompileMode mode) {
|
||||||
@ -41,12 +41,24 @@ struct SourceMetadata {
|
|||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Str snapshot(int lineno){
|
_Str snapshot(int lineno, const char* cursor=nullptr){
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
|
ss << " " << "File \"" << filename << "\", line " << lineno << '\n';
|
||||||
_Str line = getLine(lineno).__lstrip();
|
std::pair<const char*,const char*> pair = getLine(lineno);
|
||||||
if(line.empty()) line = "<?>";
|
_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';
|
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();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,12 +179,6 @@ struct Parser {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isNameStart(char c){
|
|
||||||
if(isalpha(c) || c=='_') return true;
|
|
||||||
if(!isascii(c)) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int eatName() {
|
int eatName() {
|
||||||
current_char--;
|
current_char--;
|
||||||
while(true){
|
while(true){
|
||||||
|
185
tests/dna2.py
Normal file
185
tests/dna2.py
Normal file
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user