mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
some fix
This commit is contained in:
parent
18fe69d579
commit
79012a6b08
@ -38,13 +38,7 @@ enum BindType {
|
||||
BindType_CLASSMETHOD,
|
||||
};
|
||||
|
||||
enum CompileMode {
|
||||
EXEC_MODE,
|
||||
EVAL_MODE,
|
||||
REPL_MODE,
|
||||
JSON_MODE,
|
||||
CELL_MODE
|
||||
};
|
||||
enum CompileMode { EXEC_MODE, EVAL_MODE, REPL_MODE, JSON_MODE, CELL_MODE };
|
||||
|
||||
/************* Global VMs *************/
|
||||
void py_initialize();
|
||||
@ -294,7 +288,9 @@ bool py_callmethod(py_Ref self, py_Name, int argc, py_Ref argv);
|
||||
bool py_callmagic(py_Name name, int argc, py_Ref argv);
|
||||
|
||||
bool py_str(py_Ref val);
|
||||
bool py_repr(py_Ref val);
|
||||
|
||||
#define py_repr(val) py_callmagic(__repr__, 1, val)
|
||||
#define py_len(val) py_callmagic(__len__, 1, val)
|
||||
|
||||
/// The return value of the most recent call.
|
||||
py_GlobalRef py_retval();
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "pocketpy/objects/sourcedata.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/strname.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/common/config.h"
|
||||
#include "pocketpy/common/memorypool.h"
|
||||
#include <ctype.h>
|
||||
@ -2348,6 +2349,124 @@ static Error* compile_function(Compiler* self, int decorators) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* compile_decorated(Compiler* self) {
|
||||
Error* err;
|
||||
int count = 0;
|
||||
do {
|
||||
check(EXPR(self));
|
||||
count += 1;
|
||||
if(!match_newlines()) return SyntaxError("expected a newline after '@'");
|
||||
} while(match(TK_DECORATOR));
|
||||
|
||||
if(match(TK_CLASS)) {
|
||||
// check(compile_class(count));
|
||||
} else {
|
||||
consume(TK_DEF);
|
||||
check(compile_function(self, count));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// import a [as b]
|
||||
// import a [as b], c [as d]
|
||||
static Error* compile_normal_import(Compiler* self) {
|
||||
do {
|
||||
consume(TK_ID);
|
||||
c11_sv name = Token__sv(prev());
|
||||
int index = Ctx__add_const_string(ctx(), name);
|
||||
Ctx__emit_(ctx(), OP_IMPORT_PATH, index, prev()->line);
|
||||
if(match(TK_AS)) {
|
||||
consume(TK_ID);
|
||||
name = Token__sv(prev());
|
||||
}
|
||||
Ctx__emit_store_name(ctx(), name_scope(self), py_name2(name), prev()->line);
|
||||
} while(match(TK_COMMA));
|
||||
consume_end_stmt();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// from a import b [as c], d [as e]
|
||||
// from a.b import c [as d]
|
||||
// from . import a [as b]
|
||||
// from .a import b [as c]
|
||||
// from ..a import b [as c]
|
||||
// from .a.b import c [as d]
|
||||
// from xxx import *
|
||||
static Error* compile_from_import(c11_sbuf* buf, Compiler* self) {
|
||||
int dots = 0;
|
||||
|
||||
while(true) {
|
||||
switch(curr()->type) {
|
||||
case TK_DOT: dots += 1; break;
|
||||
case TK_DOTDOT: dots += 2; break;
|
||||
case TK_DOTDOTDOT: dots += 3; break;
|
||||
default: goto __EAT_DOTS_END;
|
||||
}
|
||||
advance();
|
||||
}
|
||||
__EAT_DOTS_END:
|
||||
for(int i = 0; i < dots; i++) {
|
||||
c11_sbuf__write_char(buf, '.');
|
||||
}
|
||||
|
||||
if(dots > 0) {
|
||||
// @id is optional if dots > 0
|
||||
if(match(TK_ID)) {
|
||||
c11_sbuf__write_sv(buf, Token__sv(prev()));
|
||||
while(match(TK_DOT)) {
|
||||
consume(TK_ID);
|
||||
c11_sbuf__write_char(buf, '.');
|
||||
c11_sbuf__write_sv(buf, Token__sv(prev()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// @id is required if dots == 0
|
||||
consume(TK_ID);
|
||||
c11_sbuf__write_sv(buf, Token__sv(prev()));
|
||||
while(match(TK_DOT)) {
|
||||
consume(TK_ID);
|
||||
c11_sbuf__write_char(buf, '.');
|
||||
c11_sbuf__write_sv(buf, Token__sv(prev()));
|
||||
}
|
||||
}
|
||||
|
||||
c11_string* path = c11_sbuf__submit(buf);
|
||||
Ctx__emit_(ctx(),
|
||||
OP_IMPORT_PATH,
|
||||
Ctx__add_const_string(ctx(), c11_string__sv(path)),
|
||||
prev()->line);
|
||||
consume(TK_IMPORT);
|
||||
|
||||
if(match(TK_MUL)) {
|
||||
if(name_scope(self) != NAME_GLOBAL)
|
||||
return SyntaxError("from <module> import * can only be used in global scope");
|
||||
// pop the module and import __all__
|
||||
Ctx__emit_(ctx(), OP_POP_IMPORT_STAR, BC_NOARG, prev()->line);
|
||||
consume_end_stmt();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
consume(TK_ID);
|
||||
c11_sv name = Token__sv(prev());
|
||||
Ctx__emit_(ctx(), OP_LOAD_ATTR, py_name2(name), prev()->line);
|
||||
if(match(TK_AS)) {
|
||||
consume(TK_ID);
|
||||
name = Token__sv(prev());
|
||||
}
|
||||
Ctx__emit_store_name(ctx(), name_scope(self), py_name2(name), prev()->line);
|
||||
} while(match(TK_COMMA));
|
||||
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||
consume_end_stmt();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* compile_try_except(Compiler* self) {
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* compile_stmt(Compiler* self) {
|
||||
Error* err;
|
||||
if(match(TK_CLASS)) {
|
||||
@ -2402,11 +2521,18 @@ static Error* compile_stmt(Compiler* self) {
|
||||
case TK_IF: check(compile_if_stmt(self)); break;
|
||||
case TK_WHILE: check(compile_while_loop(self)); break;
|
||||
case TK_FOR: check(compile_for_loop(self)); break;
|
||||
// case TK_IMPORT: check(compile_normal_import()); break;
|
||||
// case TK_FROM: check(compile_from_import()); break;
|
||||
case TK_IMPORT: check(compile_normal_import(self)); break;
|
||||
case TK_FROM: {
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
err = compile_from_import(&buf, self);
|
||||
c11_sbuf__dtor(&buf);
|
||||
if(err) return err;
|
||||
break;
|
||||
}
|
||||
case TK_DEF: check(compile_function(self, 0)); break;
|
||||
// case TK_DECORATOR: check(compile_decorated()); break;
|
||||
// case TK_TRY: check(compile_try_except()); break;
|
||||
case TK_DECORATOR: check(compile_decorated(self)); break;
|
||||
case TK_TRY: check(compile_try_except(self)); break;
|
||||
case TK_PASS: consume_end_stmt(); break;
|
||||
/*************************************************/
|
||||
case TK_ASSERT: {
|
||||
|
@ -70,10 +70,16 @@ static bool _py_builtins__exit(int argc, py_Ref argv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool _py_builtins__len(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
return py_len(argv);
|
||||
}
|
||||
|
||||
py_TValue pk_builtins__register() {
|
||||
py_Ref builtins = py_newmodule("builtins", NULL);
|
||||
py_bindnativefunc(builtins, "repr", _py_builtins__repr);
|
||||
py_bindnativefunc(builtins, "exit", _py_builtins__exit);
|
||||
py_bindnativefunc(builtins, "len", _py_builtins__len);
|
||||
return *builtins;
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,15 @@ static bool _py_str__str__(int argc, py_Ref argv) {
|
||||
|
||||
static bool _py_str__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
assert(false);
|
||||
return false;
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
int size;
|
||||
const char* data = py_tostrn(&argv[0], &size);
|
||||
c11_sbuf__write_quoted(&buf, (c11_sv){data, size}, '\'');
|
||||
c11_string* res = c11_sbuf__submit(&buf);
|
||||
py_newstrn(py_retval(), res->data, res->size);
|
||||
c11_string__delete(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _py_str__iter__(int argc, py_Ref argv) {
|
||||
@ -294,5 +301,3 @@ bool py_str(py_Ref val) {
|
||||
if(!tmp) return py_repr(val);
|
||||
return py_call(tmp, 1, val);
|
||||
}
|
||||
|
||||
bool py_repr(py_Ref val) { return py_callmagic(__repr__, 1, val); }
|
153
tests/04_str.py
153
tests/04_str.py
@ -44,7 +44,6 @@ assert s.replace("foo","ball") == "balltball"
|
||||
assert s.startswith('f') == True;assert s.endswith('o') == False
|
||||
assert t.startswith('this') == True;
|
||||
|
||||
|
||||
assert t.split('w') == ['this is string example....', 'o', '!!!']
|
||||
assert "a,b,c".split(',') == ['a', 'b', 'c']
|
||||
assert 'a,'.split(',') == ['a']
|
||||
@ -110,29 +109,9 @@ num = 6
|
||||
assert str(num) == '6'
|
||||
|
||||
# test Lo group names
|
||||
|
||||
测试 = "test"
|
||||
assert 测试 == "test"
|
||||
|
||||
assert "Hello, {}!".format("World") == "Hello, World!"
|
||||
assert "{} {} {}".format("I", "love", "Python") == "I love Python"
|
||||
assert "{0} {1} {2}".format("I", "love", "Python") == "I love Python"
|
||||
assert "{2} {1} {0}".format("I", "love", "Python") == "Python love I"
|
||||
assert "{0}{1}{0}".format("abra", "cad") == "abracadabra"
|
||||
|
||||
assert "{k}={v}".format(k="key", v="value") == "key=value"
|
||||
assert "{k}={k}".format(k="key") == "key=key"
|
||||
assert "{0}={1}".format('{0}', '{1}') == "{0}={1}"
|
||||
assert "{{{0}}}".format(1) == "{1}"
|
||||
assert "{0}{1}{1}".format(1, 2, 3) == "122"
|
||||
try:
|
||||
"{0}={1}}".format(1, 2)
|
||||
exit(1)
|
||||
except ValueError:
|
||||
pass
|
||||
assert "{{{}xxx{}x}}".format(1, 2) == "{1xxx2x}"
|
||||
assert "{{abc}}".format() == "{abc}"
|
||||
|
||||
# 3rd slice
|
||||
a = "Hello, World!"
|
||||
assert a[::-1] == "!dlroW ,olleH"
|
||||
@ -152,20 +131,35 @@ assert b[5:2:-2] == [',', 'l']
|
||||
a = '123'
|
||||
assert a.rjust(5) == ' 123'
|
||||
assert a.rjust(5, '0') == '00123'
|
||||
try:
|
||||
a.rjust(5, '00')
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
assert a.ljust(5) == '123 '
|
||||
assert a.ljust(5, '0') == '12300'
|
||||
try:
|
||||
a.ljust(5, '00')
|
||||
exit(1)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
assert '\x30\x31\x32' == '012'
|
||||
assert '\b\b\b' == '\x08\x08\x08'
|
||||
assert repr('\x1f\x1e\x1f') == '\'\\x1f\\x1e\\x1f\''
|
||||
|
||||
assert hex(-42) == '-0x2a'
|
||||
assert hex(42) == '0x2a'
|
||||
|
||||
assert hex(0) == '0x0'
|
||||
assert hex(1) == '0x1'
|
||||
assert hex(15) == '0xf'
|
||||
assert hex(16) == '0x10'
|
||||
assert hex(255) == '0xff'
|
||||
assert hex(256) == '0x100'
|
||||
assert hex(257) == '0x101'
|
||||
assert hex(17) == '0x11'
|
||||
|
||||
a = '123'
|
||||
assert a.index('2') == 1
|
||||
assert a.index('1') == 0
|
||||
assert a.index('3') == 2
|
||||
|
||||
assert a.index('2', 1) == 1
|
||||
assert a.index('1', 0) == 0
|
||||
|
||||
assert a.find('1') == 0
|
||||
assert a.find('1', 1) == -1
|
||||
|
||||
a = 'abcd'
|
||||
assert list(a) == ['a', 'b', 'c', 'd']
|
||||
@ -184,78 +178,27 @@ assert list(a) == ['b']
|
||||
a = '测'
|
||||
assert list(a) == ['测']
|
||||
|
||||
assert '\b\b\b' == '\x08\x08\x08'
|
||||
# test format()
|
||||
assert "Hello, {}!".format("World") == "Hello, World!"
|
||||
assert "{} {} {}".format("I", "love", "Python") == "I love Python"
|
||||
assert "{0} {1} {2}".format("I", "love", "Python") == "I love Python"
|
||||
assert "{2} {1} {0}".format("I", "love", "Python") == "Python love I"
|
||||
assert "{0}{1}{0}".format("abra", "cad") == "abracadabra"
|
||||
|
||||
assert "{k}={v}".format(k="key", v="value") == "key=value"
|
||||
assert "{k}={k}".format(k="key") == "key=key"
|
||||
assert "{0}={1}".format('{0}', '{1}') == "{0}={1}"
|
||||
assert "{{{0}}}".format(1) == "{1}"
|
||||
assert "{0}{1}{1}".format(1, 2, 3) == "122"
|
||||
|
||||
# try:
|
||||
# "{0}={1}}".format(1, 2)
|
||||
# exit(1)
|
||||
# except ValueError:
|
||||
# pass
|
||||
|
||||
assert "{{{}xxx{}x}}".format(1, 2) == "{1xxx2x}"
|
||||
assert "{{abc}}".format() == "{abc}"
|
||||
|
||||
# test f-string
|
||||
stack=[1,2,3,4]; assert f"{stack[2:]}" == '[3, 4]'
|
||||
|
||||
assert repr('\x1f\x1e\x1f') == '\'\\x1f\\x1e\\x1f\''
|
||||
|
||||
|
||||
assert hex(-42) == '-0x2a'
|
||||
assert hex(42) == '0x2a'
|
||||
|
||||
assert hex(0) == '0x0'
|
||||
assert hex(1) == '0x1'
|
||||
assert hex(15) == '0xf'
|
||||
assert hex(16) == '0x10'
|
||||
assert hex(255) == '0xff'
|
||||
assert hex(256) == '0x100'
|
||||
assert hex(257) == '0x101'
|
||||
assert hex(17) == '0x11'
|
||||
|
||||
import c
|
||||
assert repr(c.NULL) == '<void* at 0x0>'
|
||||
assert repr(c.void_p(1)) == '<void* at 0x1>'
|
||||
assert repr(c.void_p(15)) == '<void* at 0xf>'
|
||||
assert repr(c.void_p(16)) == '<void* at 0x10>'
|
||||
assert repr(c.void_p(255)) == '<void* at 0xff>'
|
||||
assert repr(c.void_p(256)) == '<void* at 0x100>'
|
||||
assert repr(c.void_p(257)) == '<void* at 0x101>'
|
||||
assert repr(c.void_p(17)) == '<void* at 0x11>'
|
||||
|
||||
# random hex test
|
||||
import random
|
||||
|
||||
|
||||
def test(__min, __max):
|
||||
for _ in range(100):
|
||||
num = random.randint(__min, __max)
|
||||
hex_num = hex(num)
|
||||
assert eval(hex_num) == num
|
||||
if num >= 0:
|
||||
assert repr(c.void_p(num)) == f'<void* at 0x{hex_num[2:]}>'
|
||||
|
||||
test(0, 100)
|
||||
test(0, 100000)
|
||||
test(-100, 100)
|
||||
test(-100000, 100000)
|
||||
test(-2**30, 2**30)
|
||||
|
||||
|
||||
a = '123'
|
||||
assert a.index('2') == 1
|
||||
assert a.index('1') == 0
|
||||
assert a.index('3') == 2
|
||||
|
||||
assert a.index('2', 1) == 1
|
||||
assert a.index('1', 0) == 0
|
||||
|
||||
try:
|
||||
a.index('1', 1)
|
||||
exit(1)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
try:
|
||||
a.index('1', -1)
|
||||
exit(1)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
assert a.find('1') == 0
|
||||
assert a.find('1', 1) == -1
|
||||
|
||||
try:
|
||||
a.find('1', -1)
|
||||
exit(1)
|
||||
except ValueError:
|
||||
pass
|
||||
|
Loading…
x
Reference in New Issue
Block a user