mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
cdbd884398
commit
06068ab3e0
@ -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.
|
||||
|
||||
|
@ -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 .<identifier>
|
||||
label .<identifier>
|
||||
$goto <identifier>
|
||||
$label <identifier>
|
||||
```
|
||||
|
||||
## Example
|
||||
@ -22,7 +20,7 @@ label .<identifier>
|
||||
for i in range(10):
|
||||
for j in range(10):
|
||||
for k in range(10):
|
||||
goto .exit
|
||||
$goto exit
|
||||
|
||||
label .exit
|
||||
$label exit
|
||||
```
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
26
src/lexer.h
26
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<s_len; i++) eatchar_include_newline();
|
||||
return ok;
|
||||
}
|
||||
|
||||
int eat_spaces(){
|
||||
int count = 0;
|
||||
while (true) {
|
||||
@ -381,6 +383,16 @@ struct Lexer {
|
||||
case '[': add_token(TK("[")); return true;
|
||||
case ']': add_token(TK("]")); return true;
|
||||
case '@': add_token(TK("@")); return true;
|
||||
case '$': {
|
||||
for(int i=TK("$goto"); i<=TK("$label"); i++){
|
||||
// +1 to skip the '$'
|
||||
if(match_string(TK_STR(i) + 1)){
|
||||
add_token((TokenIndex)i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
SyntaxError("invalid special token");
|
||||
}
|
||||
case '%': add_token_2('=', TK("%"), TK("%=")); return true;
|
||||
case '&': add_token_2('=', TK("&"), TK("&=")); return true;
|
||||
case '|': add_token_2('=', TK("|"), TK("|=")); return true;
|
||||
|
@ -72,11 +72,6 @@ inline void init_builtins(VM* _vm) {
|
||||
#undef BIND_NUM_ARITH_OPT
|
||||
#undef BIND_NUM_LOGICAL_OPT
|
||||
|
||||
_vm->bind_builtin_func<1>("__sys_stdout_write", [](VM* vm, ArgsView args) {
|
||||
(*vm->_stdout) << CAST(Str&, args[0]);
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind_builtin_func<2>("super", [](VM* vm, ArgsView args) {
|
||||
vm->check_non_tagged_type(args[0], vm->tp_type);
|
||||
Type type = OBJ_GET(Type, args[0]);
|
||||
@ -768,6 +763,21 @@ inline void add_module_time(VM* vm){
|
||||
inline void add_module_sys(VM* vm){
|
||||
PyObject* mod = vm->new_module("sys");
|
||||
vm->setattr(mod, "version", VAR(PK_VERSION));
|
||||
|
||||
PyObject* stdout = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
||||
PyObject* stderr = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
||||
vm->setattr(mod, "stdout", stdout);
|
||||
vm->setattr(mod, "stderr", stderr);
|
||||
|
||||
vm->bind_func<1>(stdout, "write", [](VM* vm, ArgsView args) {
|
||||
(*vm->_stdout) << CAST(Str&, args[0]).sv();
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
vm->bind_func<1>(stderr, "write", [](VM* vm, ArgsView args) {
|
||||
(*vm->_stderr) << CAST(Str&, args[0]).sv();
|
||||
return vm->None;
|
||||
});
|
||||
}
|
||||
|
||||
inline void add_module_json(VM* vm){
|
||||
|
@ -2,9 +2,9 @@ a = []
|
||||
|
||||
for i in range(10): # [0]
|
||||
for j in range(10): # [0-0]
|
||||
goto .test
|
||||
$goto test
|
||||
print(2)
|
||||
label .test
|
||||
$label test
|
||||
a.append(i)
|
||||
for k in range(5): # [0-1]
|
||||
for t in range(7): # [0-1-0]
|
||||
@ -16,7 +16,7 @@ b = False
|
||||
|
||||
for i in range(10): # [1]
|
||||
for j in range(10): # [1-0]
|
||||
goto .out
|
||||
$goto out
|
||||
b = True
|
||||
label .out
|
||||
$label out
|
||||
assert not b
|
Loading…
x
Reference in New Issue
Block a user