mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
add with and from import
This commit is contained in:
parent
5a2d389c22
commit
3d84156a19
@ -664,7 +664,7 @@ __LISTCOMP:
|
|||||||
return tkmodule;
|
return tkmodule;
|
||||||
}
|
}
|
||||||
|
|
||||||
// import module1 [as alias1 [, module2 [as alias2 ...]]
|
// import a as b
|
||||||
void compileRegularImport() {
|
void compileRegularImport() {
|
||||||
do {
|
do {
|
||||||
Token tkmodule = compileImportPath();
|
Token tkmodule = compileImportPath();
|
||||||
@ -678,6 +678,25 @@ __LISTCOMP:
|
|||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from a import b as c, d as e
|
||||||
|
void compileFromImport() {
|
||||||
|
Token tkmodule = compileImportPath();
|
||||||
|
consume(TK("import"));
|
||||||
|
do {
|
||||||
|
consume(TK("@id"));
|
||||||
|
Token tkname = parser->previous;
|
||||||
|
int index = getCode()->addName(tkname.str(), NAME_GLOBAL);
|
||||||
|
emitCode(OP_BUILD_ATTR_PTR, index);
|
||||||
|
if (match(TK("as"))) {
|
||||||
|
consume(TK("@id"));
|
||||||
|
tkname = parser->previous;
|
||||||
|
}
|
||||||
|
index = getCode()->addName(tkname.str(), NAME_GLOBAL);
|
||||||
|
emitCode(OP_STORE_NAME_PTR, index);
|
||||||
|
} while (match(TK(",")));
|
||||||
|
consumeEndStatement();
|
||||||
|
}
|
||||||
|
|
||||||
void parsePrecedence(Precedence precedence) {
|
void parsePrecedence(Precedence precedence) {
|
||||||
lexToken();
|
lexToken();
|
||||||
GrammarFn prefix = rules[parser->previous.type].prefix;
|
GrammarFn prefix = rules[parser->previous.type].prefix;
|
||||||
@ -786,6 +805,21 @@ __LISTCOMP:
|
|||||||
EXPR();
|
EXPR();
|
||||||
emitCode(OP_ASSERT);
|
emitCode(OP_ASSERT);
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
|
} else if(match(TK("with"))){
|
||||||
|
EXPR();
|
||||||
|
consume(TK("as"));
|
||||||
|
consume(TK("@id"));
|
||||||
|
Token tkname = parser->previous;
|
||||||
|
int index = getCode()->addName(
|
||||||
|
tkname.str(),
|
||||||
|
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
|
||||||
|
);
|
||||||
|
emitCode(OP_STORE_NAME_PTR, index);
|
||||||
|
emitCode(OP_LOAD_NAME_PTR, index);
|
||||||
|
emitCode(OP_WITH_ENTER);
|
||||||
|
compileBlockBody();
|
||||||
|
emitCode(OP_LOAD_NAME_PTR, index);
|
||||||
|
emitCode(OP_WITH_EXIT);
|
||||||
} else if(match(TK("label"))){
|
} else if(match(TK("label"))){
|
||||||
if(mode() != EXEC_MODE) syntaxError("'label' is only available in EXEC_MODE");
|
if(mode() != EXEC_MODE) syntaxError("'label' is only available in EXEC_MODE");
|
||||||
consume(TK(".")); consume(TK("@id"));
|
consume(TK(".")); consume(TK("@id"));
|
||||||
@ -926,6 +960,8 @@ __LISTCOMP:
|
|||||||
compileFunction();
|
compileFunction();
|
||||||
} else if (match(TK("import"))) {
|
} else if (match(TK("import"))) {
|
||||||
compileRegularImport();
|
compileRegularImport();
|
||||||
|
} else if (match(TK("from"))) {
|
||||||
|
compileFromImport();
|
||||||
} else {
|
} else {
|
||||||
compileStatement();
|
compileStatement();
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ const _Int _Int_MAX_NEG = -9223372036854775807LL;
|
|||||||
const _Float _FLOAT_INF_POS = INFINITY;
|
const _Float _FLOAT_INF_POS = INFINITY;
|
||||||
const _Float _FLOAT_INF_NEG = -INFINITY;
|
const _Float _FLOAT_INF_NEG = -INFINITY;
|
||||||
|
|
||||||
#define PK_VERSION "0.3.5"
|
#define PK_VERSION "0.3.6"
|
||||||
|
|
||||||
class CodeObject;
|
class CodeObject;
|
||||||
class BasePointer;
|
class BasePointer;
|
||||||
|
@ -63,4 +63,7 @@ OPCODE(GOTO)
|
|||||||
OPCODE(UNARY_REF) // for &
|
OPCODE(UNARY_REF) // for &
|
||||||
OPCODE(UNARY_DEREF) // for *
|
OPCODE(UNARY_DEREF) // for *
|
||||||
|
|
||||||
|
OPCODE(WITH_ENTER)
|
||||||
|
OPCODE(WITH_EXIT)
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -12,7 +12,7 @@ constexpr const char* __TOKENS[] = {
|
|||||||
"==", "!=", ">=", "<=",
|
"==", "!=", ">=", "<=",
|
||||||
"+=", "-=", "*=", "/=", "//=",
|
"+=", "-=", "*=", "/=", "//=",
|
||||||
/** KW_BEGIN **/
|
/** KW_BEGIN **/
|
||||||
"class", "import", "as", "def", "lambda", "pass", "del",
|
"class", "import", "as", "def", "lambda", "pass", "del", "from", "with",
|
||||||
"None", "in", "is", "and", "or", "not", "True", "False", "global",
|
"None", "in", "is", "and", "or", "not", "True", "False", "global",
|
||||||
"goto", "label", // extended keywords, not available in cpython
|
"goto", "label", // extended keywords, not available in cpython
|
||||||
"while", "for", "if", "elif", "else", "break", "continue", "return", "assert", "raise",
|
"while", "for", "if", "elif", "else", "break", "continue", "return", "assert", "raise",
|
||||||
|
@ -404,11 +404,18 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindMethod("str", "join", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("str", "join", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkArgSize(args, 2, true);
|
vm->__checkArgSize(args, 2, true);
|
||||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||||
const PyVarList& _list = vm->PyList_AS_C(args[1]);
|
PyVarList* _list;
|
||||||
|
if(args[1]->isType(vm->_tp_list)){
|
||||||
|
_list = &vm->PyList_AS_C(args[1]);
|
||||||
|
}else if(args[1]->isType(vm->_tp_tuple)){
|
||||||
|
_list = &vm->PyTuple_AS_C(args[1]);
|
||||||
|
}else{
|
||||||
|
vm->typeError("can only join a list or tuple");
|
||||||
|
}
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
for(int i = 0; i < _list.size(); i++){
|
for(int i = 0; i < _list->size(); i++){
|
||||||
if(i > 0) ss << _self;
|
if(i > 0) ss << _self;
|
||||||
ss << vm->PyStr_AS_C(vm->asStr(_list[i]));
|
ss << vm->PyStr_AS_C(vm->asStr(_list->operator[](i)));
|
||||||
}
|
}
|
||||||
return vm->PyStr(ss.str());
|
return vm->PyStr(ss.str());
|
||||||
});
|
});
|
||||||
|
12
src/vm.h
12
src/vm.h
@ -345,6 +345,18 @@ protected:
|
|||||||
frame->push(it->second);
|
frame->push(it->second);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case OP_WITH_ENTER:
|
||||||
|
{
|
||||||
|
PyVar obj = frame->popValue(this);
|
||||||
|
PyVar enter_fn = getAttr(obj, "__enter__"_c);
|
||||||
|
call(enter_fn, {});
|
||||||
|
} break;
|
||||||
|
case OP_WITH_EXIT:
|
||||||
|
{
|
||||||
|
PyVar obj = frame->popValue(this);
|
||||||
|
PyVar exit_fn = getAttr(obj, "__exit__"_c);
|
||||||
|
call(exit_fn, {});
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
systemError(_Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
|
systemError(_Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
|
||||||
break;
|
break;
|
||||||
|
@ -48,6 +48,10 @@ seq = ["r","u","n","o","o","b"]
|
|||||||
assert s1.join( seq ) == "r-u-n-o-o-b"
|
assert s1.join( seq ) == "r-u-n-o-o-b"
|
||||||
assert s2.join( seq ) == "runoob"
|
assert s2.join( seq ) == "runoob"
|
||||||
|
|
||||||
|
def test(*seq):
|
||||||
|
return s1.join(seq)
|
||||||
|
assert test("r", "u", "n", "o", "o", "b") == "r-u-n-o-o-b"
|
||||||
|
|
||||||
|
|
||||||
##num = 6
|
##num = 6
|
||||||
##assert str(num) == '6' TypeError: 'str' object is not callable
|
##assert str(num) == '6' TypeError: 'str' object is not callable
|
||||||
|
@ -1,6 +1,26 @@
|
|||||||
import random
|
import random as r, sys as s
|
||||||
|
|
||||||
for _ in range(100):
|
for _ in range(100):
|
||||||
i = random.randint(1, 10)
|
i = r.randint(1, 10)
|
||||||
assert i <= 10
|
assert i <= 10
|
||||||
assert i >= 1
|
assert i >= 1
|
||||||
|
|
||||||
|
|
||||||
|
from sys import version as v
|
||||||
|
|
||||||
|
assert type(v) is str
|
||||||
|
|
||||||
|
class Context:
|
||||||
|
def __init__(self):
|
||||||
|
self.x = 0
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.x = 1
|
||||||
|
|
||||||
|
def __exit__(self):
|
||||||
|
self.x = 2
|
||||||
|
|
||||||
|
with Context() as c:
|
||||||
|
assert c.x == 1
|
||||||
|
|
||||||
|
assert c.x == 2
|
Loading…
x
Reference in New Issue
Block a user