move str.join | add partial support of tuple

This commit is contained in:
blueloveTH 2022-11-06 15:48:28 +08:00
parent daf192b356
commit a4dc943c7b
5 changed files with 78 additions and 60 deletions

View File

@ -4,20 +4,11 @@ const char* __BUILTINS_CODE = R"(
def len(x):
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):
s = ""
a = []
for i in range(n):
s += self
return s
a.append(self)
return ''.join(a)
str.__mul__ = __str4__mul__
def __str4split(self, sep):
@ -40,9 +31,16 @@ def __list4__str__(self):
a = []
for i in self:
a.append(str(i))
return "[" + ", ".join(a) + "]"
return '[' + ', '.join(a) + ']'
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):
for i in other:
self.append(i)
@ -91,7 +89,7 @@ class dict:
if self._a[i][0] == key:
return [True, i]
i = ((5*i) + 1) % self._capacity
return [False, i]
return False,i
def __getitem__(self, key):
ret = self.__probe(key)

View File

@ -72,12 +72,12 @@ public:
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
#define METHOD(name) &Compiler::name
#define NO_INFIX PREC_NONE
for(_TokenType i=0; i<__TOKENS_LEN; i++) rules[i] = { nullptr, nullptr, PREC_NONE };
#define NO_INFIX 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("(")] = { METHOD(exprGrouping), METHOD(exprCall), PREC_CALL };
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_TERM };
rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM };
@ -91,8 +91,6 @@ public:
rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY };
rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
rules[TK("lambda")] = { METHOD(exprLambda), nullptr, NO_INFIX };
rules[TK("None")] = { METHOD(exprValue), nullptr, NO_INFIX };
rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
@ -100,11 +98,13 @@ public:
rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND };
rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR };
rules[TK("not")] = { METHOD(exprUnaryOp), nullptr, PREC_UNARY };
rules[TK("True")] = { METHOD(exprValue), nullptr, NO_INFIX };
rules[TK("False")] = { METHOD(exprValue), nullptr, NO_INFIX };
rules[TK("@id")] = { METHOD(exprName), nullptr, NO_INFIX };
rules[TK("@num")] = { METHOD(exprLiteral), nullptr, NO_INFIX };
rules[TK("@str")] = { METHOD(exprLiteral), nullptr, NO_INFIX };
rules[TK("True")] = { METHOD(exprValue), NO_INFIX };
rules[TK("False")] = { METHOD(exprValue), NO_INFIX };
rules[TK("lambda")] = { METHOD(exprLambda), NO_INFIX };
rules[TK("None")] = { METHOD(exprValue), NO_INFIX };
rules[TK("@id")] = { METHOD(exprName), NO_INFIX };
rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX };
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
#undef METHOD
#undef NO_INFIX
}
@ -313,7 +313,7 @@ public:
_TokenType assignment = parser->previous.type;
matchNewLines();
if (assignment == TK("=")) { // name = (expr);
compileExpression();
compileExpressionTuple();
} else { // name += / -= / *= ... = (expr);
emitCode(OP_LOAD_NAME, index);
compileExpression();
@ -392,7 +392,7 @@ public:
void exprGrouping() {
matchNewLines();
compileExpression();
compileExpressionTuple();
matchNewLines();
consume(TK(")"));
}
@ -442,7 +442,7 @@ public:
compileExpression();
emitAssignOp(assignment);
} else {
compileExpression();
compileExpressionTuple();
}
emitCode(OP_STORE_ATTR, index);
} else {
@ -488,7 +488,7 @@ public:
if (assignment != TK("=")) {
UNREACHABLE();
} else {
compileExpression();
compileExpressionTuple();
}
emitCode(OP_STORE_SUBSCR);
} else {
@ -593,6 +593,17 @@ public:
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() {
matchNewLines();
compileExpression(); //< Condition.
@ -642,7 +653,7 @@ public:
const _Str& iterName = parser->previous.str();
int iterIndex = getCode()->addName(iterName);
consume(TK("in"));
compileExpression();
compileExpressionTuple();
emitCode(OP_GET_ITER);
Loop& loop = enterLoop(true);
int patch = emitCode(OP_FOR_ITER);
@ -672,7 +683,7 @@ public:
if(matchEndStatement()){
emitCode(OP_LOAD_NONE);
}else{
compileExpression();
compileExpressionTuple();
consumeEndStatement();
}
emitCode(OP_RETURN_VALUE);
@ -706,7 +717,7 @@ public:
} else if(match(TK("pass"))){
consumeEndStatement();
} else {
compileExpression();
compileExpressionTuple();
consumeEndStatement();
// If last op is not an assignment, pop the result.

View File

@ -4,7 +4,7 @@
#include <chrono>
#include "pocketpy.h"
//#define PK_DEBUG
#define PK_DEBUG
//#define PK_DEBUG_TIME
class Timer{

View File

@ -26,7 +26,7 @@ constexpr const char* __TOKENS[] = {
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++){
const char* i = __TOKENS[k];
const char* j = token;
@ -38,12 +38,10 @@ constexpr _TokenType __tokenIndex(const char* token) {
return 0;
}
#define TK(s) __tokenIndex(s)
#define TK_STR(t) __TOKENS[t]
const _TokenType __KW_BEGIN = __tokenIndex("class");
const _TokenType __KW_END = __tokenIndex("raise");
const _TokenType __KW_BEGIN = TK("class");
const _TokenType __KW_END = TK("raise");
const std::unordered_map<std::string_view, _TokenType> __KW_MAP = [](){
std::unordered_map<std::string_view, _TokenType> map;

View File

@ -277,6 +277,17 @@ void __initializeBuiltinFunctions(VM* _vm) {
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 ************/
_vm->bindMethod("list", "__iter__", [](VM* vm, PyVarList args) {
vm->__checkType(args.at(0), vm->_tp_list);