mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
move str.join | add partial support of tuple
This commit is contained in:
parent
daf192b356
commit
a4dc943c7b
@ -4,20 +4,11 @@ const char* __BUILTINS_CODE = R"(
|
|||||||
def len(x):
|
def len(x):
|
||||||
return x.__len__()
|
return x.__len__()
|
||||||
|
|
||||||
def __str4join(self, seq):
|
|
||||||
s = ""
|
|
||||||
for i in seq:
|
|
||||||
s += str(i) + self # in Python3, it uses 'i' instead of 'str(i)'
|
|
||||||
if len(self) > 0:
|
|
||||||
s = s[:-len(self)]
|
|
||||||
return s
|
|
||||||
str.join = __str4join
|
|
||||||
|
|
||||||
def __str4__mul__(self, n):
|
def __str4__mul__(self, n):
|
||||||
s = ""
|
a = []
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
s += self
|
a.append(self)
|
||||||
return s
|
return ''.join(a)
|
||||||
str.__mul__ = __str4__mul__
|
str.__mul__ = __str4__mul__
|
||||||
|
|
||||||
def __str4split(self, sep):
|
def __str4split(self, sep):
|
||||||
@ -40,9 +31,16 @@ def __list4__str__(self):
|
|||||||
a = []
|
a = []
|
||||||
for i in self:
|
for i in self:
|
||||||
a.append(str(i))
|
a.append(str(i))
|
||||||
return "[" + ", ".join(a) + "]"
|
return '[' + ', '.join(a) + ']'
|
||||||
list.__str__ = __list4__str__
|
list.__str__ = __list4__str__
|
||||||
|
|
||||||
|
def __tuple4__str__(self):
|
||||||
|
a = []
|
||||||
|
for i in self:
|
||||||
|
a.append(str(i))
|
||||||
|
return '(' + ', '.join(a) + ')'
|
||||||
|
tuple.__str__ = __tuple4__str__
|
||||||
|
|
||||||
def __list4extend(self, other):
|
def __list4extend(self, other):
|
||||||
for i in other:
|
for i in other:
|
||||||
self.append(i)
|
self.append(i)
|
||||||
@ -91,7 +89,7 @@ class dict:
|
|||||||
if self._a[i][0] == key:
|
if self._a[i][0] == key:
|
||||||
return [True, i]
|
return [True, i]
|
||||||
i = ((5*i) + 1) % self._capacity
|
i = ((5*i) + 1) % self._capacity
|
||||||
return [False, i]
|
return False,i
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
ret = self.__probe(key)
|
ret = self.__probe(key)
|
||||||
|
@ -72,39 +72,39 @@ public:
|
|||||||
|
|
||||||
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
|
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
|
||||||
#define METHOD(name) &Compiler::name
|
#define METHOD(name) &Compiler::name
|
||||||
#define NO_INFIX PREC_NONE
|
#define NO_INFIX nullptr, PREC_NONE
|
||||||
for(_TokenType i=0; i<__TOKENS_LEN; i++) rules[i] = { nullptr, nullptr, PREC_NONE };
|
for(_TokenType i=0; i<__TOKENS_LEN; i++) rules[i] = { nullptr, NO_INFIX };
|
||||||
rules[TK(".")] = { nullptr, METHOD(exprAttrib), PREC_ATTRIB };
|
rules[TK(".")] = { nullptr, METHOD(exprAttrib), PREC_ATTRIB };
|
||||||
rules[TK("(")] = { METHOD(exprGrouping), METHOD(exprCall), PREC_CALL };
|
rules[TK("(")] = { METHOD(exprGrouping), METHOD(exprCall), PREC_CALL };
|
||||||
rules[TK("[")] = { METHOD(exprList), METHOD(exprSubscript), PREC_SUBSCRIPT };
|
rules[TK("[")] = { METHOD(exprList), METHOD(exprSubscript), PREC_SUBSCRIPT };
|
||||||
rules[TK("{")] = { METHOD(exprMap), nullptr, NO_INFIX };
|
rules[TK("{")] = { METHOD(exprMap), NO_INFIX };
|
||||||
rules[TK("%")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
rules[TK("%")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
||||||
rules[TK("+")] = { nullptr, METHOD(exprBinaryOp), PREC_TERM };
|
rules[TK("+")] = { nullptr, METHOD(exprBinaryOp), PREC_TERM };
|
||||||
rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM };
|
rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM };
|
||||||
rules[TK("*")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
rules[TK("*")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
||||||
rules[TK("/")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
rules[TK("/")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
||||||
rules[TK("//")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
rules[TK("//")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
||||||
rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT };
|
rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT };
|
||||||
rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY };
|
rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY };
|
||||||
rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY };
|
rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY };
|
||||||
rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("lambda")] = { METHOD(exprLambda), nullptr, NO_INFIX };
|
rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||||
rules[TK("None")] = { METHOD(exprValue), nullptr, NO_INFIX };
|
rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||||
rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||||
rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
||||||
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND };
|
||||||
rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR };
|
||||||
rules[TK("and")] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND };
|
rules[TK("not")] = { METHOD(exprUnaryOp), nullptr, PREC_UNARY };
|
||||||
rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR };
|
rules[TK("True")] = { METHOD(exprValue), NO_INFIX };
|
||||||
rules[TK("not")] = { METHOD(exprUnaryOp), nullptr, PREC_UNARY };
|
rules[TK("False")] = { METHOD(exprValue), NO_INFIX };
|
||||||
rules[TK("True")] = { METHOD(exprValue), nullptr, NO_INFIX };
|
rules[TK("lambda")] = { METHOD(exprLambda), NO_INFIX };
|
||||||
rules[TK("False")] = { METHOD(exprValue), nullptr, NO_INFIX };
|
rules[TK("None")] = { METHOD(exprValue), NO_INFIX };
|
||||||
rules[TK("@id")] = { METHOD(exprName), nullptr, NO_INFIX };
|
rules[TK("@id")] = { METHOD(exprName), NO_INFIX };
|
||||||
rules[TK("@num")] = { METHOD(exprLiteral), nullptr, NO_INFIX };
|
rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX };
|
||||||
rules[TK("@str")] = { METHOD(exprLiteral), nullptr, NO_INFIX };
|
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
|
||||||
#undef METHOD
|
#undef METHOD
|
||||||
#undef NO_INFIX
|
#undef NO_INFIX
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ public:
|
|||||||
_TokenType assignment = parser->previous.type;
|
_TokenType assignment = parser->previous.type;
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
if (assignment == TK("=")) { // name = (expr);
|
if (assignment == TK("=")) { // name = (expr);
|
||||||
compileExpression();
|
compileExpressionTuple();
|
||||||
} else { // name += / -= / *= ... = (expr);
|
} else { // name += / -= / *= ... = (expr);
|
||||||
emitCode(OP_LOAD_NAME, index);
|
emitCode(OP_LOAD_NAME, index);
|
||||||
compileExpression();
|
compileExpression();
|
||||||
@ -392,7 +392,7 @@ public:
|
|||||||
|
|
||||||
void exprGrouping() {
|
void exprGrouping() {
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
compileExpression();
|
compileExpressionTuple();
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
consume(TK(")"));
|
consume(TK(")"));
|
||||||
}
|
}
|
||||||
@ -442,7 +442,7 @@ public:
|
|||||||
compileExpression();
|
compileExpression();
|
||||||
emitAssignOp(assignment);
|
emitAssignOp(assignment);
|
||||||
} else {
|
} else {
|
||||||
compileExpression();
|
compileExpressionTuple();
|
||||||
}
|
}
|
||||||
emitCode(OP_STORE_ATTR, index);
|
emitCode(OP_STORE_ATTR, index);
|
||||||
} else {
|
} else {
|
||||||
@ -488,7 +488,7 @@ public:
|
|||||||
if (assignment != TK("=")) {
|
if (assignment != TK("=")) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
} else {
|
} else {
|
||||||
compileExpression();
|
compileExpressionTuple();
|
||||||
}
|
}
|
||||||
emitCode(OP_STORE_SUBSCR);
|
emitCode(OP_STORE_SUBSCR);
|
||||||
} else {
|
} else {
|
||||||
@ -593,6 +593,17 @@ public:
|
|||||||
parsePrecedence(PREC_LOWEST);
|
parsePrecedence(PREC_LOWEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compiles an expression. Support tuple syntax.
|
||||||
|
void compileExpressionTuple() {
|
||||||
|
int size = 0;
|
||||||
|
while (true) {
|
||||||
|
compileExpression();
|
||||||
|
size++;
|
||||||
|
if (!match(TK(","))) break;
|
||||||
|
}
|
||||||
|
if(size > 1) emitCode(OP_BUILD_TUPLE, size);
|
||||||
|
}
|
||||||
|
|
||||||
void compileIfStatement() {
|
void compileIfStatement() {
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
compileExpression(); //< Condition.
|
compileExpression(); //< Condition.
|
||||||
@ -642,7 +653,7 @@ public:
|
|||||||
const _Str& iterName = parser->previous.str();
|
const _Str& iterName = parser->previous.str();
|
||||||
int iterIndex = getCode()->addName(iterName);
|
int iterIndex = getCode()->addName(iterName);
|
||||||
consume(TK("in"));
|
consume(TK("in"));
|
||||||
compileExpression();
|
compileExpressionTuple();
|
||||||
emitCode(OP_GET_ITER);
|
emitCode(OP_GET_ITER);
|
||||||
Loop& loop = enterLoop(true);
|
Loop& loop = enterLoop(true);
|
||||||
int patch = emitCode(OP_FOR_ITER);
|
int patch = emitCode(OP_FOR_ITER);
|
||||||
@ -672,7 +683,7 @@ public:
|
|||||||
if(matchEndStatement()){
|
if(matchEndStatement()){
|
||||||
emitCode(OP_LOAD_NONE);
|
emitCode(OP_LOAD_NONE);
|
||||||
}else{
|
}else{
|
||||||
compileExpression();
|
compileExpressionTuple();
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
}
|
}
|
||||||
emitCode(OP_RETURN_VALUE);
|
emitCode(OP_RETURN_VALUE);
|
||||||
@ -706,7 +717,7 @@ public:
|
|||||||
} else if(match(TK("pass"))){
|
} else if(match(TK("pass"))){
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
} else {
|
} else {
|
||||||
compileExpression();
|
compileExpressionTuple();
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
|
|
||||||
// If last op is not an assignment, pop the result.
|
// If last op is not an assignment, pop the result.
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include "pocketpy.h"
|
#include "pocketpy.h"
|
||||||
|
|
||||||
//#define PK_DEBUG
|
#define PK_DEBUG
|
||||||
//#define PK_DEBUG_TIME
|
//#define PK_DEBUG_TIME
|
||||||
|
|
||||||
class Timer{
|
class Timer{
|
||||||
|
@ -26,7 +26,7 @@ constexpr const char* __TOKENS[] = {
|
|||||||
|
|
||||||
const _TokenType __TOKENS_LEN = sizeof(__TOKENS) / sizeof(__TOKENS[0]);
|
const _TokenType __TOKENS_LEN = sizeof(__TOKENS) / sizeof(__TOKENS[0]);
|
||||||
|
|
||||||
constexpr _TokenType __tokenIndex(const char* token) {
|
constexpr _TokenType TK(const char* const token) {
|
||||||
for(int k=0; k<__TOKENS_LEN; k++){
|
for(int k=0; k<__TOKENS_LEN; k++){
|
||||||
const char* i = __TOKENS[k];
|
const char* i = __TOKENS[k];
|
||||||
const char* j = token;
|
const char* j = token;
|
||||||
@ -38,12 +38,10 @@ constexpr _TokenType __tokenIndex(const char* token) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define TK(s) __tokenIndex(s)
|
|
||||||
#define TK_STR(t) __TOKENS[t]
|
#define TK_STR(t) __TOKENS[t]
|
||||||
|
|
||||||
const _TokenType __KW_BEGIN = __tokenIndex("class");
|
const _TokenType __KW_BEGIN = TK("class");
|
||||||
const _TokenType __KW_END = __tokenIndex("raise");
|
const _TokenType __KW_END = TK("raise");
|
||||||
|
|
||||||
const std::unordered_map<std::string_view, _TokenType> __KW_MAP = [](){
|
const std::unordered_map<std::string_view, _TokenType> __KW_MAP = [](){
|
||||||
std::unordered_map<std::string_view, _TokenType> map;
|
std::unordered_map<std::string_view, _TokenType> map;
|
||||||
|
@ -277,6 +277,17 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
return vm->PyBool(_self.str().rfind(_suffix.str()) == _self.str().length() - _suffix.str().length());
|
return vm->PyBool(_self.str().rfind(_suffix.str()) == _self.str().length() - _suffix.str().length());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_vm->bindMethod("str", "join", [](VM* vm, PyVarList args) {
|
||||||
|
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
||||||
|
const PyVarList& _list = vm->PyList_AS_C(args[1]);
|
||||||
|
_StrStream ss;
|
||||||
|
for(int i = 0; i < _list.size(); i++){
|
||||||
|
if(i > 0) ss << _self;
|
||||||
|
ss << vm->PyStr_AS_C(vm->asStr(_list[i]));
|
||||||
|
}
|
||||||
|
return vm->PyStr(ss);
|
||||||
|
});
|
||||||
|
|
||||||
/************ PyList ************/
|
/************ PyList ************/
|
||||||
_vm->bindMethod("list", "__iter__", [](VM* vm, PyVarList args) {
|
_vm->bindMethod("list", "__iter__", [](VM* vm, PyVarList args) {
|
||||||
vm->__checkType(args.at(0), vm->_tp_list);
|
vm->__checkType(args.at(0), vm->_tp_list);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user