From 06068ab3e07a66d9017b97da28754ceee13d062a Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Wed, 3 May 2023 21:43:37 +0800 Subject: [PATCH] ... --- docs/features/basic.md | 4 +--- docs/features/goto.md | 10 ++++------ python/builtins.py | 4 +++- src/ceval.h | 2 +- src/compiler.h | 9 ++++----- src/lexer.h | 26 +++++++++++++++++++------- src/pocketpy.h | 20 +++++++++++++++----- tests/27_goto.py | 8 ++++---- 8 files changed, 51 insertions(+), 32 deletions(-) diff --git a/docs/features/basic.md b/docs/features/basic.md index 04312fa0..3f8b3fd0 100644 --- a/docs/features/basic.md +++ b/docs/features/basic.md @@ -1,11 +1,9 @@ --- icon: dot -order: 100 title: Basic Features +order: 100 --- -# basic - The following table shows the basic features of pkpy with respect to [cpython](https://github.com/python/cpython). The features marked with `YES` are supported, and the features marked with `NO` are not supported. diff --git a/docs/features/goto.md b/docs/features/goto.md index e694ae43..1bbc8f3d 100644 --- a/docs/features/goto.md +++ b/docs/features/goto.md @@ -3,8 +3,6 @@ icon: dot title: Goto Statement --- -# goto/label - pkpy supports `goto` and `label` just like C. You are allowed to change the control flow unconditionally. ## Syntax @@ -12,8 +10,8 @@ pkpy supports `goto` and `label` just like C. You are allowed to change the cont Labels are named a dot `.` and an identifier. ``` -goto . -label . +$goto +$label ``` ## Example @@ -22,7 +20,7 @@ label . for i in range(10): for j in range(10): for k in range(10): - goto .exit + $goto exit -label .exit +$label exit ``` diff --git a/python/builtins.py b/python/builtins.py index ddce6c49..a3275a6d 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -1,6 +1,8 @@ +import sys as _sys + def print(*args, sep=' ', end='\n'): s = sep.join([str(i) for i in args]) - __sys_stdout_write(s + end) + _sys.stdout.write(s + end) def round(x, ndigits=0): assert ndigits >= 0 diff --git a/src/ceval.h b/src/ceval.h index 969a886a..7b1d08e0 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -501,7 +501,7 @@ __NEXT_STEP:; TOP()->attr().set(_name, _0); DISPATCH(); /*****************************************/ - // // TODO: using "goto" inside with block may cause __exit__ not called + // TODO: using "goto" inside with block may cause __exit__ not called TARGET(WITH_ENTER) call_method(POPX(), __enter__); DISPATCH(); diff --git a/src/compiler.h b/src/compiler.h index 8a98486b..6e930394 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -795,17 +795,16 @@ __SUBSCR_END: ctx()->emit(OP_WITH_EXIT, BC_NOARG, prev().line); } break; /*************************************************/ - // TODO: refactor goto/label use special $ syntax - case TK("label"): { + case TK("$label"): { if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE"); - consume(TK(".")); consume(TK("@id")); + consume(TK("@id")); bool ok = ctx()->add_label(prev().str()); if(!ok) SyntaxError("label " + prev().str().escape() + " already exists"); consume_end_stmt(); } break; - case TK("goto"): + case TK("$goto"): if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE"); - consume(TK(".")); consume(TK("@id")); + consume(TK("@id")); ctx()->emit(OP_GOTO, StrName(prev().str()).index, prev().line); consume_end_stmt(); break; diff --git a/src/lexer.h b/src/lexer.h index 270c7c1d..db105087 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -21,10 +21,11 @@ constexpr const char* kTokens[] = { /*****************************************/ ".", ",", ":", ";", "#", "(", ")", "[", "]", "{", "}", "**", "=", ">", "<", "...", "->", "?", "@", "==", "!=", ">=", "<=", + /** SPEC_BEGIN **/ + "$goto", "$label", /** KW_BEGIN **/ "class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield", "None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally", - "goto", "label", // extended keywords, not available in cpython "while", "for", "if", "elif", "else", "break", "continue", "return", "assert", "raise" }; @@ -38,13 +39,7 @@ constexpr TokenIndex TK(const char token[]) { while(*i && *j && *i == *j) { i++; j++;} if(*i == *j) return k; } -#ifdef __GNUC__ - // for old version of gcc, it is not smart enough to ignore FATAL_ERROR() - // so we must do a normal return return 255; -#else - FATAL_ERROR(); -#endif } #define TK_STR(t) kTokens[t] @@ -125,6 +120,13 @@ struct Lexer { return true; } + bool match_string(const char* s){ + int s_len = strlen(s); + bool ok = strncmp(curr_char, s, s_len) == 0; + if(ok) for(int i=0; i