blueloveTH há 1 ano atrás
pai
commit
2a84911862

+ 5 - 5
include/pocketpy/common/sstream.h

@@ -22,7 +22,7 @@ typedef struct pk_AnyStr {
         float _float;
         double _double;
         char _char;
-        const pkpy_Str* _str;
+        const py_Str* _str;
         c11_string _sv;
         const char* _cstr;
         void* _ptr;
@@ -34,7 +34,7 @@ PK_INLINE pk_AnyStr pk_AnyStr__i64(int64_t x) { pk_AnyStr s; s.type = 2; s._i64
 PK_INLINE pk_AnyStr pk_AnyStr__float(float x) { pk_AnyStr s; s.type = 3; s._float = x; return s; }
 PK_INLINE pk_AnyStr pk_AnyStr__double(double x) { pk_AnyStr s; s.type = 4; s._double = x; return s; }
 PK_INLINE pk_AnyStr pk_AnyStr__char(char x) { pk_AnyStr s; s.type = 5; s._char = x; return s; }
-PK_INLINE pk_AnyStr pk_AnyStr__str(const pkpy_Str* x) { pk_AnyStr s; s.type = 6; s._str = x; return s; }
+PK_INLINE pk_AnyStr pk_AnyStr__str(const py_Str* x) { pk_AnyStr s; s.type = 6; s._str = x; return s; }
 PK_INLINE pk_AnyStr pk_AnyStr__sv(c11_string x) { pk_AnyStr s; s.type = 7; s._sv = x; return s; }
 PK_INLINE pk_AnyStr pk_AnyStr__cstr(const char* x) { pk_AnyStr s; s.type = 8; s._cstr = x; return s; }
 PK_INLINE pk_AnyStr pk_AnyStr__ptr(void* x) { pk_AnyStr s; s.type = 9; s._ptr = x; return s; }
@@ -48,7 +48,7 @@ void pk_SStream__write_i64(pk_SStream* self, int64_t);
 void pk_SStream__write_float(pk_SStream* self, float, int precision);
 void pk_SStream__write_double(pk_SStream* self, double, int precision);
 void pk_SStream__write_char(pk_SStream* self, char);
-void pk_SStream__write_Str(pk_SStream* self, const pkpy_Str*);
+void pk_SStream__write_Str(pk_SStream* self, const py_Str*);
 void pk_SStream__write_sv(pk_SStream* self, c11_string);
 void pk_SStream__write_cstr(pk_SStream* self, const char*);
 void pk_SStream__write_cstrn(pk_SStream* self, const char*, int);
@@ -59,7 +59,7 @@ void pk_SStream__write_any(pk_SStream* self, const char* fmt, const pk_AnyStr* a
 const char* pk_format_any(const char* fmt, const pk_AnyStr* args, int n);
 
 // Submit the stream and return the final string. The stream becomes invalid after this call
-pkpy_Str pk_SStream__submit(pk_SStream* self);
+py_Str pk_SStream__submit(pk_SStream* self);
 
 #define pk__anystr(x) _Generic((x), \
     int: pk_AnyStr__int, \
@@ -67,7 +67,7 @@ pkpy_Str pk_SStream__submit(pk_SStream* self);
     float: pk_AnyStr__float, \
     double: pk_AnyStr__double, \
     char: pk_AnyStr__char, \
-    const pkpy_Str*: pk_AnyStr__str, \
+    const py_Str*: pk_AnyStr__str, \
     c11_string: pk_AnyStr__sv, \
     const char*: pk_AnyStr__cstr, \
     void*: pk_AnyStr__ptr \

+ 32 - 32
include/pocketpy/common/str.h

@@ -19,7 +19,7 @@ int c11_string__cmp(c11_string self, c11_string other);
 int c11_string__cmp2(c11_string self, const char* other, int size);
 int c11_string__cmp3(c11_string self, const char* other);
 
-typedef struct pkpy_Str{
+typedef struct py_Str{
     int size;
     bool is_ascii;
     bool is_sso;
@@ -27,46 +27,46 @@ typedef struct pkpy_Str{
         char* _ptr;
         char _inlined[16];
     };
-} pkpy_Str;
+} py_Str;
 
-PK_INLINE const char* pkpy_Str__data(const pkpy_Str* self){
+PK_INLINE const char* py_Str__data(const py_Str* self){
     return self->is_sso ? self->_inlined : self->_ptr;
 }
 
-PK_INLINE c11_string pkpy_Str__sv(const pkpy_Str* self){
+PK_INLINE c11_string py_Str__sv(const py_Str* self){
     c11_string retval;
-    retval.data = pkpy_Str__data(self);
+    retval.data = py_Str__data(self);
     retval.size = self->size;
     return retval;
 }
 
-void pkpy_Str__ctor(pkpy_Str* self, const char* data);
-void pkpy_Str__ctor2(pkpy_Str* self, const char* data, int size);
-void pkpy_Str__dtor(pkpy_Str* self);
-pkpy_Str pkpy_Str__copy(const pkpy_Str* self);
-pkpy_Str pkpy_Str__concat(const pkpy_Str* self, const pkpy_Str* other);
-pkpy_Str pkpy_Str__concat2(const pkpy_Str* self, const char* other, int size);
-pkpy_Str pkpy_Str__slice(const pkpy_Str* self, int start);
-pkpy_Str pkpy_Str__slice2(const pkpy_Str* self, int start, int stop);
-pkpy_Str pkpy_Str__lower(const pkpy_Str* self);
-pkpy_Str pkpy_Str__upper(const pkpy_Str* self);
-pkpy_Str pkpy_Str__escape(const pkpy_Str* self, char quote);
-pkpy_Str pkpy_Str__strip(const pkpy_Str* self, bool left, bool right);
-pkpy_Str pkpy_Str__strip2(const pkpy_Str* self, bool left, bool right, const pkpy_Str* chars);
-pkpy_Str pkpy_Str__replace(const pkpy_Str* self, char old, char new_);
-pkpy_Str pkpy_Str__replace2(const pkpy_Str* self, const pkpy_Str* old, const pkpy_Str* new_);
-pkpy_Str pkpy_Str__u8_getitem(const pkpy_Str* self, int i);
-pkpy_Str pkpy_Str__u8_slice(const pkpy_Str* self, int start, int stop, int step);
-int pkpy_Str__u8_length(const pkpy_Str* self);
-int pkpy_Str__cmp(const pkpy_Str* self, const pkpy_Str* other);
-int pkpy_Str__cmp2(const pkpy_Str* self, const char* other, int size);
-int pkpy_Str__cmp3(const pkpy_Str* self, const char* other);
-int pkpy_Str__unicode_index_to_byte(const pkpy_Str* self, int i);
-int pkpy_Str__byte_index_to_unicode(const pkpy_Str* self, int n);
-int pkpy_Str__index(const pkpy_Str* self, const pkpy_Str* sub, int start);
-int pkpy_Str__count(const pkpy_Str* self, const pkpy_Str* sub);
-c11_vector/* T=c11_string */ pkpy_Str__split(const pkpy_Str* self, char sep);
-c11_vector/* T=c11_string */ pkpy_Str__split2(const pkpy_Str* self, const pkpy_Str* sep);
+void py_Str__ctor(py_Str* self, const char* data);
+void py_Str__ctor2(py_Str* self, const char* data, int size);
+void py_Str__dtor(py_Str* self);
+py_Str py_Str__copy(const py_Str* self);
+py_Str py_Str__concat(const py_Str* self, const py_Str* other);
+py_Str py_Str__concat2(const py_Str* self, const char* other, int size);
+py_Str py_Str__slice(const py_Str* self, int start);
+py_Str py_Str__slice2(const py_Str* self, int start, int stop);
+py_Str py_Str__lower(const py_Str* self);
+py_Str py_Str__upper(const py_Str* self);
+py_Str py_Str__escape(const py_Str* self, char quote);
+py_Str py_Str__strip(const py_Str* self, bool left, bool right);
+py_Str py_Str__strip2(const py_Str* self, bool left, bool right, const py_Str* chars);
+py_Str py_Str__replace(const py_Str* self, char old, char new_);
+py_Str py_Str__replace2(const py_Str* self, const py_Str* old, const py_Str* new_);
+py_Str py_Str__u8_getitem(const py_Str* self, int i);
+py_Str py_Str__u8_slice(const py_Str* self, int start, int stop, int step);
+int py_Str__u8_length(const py_Str* self);
+int py_Str__cmp(const py_Str* self, const py_Str* other);
+int py_Str__cmp2(const py_Str* self, const char* other, int size);
+int py_Str__cmp3(const py_Str* self, const char* other);
+int py_Str__unicode_index_to_byte(const py_Str* self, int i);
+int py_Str__byte_index_to_unicode(const py_Str* self, int n);
+int py_Str__index(const py_Str* self, const py_Str* sub, int start);
+int py_Str__count(const py_Str* self, const py_Str* sub);
+c11_vector/* T=c11_string */ py_Str__split(const py_Str* self, char sep);
+c11_vector/* T=c11_string */ py_Str__split2(const py_Str* self, const py_Str* sep);
 
 bool c11__isascii(const char* p, int size);
 bool c11__is_unicode_Lo_char(int c);

+ 1 - 1
include/pocketpy/compiler/lexer.h

@@ -42,7 +42,7 @@ typedef enum TokenIndex{
 void pk_TokenDeserializer__ctor(pk_TokenDeserializer* self, const char* source);
 bool pk_TokenDeserializer__match_char(pk_TokenDeserializer* self, char c);
 c11_string pk_TokenDeserializer__read_string(pk_TokenDeserializer* self, char c);
-pkpy_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self, char c);
+py_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self, char c);
 int pk_TokenDeserializer__read_count(pk_TokenDeserializer* self);
 int64_t pk_TokenDeserializer__read_uint(pk_TokenDeserializer* self, char c);
 double pk_TokenDeserializer__read_float(pk_TokenDeserializer* self, char c);

+ 2 - 2
include/pocketpy/compiler/lexer.hpp

@@ -98,8 +98,8 @@ struct Lexer {
 
     Lexer(VM* vm, std::string_view source, const Str& filename, CompileMode mode) noexcept{
         src = pkpy_SourceData__rcnew({source.data(), (int)source.size()}, &filename, mode);
-        this->token_start = pkpy_Str__data(&src->source);
-        this->curr_char = pkpy_Str__data(&src->source);
+        this->token_start = py_Str__data(&src->source);
+        this->curr_char = py_Str__data(&src->source);
     }
 
     ~Lexer(){

+ 1 - 1
include/pocketpy/objects/codeobject.h

@@ -69,7 +69,7 @@ typedef struct BytecodeEx {
 
 typedef struct CodeObject {
     pkpy_SourceData_ src;
-    pkpy_Str name;
+    py_Str name;
 
     c11_vector/*T=Bytecode*/                codes;
     c11_vector/*T=CodeObjectByteCodeEx*/    codes_ex;

+ 3 - 3
include/pocketpy/objects/error.h

@@ -13,12 +13,12 @@ typedef struct pkpy_ExceptionFrame {
     pkpy_SourceData_ src;
     int lineno;
     const char* cursor;
-    pkpy_Str name;
+    py_Str name;
 } pkpy_ExceptionFrame;
 
 typedef struct pkpy_Exception {
     StrName type;
-    pkpy_Str msg;
+    py_Str msg;
     bool is_re;
 
     int _ip_on_error;
@@ -32,7 +32,7 @@ typedef struct pkpy_Exception {
 void pkpy_Exception__ctor(pkpy_Exception* self, StrName type);
 void pkpy_Exception__dtor(pkpy_Exception* self);
 void pkpy_Exception__stpush(pkpy_Exception* self, pkpy_SourceData_ src, int lineno, const char* cursor, const char* name);
-pkpy_Str pkpy_Exception__summary(pkpy_Exception* self);
+py_Str pkpy_Exception__summary(pkpy_Exception* self);
 
 struct Error{
     const char* type;

+ 6 - 6
include/pocketpy/objects/sourcedata.h

@@ -16,21 +16,21 @@ struct pkpy_SourceData {
     enum CompileMode mode;
     bool is_precompiled;
 
-    pkpy_Str filename;
-    pkpy_Str source;
+    py_Str filename;
+    py_Str source;
 
     c11_vector/*T=const char* */ line_starts;
-    c11_vector/*T=pkpy_Str*/ _precompiled_tokens;
+    c11_vector/*T=py_Str*/ _precompiled_tokens;
 };
 
 typedef struct pkpy_SourceData* pkpy_SourceData_;
 
-pkpy_SourceData_ pkpy_SourceData__rcnew(c11_string source, const pkpy_Str *filename, enum CompileMode mode);
-void pkpy_SourceData__ctor(struct pkpy_SourceData *self, c11_string source, const pkpy_Str *filename, enum CompileMode mode);
+pkpy_SourceData_ pkpy_SourceData__rcnew(c11_string source, const py_Str *filename, enum CompileMode mode);
+void pkpy_SourceData__ctor(struct pkpy_SourceData *self, c11_string source, const py_Str *filename, enum CompileMode mode);
 void pkpy_SourceData__dtor(struct pkpy_SourceData* self);
 
 bool pkpy_SourceData__get_line(const struct pkpy_SourceData* self, int lineno, const char** st, const char** ed);
-pkpy_Str pkpy_SourceData__snapshot(const struct pkpy_SourceData *self, int lineno, const char *cursor, const char *name);
+py_Str pkpy_SourceData__snapshot(const struct pkpy_SourceData *self, int lineno, const char *cursor, const char *name);
 
 #ifdef __cplusplus
 }

+ 21 - 0
include/pocketpy/pocketpy.h

@@ -15,6 +15,8 @@ typedef int16_t Type;
 typedef PyVar* py_Ref;
 typedef int (*py_CFunction)(const py_Ref, int);
 
+typedef struct py_Str py_Str;
+
 typedef struct py_Error{
     Type type;
 } py_Error;
@@ -92,9 +94,28 @@ int py_setattr(py_Ref self, py_Name name, const py_Ref val);
 /// Returns 0 | err
 int py_getattr(const py_Ref self, py_Name name, py_Ref out);
 
+/// Returns a reference to the i-th object in the stack.
+/// For example, `py_stackref(-1)` refers to the top of the stack.
+py_Ref py_stackref(int i);
+/// Pushes the object to the stack.
 void py_pushref(const py_Ref src);
+/// Pops the object from the stack.
 void py_copyref(const py_Ref src, py_Ref dst);
 
+
+/* tuple */
+
+// unchecked functions, if self is not a tuple, the behavior is undefined
+py_Ref py_tuple__getitem(const py_Ref self, int i);
+void py_tuple__setitem(py_Ref self, int i, const py_Ref val);
+int py_tuple__len(const py_Ref self);
+
+int py_str(const py_Ref, py_Str* out);
+int py_repr(const py_Ref, py_Str* out);
+
+int py_tostr(py_Ref, py_Str** out);
+int py_tobool(py_Ref, bool* out);
+
 #ifdef __cplusplus
 }
 #endif

+ 10 - 10
src/common/sourcedata.c

@@ -4,7 +4,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-pkpy_SourceData_ pkpy_SourceData__rcnew(c11_string source, const pkpy_Str* filename, enum CompileMode mode) {
+pkpy_SourceData_ pkpy_SourceData__rcnew(c11_string source, const py_Str* filename, enum CompileMode mode) {
     pkpy_SourceData_ self = malloc(sizeof(struct pkpy_SourceData));
     pkpy_SourceData__ctor(self, source, filename, mode);
     self->rc.count = 1;
@@ -14,12 +14,12 @@ pkpy_SourceData_ pkpy_SourceData__rcnew(c11_string source, const pkpy_Str* filen
 
 void pkpy_SourceData__ctor(struct pkpy_SourceData* self,
                            c11_string source,       // may not be null-terminated
-                           const pkpy_Str* filename,
+                           const py_Str* filename,
                            enum CompileMode mode) {
-    self->filename = pkpy_Str__copy(filename);  // OPTIMIZEME?
+    self->filename = py_Str__copy(filename);  // OPTIMIZEME?
     self->mode = mode;
     c11_vector__ctor(&self->line_starts, sizeof(const char*));
-    c11_vector__ctor(&self->_precompiled_tokens, sizeof(pkpy_Str));
+    c11_vector__ctor(&self->_precompiled_tokens, sizeof(py_Str));
 
     int index = 0;
     // Skip utf8 BOM if there is any.
@@ -33,17 +33,17 @@ void pkpy_SourceData__ctor(struct pkpy_SourceData* self,
         index++;
     }
     self->source = pk_SStream__submit(&ss);
-    self->is_precompiled = (strncmp(pkpy_Str__data(&self->source), "pkpy:", 5) == 0);
-    c11_vector__push(const char*, &self->line_starts, pkpy_Str__data(&self->source));
+    self->is_precompiled = (strncmp(py_Str__data(&self->source), "pkpy:", 5) == 0);
+    c11_vector__push(const char*, &self->line_starts, py_Str__data(&self->source));
 }
 
 void pkpy_SourceData__dtor(struct pkpy_SourceData* self) {
-    pkpy_Str__dtor(&self->filename);
-    pkpy_Str__dtor(&self->source);
+    py_Str__dtor(&self->filename);
+    py_Str__dtor(&self->source);
     c11_vector__dtor(&self->line_starts);
 
     for(int i=0; i<self->_precompiled_tokens.count; i++){
-        pkpy_Str__dtor(c11__at(pkpy_Str, &self->_precompiled_tokens, i));
+        py_Str__dtor(c11__at(py_Str, &self->_precompiled_tokens, i));
     }
     c11_vector__dtor(&self->_precompiled_tokens);
 }
@@ -62,7 +62,7 @@ bool pkpy_SourceData__get_line(const struct pkpy_SourceData* self, int lineno, c
     return true;
 }
 
-pkpy_Str pkpy_SourceData__snapshot(const struct pkpy_SourceData* self, int lineno, const char* cursor, const char* name) {
+py_Str pkpy_SourceData__snapshot(const struct pkpy_SourceData* self, int lineno, const char* cursor, const char* name) {
     pk_SStream ss;
     pk_SStream__ctor(&ss);
 

+ 4 - 4
src/common/sstream.c

@@ -81,8 +81,8 @@ void pk_SStream__write_double(pk_SStream* self, double val, int precision){
     if(all_is_digit) pk_SStream__write_cstr(self, ".0");
 }
 
-void pk_SStream__write_Str(pk_SStream* self, const pkpy_Str* str) {
-    pk_SStream__write_cstrn(self, pkpy_Str__data(str), str->size);
+void pk_SStream__write_Str(pk_SStream* self, const py_Str* str) {
+    pk_SStream__write_cstrn(self, py_Str__data(str), str->size);
 }
 
 void pk_SStream__write_sv(pk_SStream* self, c11_string sv) {
@@ -150,9 +150,9 @@ void pk_SStream__write_any(pk_SStream* self, const char* fmt, const pk_AnyStr* a
     }
 }
 
-pkpy_Str pk_SStream__submit(pk_SStream* self) {
+py_Str pk_SStream__submit(pk_SStream* self) {
     c11_vector__push(char, &self->data, '\0');
-    pkpy_Str retval = {
+    py_Str retval = {
         .size = self->data.count - 1,
         .is_ascii = c11__isascii((char*)self->data.data, self->data.count),
         .is_sso = false,

+ 90 - 90
src/common/str.c

@@ -7,11 +7,11 @@
 #include <ctype.h>
 #include <stdio.h>
 
-void pkpy_Str__ctor(pkpy_Str *self, const char *data){
-    pkpy_Str__ctor2(self, data, strlen(data));
+void py_Str__ctor(py_Str *self, const char *data){
+    py_Str__ctor2(self, data, strlen(data));
 }
 
-void pkpy_Str__ctor2(pkpy_Str *self, const char *data, int size){
+void py_Str__ctor2(py_Str *self, const char *data, int size){
     self->size = size;
     self->is_ascii = c11__isascii(data, size);
     self->is_sso = size < sizeof(self->_inlined);
@@ -26,7 +26,7 @@ void pkpy_Str__ctor2(pkpy_Str *self, const char *data, int size){
     p[size] = '\0';
 }
 
-void pkpy_Str__dtor(pkpy_Str *self){
+void py_Str__dtor(py_Str *self){
     if(!self->is_sso){
         free(self->_ptr);
         self->is_sso = true;
@@ -34,8 +34,8 @@ void pkpy_Str__dtor(pkpy_Str *self){
     }
 }
 
-pkpy_Str pkpy_Str__copy(const pkpy_Str *self){
-    pkpy_Str retval = *self;
+py_Str py_Str__copy(const py_Str *self){
+    py_Str retval = *self;
     if(!self->is_sso){
         retval._ptr = (char*)malloc(self->size + 1);
         // '\0' is copied
@@ -44,8 +44,8 @@ pkpy_Str pkpy_Str__copy(const pkpy_Str *self){
     return retval;
 }
 
-pkpy_Str pkpy_Str__concat(const pkpy_Str *self, const pkpy_Str *other){
-    pkpy_Str retval = {
+py_Str py_Str__concat(const py_Str *self, const py_Str *other){
+    py_Str retval = {
         .size = self->size + other->size,
         .is_ascii = self->is_ascii && other->is_ascii,
         .is_sso = self->size + other->size < sizeof(retval._inlined),
@@ -57,56 +57,56 @@ pkpy_Str pkpy_Str__concat(const pkpy_Str *self, const pkpy_Str *other){
         retval._ptr = (char*)malloc(retval.size + 1);
         p = retval._ptr;
     }
-    memcpy(p, pkpy_Str__data(self), self->size);
-    memcpy(p + self->size, pkpy_Str__data(other), other->size);
+    memcpy(p, py_Str__data(self), self->size);
+    memcpy(p + self->size, py_Str__data(other), other->size);
     p[retval.size] = '\0';
     return retval;
 }
 
-pkpy_Str pkpy_Str__concat2(const pkpy_Str *self, const char *other, int size){
-    pkpy_Str tmp;
-    pkpy_Str__ctor2(&tmp, other, size);
-    pkpy_Str retval = pkpy_Str__concat(self, &tmp);
-    pkpy_Str__dtor(&tmp);
+py_Str py_Str__concat2(const py_Str *self, const char *other, int size){
+    py_Str tmp;
+    py_Str__ctor2(&tmp, other, size);
+    py_Str retval = py_Str__concat(self, &tmp);
+    py_Str__dtor(&tmp);
     return retval;
 }
 
-pkpy_Str pkpy_Str__slice(const pkpy_Str *self, int start){
-    return pkpy_Str__slice2(self, start, self->size);
+py_Str py_Str__slice(const py_Str *self, int start){
+    return py_Str__slice2(self, start, self->size);
 }
 
-pkpy_Str pkpy_Str__slice2(const pkpy_Str *self, int start, int stop){
-    pkpy_Str retval;
+py_Str py_Str__slice2(const py_Str *self, int start, int stop){
+    py_Str retval;
     if(stop < start) stop = start;
-    pkpy_Str__ctor2(&retval, pkpy_Str__data(self) + start, stop - start);
+    py_Str__ctor2(&retval, py_Str__data(self) + start, stop - start);
     return retval;
 }
 
-pkpy_Str pkpy_Str__lower(const pkpy_Str *self){
-    pkpy_Str retval = pkpy_Str__copy(self);
-    char* p = (char*)pkpy_Str__data(&retval);
+py_Str py_Str__lower(const py_Str *self){
+    py_Str retval = py_Str__copy(self);
+    char* p = (char*)py_Str__data(&retval);
     for(int i = 0; i < retval.size; i++){
         if('A' <= p[i] && p[i] <= 'Z') p[i] += 32;
     }
     return retval;
 }
 
-pkpy_Str pkpy_Str__upper(const pkpy_Str *self){
-    pkpy_Str retval = pkpy_Str__copy(self);
-    char* p = (char*)pkpy_Str__data(&retval);
+py_Str py_Str__upper(const py_Str *self){
+    py_Str retval = py_Str__copy(self);
+    char* p = (char*)py_Str__data(&retval);
     for(int i = 0; i < retval.size; i++){
         if('a' <= p[i] && p[i] <= 'z') p[i] -= 32;
     }
     return retval;
 }
 
-pkpy_Str pkpy_Str__escape(const pkpy_Str* self, char quote){
+py_Str py_Str__escape(const py_Str* self, char quote){
     assert(quote == '"' || quote == '\'');
     c11_vector buffer;
     c11_vector__ctor(&buffer, sizeof(char));
     c11_vector__reserve(&buffer, self->size);
     c11_vector__push(char, &buffer, quote);
-    const char* data = pkpy_Str__data(self);
+    const char* data = py_Str__data(self);
     for(int i = 0; i < self->size; i++) {
         char c = data[i];
         switch(c) {
@@ -147,7 +147,7 @@ pkpy_Str pkpy_Str__escape(const pkpy_Str* self, char quote){
     }
     c11_vector__push(char, &buffer, quote);
     c11_vector__push(char, &buffer, '\0');
-    pkpy_Str retval = {
+    py_Str retval = {
         .size = buffer.count - 1,
         .is_ascii = self->is_ascii,
         .is_sso = false,
@@ -156,8 +156,8 @@ pkpy_Str pkpy_Str__escape(const pkpy_Str* self, char quote){
     return retval;
 }
 
-pkpy_Str pkpy_Str__strip(const pkpy_Str *self, bool left, bool right){
-    const char* data = pkpy_Str__data(self);
+py_Str py_Str__strip(const py_Str *self, bool left, bool right){
+    const char* data = py_Str__data(self);
     if(self->is_ascii) {
         int L = 0;
         int R = self->size;
@@ -169,67 +169,67 @@ pkpy_Str pkpy_Str__strip(const pkpy_Str *self, bool left, bool right){
             while(L < R && (data[R - 1] == ' ' || data[R - 1] == '\t' || data[R - 1] == '\n' || data[R - 1] == '\r'))
                 R--;
         }
-        return pkpy_Str__slice2(self, L, R);
+        return py_Str__slice2(self, L, R);
     } else {
-        pkpy_Str tmp;
-        pkpy_Str__ctor(&tmp, " \t\n\r");
-        pkpy_Str retval = pkpy_Str__strip2(self, left, right, &tmp);
-        pkpy_Str__dtor(&tmp);
+        py_Str tmp;
+        py_Str__ctor(&tmp, " \t\n\r");
+        py_Str retval = py_Str__strip2(self, left, right, &tmp);
+        py_Str__dtor(&tmp);
         return retval;
     }
 }
 
-pkpy_Str pkpy_Str__strip2(const pkpy_Str *self, bool left, bool right, const pkpy_Str *chars){
+py_Str py_Str__strip2(const py_Str *self, bool left, bool right, const py_Str *chars){
     int L = 0;
-    int R = pkpy_Str__u8_length(self);
+    int R = py_Str__u8_length(self);
     if(left) {
         while(L < R){
-            pkpy_Str tmp = pkpy_Str__u8_getitem(self, L);
-            bool found = pkpy_Str__index(chars, &tmp, 0) != -1;
-            pkpy_Str__dtor(&tmp);
+            py_Str tmp = py_Str__u8_getitem(self, L);
+            bool found = py_Str__index(chars, &tmp, 0) != -1;
+            py_Str__dtor(&tmp);
             if(!found) break;
             L++;
         }
     }
     if(right) {
         while(L < R){
-            pkpy_Str tmp = pkpy_Str__u8_getitem(self, R - 1);
-            bool found = pkpy_Str__index(chars, &tmp, 0) != -1;
-            pkpy_Str__dtor(&tmp);
+            py_Str tmp = py_Str__u8_getitem(self, R - 1);
+            bool found = py_Str__index(chars, &tmp, 0) != -1;
+            py_Str__dtor(&tmp);
             if(!found) break;
             R--;
         }
     }
-    return pkpy_Str__u8_slice(self, L, R, 1);
+    return py_Str__u8_slice(self, L, R, 1);
 }
 
-pkpy_Str pkpy_Str__replace(const pkpy_Str *self, char old, char new_){
-    pkpy_Str retval = pkpy_Str__copy(self);
-    char* p = (char*)pkpy_Str__data(&retval);
+py_Str py_Str__replace(const py_Str *self, char old, char new_){
+    py_Str retval = py_Str__copy(self);
+    char* p = (char*)py_Str__data(&retval);
     for(int i = 0; i < retval.size; i++){
         if(p[i] == old) p[i] = new_;
     }
     return retval;
 }
 
-pkpy_Str pkpy_Str__replace2(const pkpy_Str *self, const pkpy_Str *old, const pkpy_Str *new_){
+py_Str py_Str__replace2(const py_Str *self, const py_Str *old, const py_Str *new_){
     c11_vector buffer;
     c11_vector__ctor(&buffer, sizeof(char));
     int start = 0;
     while(true) {
-        int i = pkpy_Str__index(self, old, start);
+        int i = py_Str__index(self, old, start);
         if(i == -1) break;
-        pkpy_Str tmp = pkpy_Str__slice2(self, start, i);
-        c11_vector__extend(char, &buffer, pkpy_Str__data(&tmp), tmp.size);
-        pkpy_Str__dtor(&tmp);
-        c11_vector__extend(char, &buffer, pkpy_Str__data(new_), new_->size);
+        py_Str tmp = py_Str__slice2(self, start, i);
+        c11_vector__extend(char, &buffer, py_Str__data(&tmp), tmp.size);
+        py_Str__dtor(&tmp);
+        c11_vector__extend(char, &buffer, py_Str__data(new_), new_->size);
         start = i + old->size;
     }
-    pkpy_Str tmp = pkpy_Str__slice2(self, start, self->size);
-    c11_vector__extend(char, &buffer, pkpy_Str__data(&tmp), tmp.size);
-    pkpy_Str__dtor(&tmp);
+    py_Str tmp = py_Str__slice2(self, start, self->size);
+    c11_vector__extend(char, &buffer, py_Str__data(&tmp), tmp.size);
+    py_Str__dtor(&tmp);
     c11_vector__push(char, &buffer, '\0');
-    pkpy_Str retval = {
+    py_Str retval = {
         .size = buffer.count - 1,
         .is_ascii = self->is_ascii && old->is_ascii && new_->is_ascii,
         .is_sso = false,
@@ -252,47 +252,47 @@ int c11_string__cmp3(c11_string self, const char *other){
     return c11_string__cmp2(self, other, strlen(other));
 }
 
-int pkpy_Str__cmp(const pkpy_Str *self, const pkpy_Str *other){
-    return pkpy_Str__cmp2(self, pkpy_Str__data(other), other->size);
+int py_Str__cmp(const py_Str *self, const py_Str *other){
+    return py_Str__cmp2(self, py_Str__data(other), other->size);
 }
 
-int pkpy_Str__cmp2(const pkpy_Str *self, const char *other, int size){
-    int res = strncmp(pkpy_Str__data(self), other, PK_MIN(self->size, size));
+int py_Str__cmp2(const py_Str *self, const char *other, int size){
+    int res = strncmp(py_Str__data(self), other, PK_MIN(self->size, size));
     if(res != 0) return res;
     return self->size - size;
 }
 
-int pkpy_Str__cmp3(const pkpy_Str *self, const char *other){
-    return strcmp(pkpy_Str__data(self), other);
+int py_Str__cmp3(const py_Str *self, const char *other){
+    return strcmp(py_Str__data(self), other);
 }
 
-pkpy_Str pkpy_Str__u8_getitem(const pkpy_Str *self, int i){
-    i = pkpy_Str__unicode_index_to_byte(self, i);
-    int size = c11__u8_header(pkpy_Str__data(self)[i], false);
-    return pkpy_Str__slice2(self, i, i + size);
+py_Str py_Str__u8_getitem(const py_Str *self, int i){
+    i = py_Str__unicode_index_to_byte(self, i);
+    int size = c11__u8_header(py_Str__data(self)[i], false);
+    return py_Str__slice2(self, i, i + size);
 }
 
-pkpy_Str pkpy_Str__u8_slice(const pkpy_Str *self, int start, int stop, int step){
+py_Str py_Str__u8_slice(const py_Str *self, int start, int stop, int step){
     c11_vector buffer;
     c11_vector__ctor(&buffer, sizeof(char));
     assert(step != 0);
     if(self->is_ascii){
-        const char* p = pkpy_Str__data(self);
+        const char* p = py_Str__data(self);
         for (int i=start; step>0 ? i<stop : i>stop; i+=step) {
             c11_vector__push(char, &buffer, p[i]);
         }
     }else{
         for (int i=start; step>0 ? i<stop : i>stop; i+=step) {
-            pkpy_Str unicode = pkpy_Str__u8_getitem(self, i);
-            const char* p = pkpy_Str__data(&unicode);
+            py_Str unicode = py_Str__u8_getitem(self, i);
+            const char* p = py_Str__data(&unicode);
             for(int j = 0; j < unicode.size; j++){
                 c11_vector__push(char, &buffer, p[j]);
             }
-            pkpy_Str__dtor(&unicode);
+            py_Str__dtor(&unicode);
         }
     }
     c11_vector__push(char, &buffer, '\0');
-    pkpy_Str retval = {
+    py_Str retval = {
         .size = buffer.count - 1,
         .is_ascii = self->is_ascii,
         .is_sso = false,
@@ -301,13 +301,13 @@ pkpy_Str pkpy_Str__u8_slice(const pkpy_Str *self, int start, int stop, int step)
     return retval;
 }
 
-int pkpy_Str__u8_length(const pkpy_Str *self){
-    return pkpy_Str__byte_index_to_unicode(self, self->size);
+int py_Str__u8_length(const py_Str *self){
+    return py_Str__byte_index_to_unicode(self, self->size);
 }
 
-int pkpy_Str__unicode_index_to_byte(const pkpy_Str* self, int i) {
+int py_Str__unicode_index_to_byte(const py_Str* self, int i) {
     if(self->is_ascii) return i;
-    const char* p = pkpy_Str__data(self);
+    const char* p = py_Str__data(self);
     int j = 0;
     while(i > 0) {
         j += c11__u8_header(p[j], false);
@@ -316,9 +316,9 @@ int pkpy_Str__unicode_index_to_byte(const pkpy_Str* self, int i) {
     return j;
 }
 
-int pkpy_Str__byte_index_to_unicode(const pkpy_Str* self, int n) {
+int py_Str__byte_index_to_unicode(const py_Str* self, int n) {
     if(self->is_ascii) return n;
-    const char* p = pkpy_Str__data(self);
+    const char* p = py_Str__data(self);
     int cnt = 0;
     for(int i = 0; i < n; i++) {
         if((p[i] & 0xC0) != 0x80) cnt++;
@@ -326,11 +326,11 @@ int pkpy_Str__byte_index_to_unicode(const pkpy_Str* self, int n) {
     return cnt;
 }
 
-int pkpy_Str__index(const pkpy_Str *self, const pkpy_Str *sub, int start){
+int py_Str__index(const py_Str *self, const py_Str *sub, int start){
     if(sub->size == 0) return start;
     int max_end = self->size - sub->size;
-    const char* self_data = pkpy_Str__data(self);
-    const char* sub_data = pkpy_Str__data(sub);
+    const char* self_data = py_Str__data(self);
+    const char* sub_data = py_Str__data(sub);
     for(int i=start; i<=max_end; i++){
         int res = memcmp(self_data + i, sub_data, sub->size);
         if(res == 0) return i;
@@ -338,12 +338,12 @@ int pkpy_Str__index(const pkpy_Str *self, const pkpy_Str *sub, int start){
     return -1;
 }
 
-int pkpy_Str__count(const pkpy_Str *self, const pkpy_Str *sub){
+int py_Str__count(const py_Str *self, const py_Str *sub){
     if(sub->size == 0) return self->size + 1;
     int cnt = 0;
     int start = 0;
     while(true) {
-        int i = pkpy_Str__index(self, sub, start);
+        int i = py_Str__index(self, sub, start);
         if(i == -1) break;
         cnt++;
         start = i + sub->size;
@@ -351,10 +351,10 @@ int pkpy_Str__count(const pkpy_Str *self, const pkpy_Str *sub){
     return cnt;
 }
 
-c11_vector/* T=c11_string */ pkpy_Str__split(const pkpy_Str *self, char sep){
+c11_vector/* T=c11_string */ py_Str__split(const py_Str *self, char sep){
     c11_vector retval;
     c11_vector__ctor(&retval, sizeof(c11_string));
-    const char* data = pkpy_Str__data(self);
+    const char* data = py_Str__data(self);
     int i = 0;
     for(int j = 0; j < self->size; j++) {
         if(data[j] == sep) {
@@ -373,13 +373,13 @@ c11_vector/* T=c11_string */ pkpy_Str__split(const pkpy_Str *self, char sep){
     return retval;
 }
 
-c11_vector/* T=c11_string */ pkpy_Str__split2(const pkpy_Str *self, const pkpy_Str *sep){
+c11_vector/* T=c11_string */ py_Str__split2(const py_Str *self, const py_Str *sep){
     c11_vector retval;
     c11_vector__ctor(&retval, sizeof(c11_string));
     int start = 0;
-    const char* data = pkpy_Str__data(self);
+    const char* data = py_Str__data(self);
     while(true) {
-        int i = pkpy_Str__index(self, sep, start);
+        int i = py_Str__index(self, sep, start);
         if(i == -1) break;
         c11_string tmp = {data + start, i - start};
         if(tmp.size != 0) c11_vector__push(c11_string, &retval, tmp);

+ 1 - 1
src/compiler/compiler.cpp

@@ -22,7 +22,7 @@ NameScope Compiler::name_scope() const noexcept{
 }
 
 CodeObject* Compiler::push_global_context() noexcept{
-    CodeObject* co = CodeObject__new(lexer.src, pkpy_Str__sv(&lexer.src->filename));
+    CodeObject* co = CodeObject__new(lexer.src, py_Str__sv(&lexer.src->filename));
     co->start_line = __i == 0 ? 1 : prev().line;
     contexts.push_back(CodeEmitContext(vm, co, contexts.size()));
     return co;

+ 6 - 6
src/compiler/lexer.c

@@ -49,7 +49,7 @@ c11_string pk_TokenDeserializer__read_string(pk_TokenDeserializer* self, char c)
     return retval;
 }
 
-pkpy_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self, char c){
+py_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self, char c){
     c11_string sv = pk_TokenDeserializer__read_string(self, c);
     const char* s = sv.data;
     char* buffer = (char*)malloc(sv.size / 2 + 1);
@@ -71,7 +71,7 @@ pkpy_Str pk_TokenDeserializer__read_string_from_hex(pk_TokenDeserializer* self,
         buffer[i / 2] = c;
     }
     buffer[sv.size / 2] = 0;
-    return (pkpy_Str){
+    return (py_Str){
         .size = sv.size / 2,
         .is_ascii = c11__isascii(buffer, sv.size / 2),
         .is_sso = false,
@@ -97,11 +97,11 @@ int64_t pk_TokenDeserializer__read_uint(pk_TokenDeserializer* self, char c){
 
 double pk_TokenDeserializer__read_float(pk_TokenDeserializer* self, char c){
     c11_string sv = pk_TokenDeserializer__read_string(self, c);
-    pkpy_Str nullterm;
-    pkpy_Str__ctor2(&nullterm, sv.data, sv.size);
+    py_Str nullterm;
+    py_Str__ctor2(&nullterm, sv.data, sv.size);
     char* end;
-    double retval = strtod(pkpy_Str__data(&nullterm), &end);
-    pkpy_Str__dtor(&nullterm);
+    double retval = strtod(py_Str__data(&nullterm), &end);
+    py_Str__dtor(&nullterm);
     assert(*end == 0);
     return retval;
 }

+ 8 - 8
src/compiler/lexer.cpp

@@ -534,7 +534,7 @@ Error* Lexer::run() noexcept{
 
 Error* Lexer::from_precompiled() noexcept{
     pk_TokenDeserializer deserializer;
-    pk_TokenDeserializer__ctor(&deserializer, pkpy_Str__data(&src->source));
+    pk_TokenDeserializer__ctor(&deserializer, py_Str__data(&src->source));
 
     deserializer.curr += 5;  // skip "pkpy:"
     c11_string version = pk_TokenDeserializer__read_string(&deserializer, '\n');
@@ -550,9 +550,9 @@ Error* Lexer::from_precompiled() noexcept{
     c11_vector* precompiled_tokens = &src->_precompiled_tokens;
     for(int i = 0; i < count; i++) {
         c11_string item = pk_TokenDeserializer__read_string(&deserializer, '\n');
-        pkpy_Str copied_item;
-        pkpy_Str__ctor2(&copied_item, item.data, item.size);
-        c11_vector__push(pkpy_Str, precompiled_tokens, copied_item);
+        py_Str copied_item;
+        py_Str__ctor2(&copied_item, item.data, item.size);
+        c11_vector__push(py_Str, precompiled_tokens, copied_item);
     }
 
     count = pk_TokenDeserializer__read_count(&deserializer);
@@ -561,9 +561,9 @@ Error* Lexer::from_precompiled() noexcept{
         t.type = (TokenIndex)pk_TokenDeserializer__read_uint(&deserializer, ',');
         if(is_raw_string_used(t.type)) {
             i64 index = pk_TokenDeserializer__read_uint(&deserializer, ',');
-            pkpy_Str* p = c11__at(pkpy_Str, precompiled_tokens, index);
-            t.start = pkpy_Str__data(p);
-            t.length = c11__getitem(pkpy_Str, precompiled_tokens, index).size;
+            py_Str* p = c11__at(py_Str, precompiled_tokens, index);
+            t.start = py_Str__data(p);
+            t.length = c11__getitem(py_Str, precompiled_tokens, index).size;
         } else {
             t.start = NULL;
             t.length = 0;
@@ -590,7 +590,7 @@ Error* Lexer::from_precompiled() noexcept{
                 t.value = pk_TokenDeserializer__read_float(&deserializer, '\n');
                 break;
             case 'S': {
-                pkpy_Str res = pk_TokenDeserializer__read_string_from_hex(&deserializer, '\n');
+                py_Str res = pk_TokenDeserializer__read_string_from_hex(&deserializer, '\n');
                 t.value = Str(std::move(res));
             } break;
             default:

+ 7 - 7
src/error.c

@@ -9,7 +9,7 @@ void pkpy_Exception__ctor(pkpy_Exception* self, StrName type){
     self->_code_on_error = NULL;
     self->self = NULL;
 
-    pkpy_Str__ctor(&self->msg, "");
+    py_Str__ctor(&self->msg, "");
     c11_vector__ctor(&self->stacktrace, sizeof(pkpy_ExceptionFrame));
 }
 
@@ -17,9 +17,9 @@ void pkpy_Exception__dtor(pkpy_Exception* self){
     for(int i=0; i<self->stacktrace.count; i++){
         pkpy_ExceptionFrame* frame = c11__at(pkpy_ExceptionFrame, &self->stacktrace, i);
         PK_DECREF(frame->src);
-        pkpy_Str__dtor(&frame->name);
+        py_Str__dtor(&frame->name);
     }
-    pkpy_Str__dtor(&self->msg);
+    py_Str__dtor(&self->msg);
     c11_vector__dtor(&self->stacktrace);
 }
 
@@ -30,10 +30,10 @@ void pkpy_Exception__stpush(pkpy_Exception* self, pkpy_SourceData_ src, int line
     frame->src = src;
     frame->lineno = lineno;
     frame->cursor = cursor;
-    pkpy_Str__ctor(&frame->name, name);
+    py_Str__ctor(&frame->name, name);
 }
 
-pkpy_Str pkpy_Exception__summary(pkpy_Exception* self){
+py_Str pkpy_Exception__summary(pkpy_Exception* self){
     pk_SStream ss;
     pk_SStream__ctor(&ss);
 
@@ -42,9 +42,9 @@ pkpy_Str pkpy_Exception__summary(pkpy_Exception* self){
     }
     for(int i=self->stacktrace.count-1; i >= 0; i--) {
         pkpy_ExceptionFrame* frame = c11__at(pkpy_ExceptionFrame, &self->stacktrace, i);
-        pkpy_Str s = pkpy_SourceData__snapshot(frame->src, frame->lineno, frame->cursor, pkpy_Str__data(&frame->name));
+        py_Str s = pkpy_SourceData__snapshot(frame->src, frame->lineno, frame->cursor, py_Str__data(&frame->name));
         pk_SStream__write_Str(&ss, &s);
-        pkpy_Str__dtor(&s);
+        py_Str__dtor(&s);
         pk_SStream__write_cstr(&ss, "\n");
     }
 

+ 1 - 1
src/interpreter/ceval.c

@@ -192,7 +192,7 @@
 //                         if(decl->nested) {
 //                             NameDict* captured = frame->_locals.to_namedict();
 //                             obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, captured);
-//                             uint16_t name = pk_StrName__map2(pkpy_Str__sv(&decl->code->name));
+//                             uint16_t name = pk_StrName__map2(py_Str__sv(&decl->code->name));
 //                             captured->set(name, obj);
 //                         } else {
 //                             obj = new_object<Function>(tp_function, decl, frame->_module, nullptr, nullptr);

+ 40 - 0
src/interpreter/vm.c

@@ -1,5 +1,7 @@
 #include "pocketpy/interpreter/vm.h"
 #include "pocketpy/common/memorypool.h"
+#include "pocketpy/common/sstream.h"
+#include "pocketpy/pocketpy.h"
 
 static unsigned char* pk_default_import_file(const char* path){
     return NULL;
@@ -36,6 +38,44 @@ static int _hello(const py_Ref args, int argc){
     return 0;
 }
 
+// print(*args, sep=' ', end='\n')
+static int _py_print(const py_Ref args, int argc){
+    int length = py_tuple__len(args+0);
+    py_Str* sep;
+    py_Str* end;
+
+    int err;
+    err = py_tostr(args+1, &sep);
+    if(err) return err;
+    err = py_tostr(args+2, &end);
+    if(err) return err;
+
+    pk_SStream ss;
+    pk_SStream__ctor(&ss);
+
+    for(int i=0; i<length; i++){
+        const py_Ref item = py_tuple__getitem(args+0, i);
+        py_Str tmp;
+        int err = py_str(item, &tmp);
+        if(!err){
+            pk_SStream__write_Str(&ss, &tmp);
+            py_Str__dtor(&tmp);
+            if(i != length-1){
+                pk_SStream__write_Str(&ss, sep);
+            }
+        }else{
+            py_Str__dtor(&tmp);
+            pk_SStream__dtor(&ss);
+            return err;
+        }
+    }
+    pk_SStream__write_Str(&ss, end);
+    py_Str out = pk_SStream__submit(&ss);
+    pk_current_vm->_stdout(py_Str__data(&out));
+    py_Str__dtor(&out);
+    return 0;
+}
+
 static void do_builtin_bindings(){
     pk_VM* vm = pk_current_vm;
 

+ 2 - 2
src/objects/codeobject.c

@@ -49,7 +49,7 @@ void FuncDecl__add_kwarg(FuncDecl* self, int index, uint16_t key, const PyVar* v
 CodeObject* CodeObject__new(pkpy_SourceData_ src, c11_string name){
     CodeObject* self = malloc(sizeof(CodeObject));
     self->src = src; PK_INCREF(src);
-    pkpy_Str__ctor2(&self->name, name.data, name.size);
+    py_Str__ctor2(&self->name, name.data, name.size);
 
     c11_vector__ctor(&self->codes, sizeof(Bytecode));
     c11_vector__ctor(&self->codes_ex, sizeof(BytecodeEx));
@@ -74,7 +74,7 @@ CodeObject* CodeObject__new(pkpy_SourceData_ src, c11_string name){
 
 void CodeObject__delete(CodeObject* self){
     PK_DECREF(self->src);
-    pkpy_Str__dtor(&self->name);
+    py_Str__dtor(&self->name);
     
     c11_vector__dtor(&self->codes);
     c11_vector__dtor(&self->codes_ex);