Compare commits

...

3 Commits

Author SHA1 Message Date
blueloveTH
f93aefdbe5 implement repl 2024-07-06 00:36:51 +08:00
blueloveTH
d74ca31f68 add some string bindings 2024-07-05 22:55:24 +08:00
blueloveTH
a86c134377 add bool bindings 2024-07-05 21:08:39 +08:00
18 changed files with 455 additions and 229 deletions

View File

@ -1,39 +1,48 @@
#pragma once #pragma once
// clang-format off // clang-format off
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
//define something for Windows (32-bit and 64-bit, this part is common) //define something for Windows (32-bit and 64-bit, this part is common)
#define PK_EXPORT __declspec(dllexport) #define PK_EXPORT __declspec(dllexport)
#define PK_SYS_PLATFORM 0 #define PY_SYS_PLATFORM 0
#define PY_SYS_PLATFORM_STRING "win32"
#elif __EMSCRIPTEN__ #elif __EMSCRIPTEN__
#define PK_EXPORT #define PK_EXPORT
#define PK_SYS_PLATFORM 1 #define PY_SYS_PLATFORM 1
#define PY_SYS_PLATFORM_STRING "emscripten"
#elif __APPLE__ #elif __APPLE__
#include <TargetConditionals.h> #include <TargetConditionals.h>
#if TARGET_IPHONE_SIMULATOR #if TARGET_IPHONE_SIMULATOR
// iOS, tvOS, or watchOS Simulator // iOS, tvOS, or watchOS Simulator
#define PK_SYS_PLATFORM 2 #define PY_SYS_PLATFORM 2
#define PY_SYS_PLATFORM_STRING "ios"
#elif TARGET_OS_IPHONE #elif TARGET_OS_IPHONE
// iOS, tvOS, or watchOS device // iOS, tvOS, or watchOS device
#define PK_SYS_PLATFORM 2 #define PY_SYS_PLATFORM 2
#define PY_SYS_PLATFORM_STRING "ios"
#elif TARGET_OS_MAC #elif TARGET_OS_MAC
#define PK_SYS_PLATFORM 3 #define PY_SYS_PLATFORM 3
#define PY_SYS_PLATFORM_STRING "darwin"
#else #else
# error "Unknown Apple platform" # error "Unknown Apple platform"
#endif #endif
#define PK_EXPORT __attribute__((visibility("default"))) #define PK_EXPORT __attribute__((visibility("default")))
#elif __ANDROID__ #elif __ANDROID__
#define PK_EXPORT __attribute__((visibility("default"))) #define PK_EXPORT __attribute__((visibility("default")))
#define PK_SYS_PLATFORM 4 #define PY_SYS_PLATFORM 4
#define PY_SYS_PLATFORM_STRING "android"
#elif __linux__ #elif __linux__
#define PK_EXPORT __attribute__((visibility("default"))) #define PK_EXPORT __attribute__((visibility("default")))
#define PK_SYS_PLATFORM 5 #define PY_SYS_PLATFORM 5
#define PY_SYS_PLATFORM_STRING "linux"
#else #else
#define PK_EXPORT #define PK_EXPORT
#define PK_SYS_PLATFORM 6 #define PY_SYS_PLATFORM 6
#define PY_SYS_PLATFORM_STRING "unknown"
#endif #endif
#if PK_SYS_PLATFORM == 0 || PK_SYS_PLATFORM == 3 || PK_SYS_PLATFORM == 5 #if PY_SYS_PLATFORM == 0 || PY_SYS_PLATFORM == 3 || PY_SYS_PLATFORM == 5
#define PK_IS_DESKTOP_PLATFORM 1 #define PK_IS_DESKTOP_PLATFORM 1
#else #else
#define PK_IS_DESKTOP_PLATFORM 0 #define PK_IS_DESKTOP_PLATFORM 0

View File

@ -32,7 +32,8 @@ int c11_sv__cmp(c11_sv self, c11_sv other);
int c11_sv__cmp2(c11_sv self, const char* other); int c11_sv__cmp2(c11_sv self, const char* other);
bool c11__streq(const char* a, const char* b); bool c11__streq(const char* a, const char* b);
bool c11__sveq(c11_sv a, const char* b); bool c11__sveq(c11_sv a, c11_sv b);
bool c11__sveq2(c11_sv a, const char* b);
c11_string* c11_string__new(const char* data); c11_string* c11_string__new(const char* data);
c11_string* c11_string__new2(const char* data, int size); c11_string* c11_string__new2(const char* data, int size);
@ -48,8 +49,6 @@ c11_sv c11_string__u8_getitem(c11_string* self, int i);
c11_string* c11_string__u8_slice(c11_string* self, int start, int stop, int step); c11_string* c11_string__u8_slice(c11_string* self, int start, int stop, int step);
// general string operations // general string operations
void c11_sv__lower(c11_sv sv, c11_vector* buf);
void c11_sv__upper(c11_sv sv, c11_vector* buf);
c11_sv c11_sv__slice(c11_sv sv, int start); c11_sv c11_sv__slice(c11_sv sv, int start);
c11_sv c11_sv__slice2(c11_sv sv, int start, int stop); c11_sv c11_sv__slice2(c11_sv sv, int start, int stop);
c11_sv c11_sv__strip(c11_sv sv, bool left, bool right); c11_sv c11_sv__strip(c11_sv sv, bool left, bool right);

View File

@ -21,8 +21,6 @@ extern "C" {
// global constants // global constants
#define PK_HEX_TABLE "0123456789abcdef" #define PK_HEX_TABLE "0123456789abcdef"
extern const char* kPlatformStrings[];
#ifdef _MSC_VER #ifdef _MSC_VER
#define c11__unreachedable() __assume(0) #define c11__unreachedable() __assume(0)
#else #else

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <stdbool.h> #include <stdbool.h>
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/str.h" #include "pocketpy/common/str.h"
#include "pocketpy/common/vector.h" #include "pocketpy/common/vector.h"
@ -8,7 +9,6 @@
extern "C" { extern "C" {
#endif #endif
enum CompileMode { EXEC_MODE, EVAL_MODE, REPL_MODE, JSON_MODE, CELL_MODE };
struct pk_SourceData { struct pk_SourceData {
RefCounted rc; RefCounted rc;

View File

@ -4,6 +4,9 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdarg.h> #include <stdarg.h>
#include "pocketpy/common/config.h"
#include "pocketpy/common/export.h"
/************* Public Types *************/ /************* Public Types *************/
typedef struct py_TValue py_TValue; typedef struct py_TValue py_TValue;
typedef uint16_t py_Name; typedef uint16_t py_Name;
@ -29,11 +32,19 @@ typedef py_TValue* py_TmpRef;
/// @return true if the function is successful. /// @return true if the function is successful.
typedef bool (*py_CFunction)(int argc, py_StackRef argv); typedef bool (*py_CFunction)(int argc, py_StackRef argv);
typedef enum BindType { enum BindType {
BindType_FUNCTION, BindType_FUNCTION,
BindType_STATICMETHOD, BindType_STATICMETHOD,
BindType_CLASSMETHOD, BindType_CLASSMETHOD,
} BindType; };
enum CompileMode {
EXEC_MODE,
EVAL_MODE,
REPL_MODE,
JSON_MODE,
CELL_MODE
};
/************* Global VMs *************/ /************* Global VMs *************/
void py_initialize(); void py_initialize();
@ -44,6 +55,7 @@ bool py_exec(const char* source);
/// Eval a simple expression. /// Eval a simple expression.
/// The result will be set to `py_retval()`. /// The result will be set to `py_retval()`.
bool py_eval(const char* source); bool py_eval(const char* source);
bool py_exec2(const char* source, const char* filename, enum CompileMode mode);
/************* Values Creation *************/ /************* Values Creation *************/
void py_newint(py_Ref, py_i64); void py_newint(py_Ref, py_i64);
@ -81,7 +93,7 @@ void py_newfunction(py_Ref out, py_CFunction, const char* sig);
void py_newfunction2(py_Ref out, void py_newfunction2(py_Ref out,
py_CFunction, py_CFunction,
const char* sig, const char* sig,
BindType bt, enum BindType bt,
const char* docstring, const char* docstring,
const py_Ref upvalue); const py_Ref upvalue);
// old style argc-based function // old style argc-based function
@ -92,7 +104,7 @@ void py_newnativefunc(py_Ref out, py_CFunction);
/// @param type type of the object. /// @param type type of the object.
/// @param slots number of slots. Use -1 to create a `__dict__`. /// @param slots number of slots. Use -1 to create a `__dict__`.
/// @param udsize size of your userdata. You can use `py_touserdata()` to get the pointer to it. /// @param udsize size of your userdata. You can use `py_touserdata()` to get the pointer to it.
void py_newobject(py_Ref out, py_Type type, int slots, int udsize); void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
/************* Type Cast *************/ /************* Type Cast *************/
py_i64 py_toint(const py_Ref); py_i64 py_toint(const py_Ref);
py_f64 py_tofloat(const py_Ref); py_f64 py_tofloat(const py_Ref);
@ -115,12 +127,13 @@ bool py_isinstance(const py_Ref obj, py_Type type);
bool py_issubclass(py_Type derived, py_Type base); bool py_issubclass(py_Type derived, py_Type base);
/************* References *************/ /************* References *************/
#define PY_CHECK_ARGC(n) \ #define PY_CHECK_ARGC(n) \
if(argc != n) return TypeError("expected %d arguments, got %d", n, argc) if(argc != n) return TypeError("expected %d arguments, got %d", n, argc)
#define PY_CHECK_ARG_TYPE(i, type) if(!py_checktype(py_arg(i), type)) return false #define PY_CHECK_ARG_TYPE(i, type) \
if(!py_checktype(py_arg(i), type)) return false
#define py_offset(p, i) (py_Ref)((char*)p + ((i) << 4)) #define py_offset(p, i) ((py_Ref)((char*)p + ((i) << 4)))
#define py_arg(i) py_offset(argv, i) #define py_arg(i) py_offset(argv, i)
py_GlobalRef py_tpmagic(py_Type type, py_Name name); py_GlobalRef py_tpmagic(py_Type type, py_Name name);
@ -131,12 +144,12 @@ py_TmpRef py_bind(py_Ref obj, const char* sig, py_CFunction f);
py_TmpRef py_bind2(py_Ref obj, py_TmpRef py_bind2(py_Ref obj,
const char* sig, const char* sig,
py_CFunction f, py_CFunction f,
BindType bt, enum BindType bt,
const char* docstring, const char* docstring,
const py_Ref upvalue); const py_Ref upvalue);
// old style argc-based bindings // old style argc-based bindings
void py_bindmethod(py_Type type, const char* name, py_CFunction f); void py_bindmethod(py_Type type, const char* name, py_CFunction f);
void py_bindmethod2(py_Type type, const char* name, py_CFunction f, BindType bt); void py_bindmethod2(py_Type type, const char* name, py_CFunction f, enum BindType bt);
void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f); void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f);
/// Get the reference to the i-th register. /// Get the reference to the i-th register.
@ -321,9 +334,10 @@ py_GlobalRef py_tpobject(py_Type type);
const char* py_tpname(py_Type type); const char* py_tpname(py_Type type);
/// Check if the object is an instance of the given type. /// Check if the object is an instance of the given type.
/// Re
bool py_checktype(const py_Ref self, py_Type type); bool py_checktype(const py_Ref self, py_Type type);
int py_replinput(char* buf);
/// Python favored string formatting. /// Python favored string formatting.
/// %d: int /// %d: int
/// %i: py_i64 (int64_t) /// %i: py_i64 (int64_t)
@ -379,12 +393,13 @@ enum py_PredefinedTypes {
} }
#endif #endif
/* /*
Some notes: Some notes:
## Macros ## Macros
1. Function macros are partial functions. They can be used as normal expressions. Use the same naming convention as functions. 1. Function macros are partial functions. They can be used as normal expressions. Use the same
2. Snippet macros are `do {...} while(0)` blocks. They cannot be used as expressions. Use `UPPER_CASE` naming convention. naming convention as functions.
2. Snippet macros are `do {...} while(0)` blocks. They cannot be used as expressions. Use
`UPPER_CASE` naming convention.
3. Constant macros are used for global constants. Use `UPPER_CASE` or k-prefix naming convention. 3. Constant macros are used for global constants. Use `UPPER_CASE` or k-prefix naming convention.
*/ */

View File

@ -1,18 +0,0 @@
#pragma once
#include "pocketpy/interpreter/vm.hpp"
namespace pkpy {
class REPL {
protected:
int need_more_lines = 0;
std::string buffer;
VM* vm;
public:
REPL(VM* vm);
bool input(std::string line);
};
} // namespace pkpy

View File

@ -220,3 +220,38 @@ void pk_sprintf(c11_sbuf* ss, const char* fmt, ...) {
pk_vsprintf(ss, fmt, args); pk_vsprintf(ss, fmt, args);
va_end(args); va_end(args);
} }
int py_replinput(char* buf) {
int size = 0;
bool multiline = false;
printf(">>> ");
while(true) {
char c = getchar();
if(c == EOF) break;
if(c == '\n') {
char last = '\0';
if(size > 0) last = buf[size - 1];
if(multiline) {
if(last == '\n'){
break; // 2 consecutive newlines to end multiline input
}else{
printf("... ");
}
} else {
if(last == ':' || last == '(' || last == '[' || last == '{') {
printf("... ");
multiline = true;
} else {
break;
}
}
}
buf[size++] = c;
}
buf[size] = '\0';
return size;
}

View File

@ -69,26 +69,12 @@ c11_string* c11_string__u8_slice(c11_string* self, int start, int stop, int step
} }
///////////////////////////////////////// /////////////////////////////////////////
void c11_sv__lower(c11_sv sv, c11_vector* buf) {
for(int i = 0; i < sv.size; i++) {
char c = sv.data[i];
if('A' <= c && c <= 'Z') c += 32;
c11_vector__push(char, buf, c);
}
}
void c11_sv__upper(c11_sv sv, c11_vector* buf) {
for(int i = 0; i < sv.size; i++) {
char c = sv.data[i];
if('a' <= c && c <= 'z') c -= 32;
c11_vector__push(char, buf, c);
}
}
c11_sv c11_sv__slice(c11_sv sv, int start) { return c11_sv__slice2(sv, start, sv.size); } c11_sv c11_sv__slice(c11_sv sv, int start) { return c11_sv__slice2(sv, start, sv.size); }
c11_sv c11_sv__slice2(c11_sv sv, int start, int stop) { c11_sv c11_sv__slice2(c11_sv sv, int start, int stop) {
if(start < 0) start = 0;
if(stop < start) stop = start; if(stop < start) stop = start;
if(stop > sv.size) stop = sv.size;
return (c11_sv){sv.data + start, stop - start}; return (c11_sv){sv.data + start, stop - start};
} }
@ -211,7 +197,12 @@ int c11_sv__cmp2(c11_sv self, const char* other) {
bool c11__streq(const char* a, const char* b) { return strcmp(a, b) == 0; } bool c11__streq(const char* a, const char* b) { return strcmp(a, b) == 0; }
bool c11__sveq(c11_sv a, const char* b) { bool c11__sveq(c11_sv a, c11_sv b) {
if(a.size != b.size) return false;
return memcmp(a.data, b.data, a.size) == 0;
}
bool c11__sveq2(c11_sv a, const char* b) {
int size = strlen(b); int size = strlen(b);
if(a.size != size) return false; if(a.size != size) return false;
return memcmp(a.data, b, size) == 0; return memcmp(a.data, b, size) == 0;
@ -250,11 +241,11 @@ IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base) {
c11_sv prefix = {.data = text.data, .size = c11__min(2, text.size)}; c11_sv prefix = {.data = text.data, .size = c11__min(2, text.size)};
if(base == -1) { if(base == -1) {
if(c11__sveq(prefix, "0b")) if(c11__sveq2(prefix, "0b"))
base = 2; base = 2;
else if(c11__sveq(prefix, "0o")) else if(c11__sveq2(prefix, "0o"))
base = 8; base = 8;
else if(c11__sveq(prefix, "0x")) else if(c11__sveq2(prefix, "0x"))
base = 16; base = 16;
else else
base = 10; base = 10;
@ -276,7 +267,7 @@ IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base) {
return IntParsing_SUCCESS; return IntParsing_SUCCESS;
} else if(base == 2) { } else if(base == 2) {
// 2-base 0b101010 // 2-base 0b101010
if(c11__sveq(prefix, "0b")) { if(c11__sveq2(prefix, "0b")) {
// text.remove_prefix(2); // text.remove_prefix(2);
text = (c11_sv){text.data + 2, text.size - 2}; text = (c11_sv){text.data + 2, text.size - 2};
} }
@ -294,7 +285,7 @@ IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base) {
return IntParsing_SUCCESS; return IntParsing_SUCCESS;
} else if(base == 8) { } else if(base == 8) {
// 8-base 0o123 // 8-base 0o123
if(c11__sveq(prefix, "0o")) { if(c11__sveq2(prefix, "0o")) {
// text.remove_prefix(2); // text.remove_prefix(2);
text = (c11_sv){text.data + 2, text.size - 2}; text = (c11_sv){text.data + 2, text.size - 2};
} }
@ -312,7 +303,7 @@ IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base) {
return IntParsing_SUCCESS; return IntParsing_SUCCESS;
} else if(base == 16) { } else if(base == 16) {
// 16-base 0x123 // 16-base 0x123
if(c11__sveq(prefix, "0x")) { if(c11__sveq2(prefix, "0x")) {
// text.remove_prefix(2); // text.remove_prefix(2);
text = (c11_sv){text.data + 2, text.size - 2}; text = (c11_sv){text.data + 2, text.size - 2};
} }

View File

@ -1,9 +0,0 @@
const char* kPlatformStrings[] = {
"win32", // 0
"emscripten", // 1
"ios", // 2
"darwin", // 3
"android", // 4
"linux", // 5
"unknown" // 6
};

View File

@ -1454,7 +1454,7 @@ static void Compiler__dtor(Compiler* self) {
#define mode() self->src->mode #define mode() self->src->mode
#define ctx() (&c11_vector__back(Ctx, &self->contexts)) #define ctx() (&c11_vector__back(Ctx, &self->contexts))
#define match_newlines() match_newlines_repl(self, NULL) #define match_newlines() match_newlines_impl(self)
#define consume(expected) \ #define consume(expected) \
if(!match(expected)) \ if(!match(expected)) \
@ -1463,12 +1463,7 @@ static void Compiler__dtor(Compiler* self) {
pk_TokenSymbols[curr()->type]); pk_TokenSymbols[curr()->type]);
#define consume_end_stmt() \ #define consume_end_stmt() \
if(!match_end_stmt(self)) return SyntaxError("expected statement end") if(!match_end_stmt(self)) return SyntaxError("expected statement end")
#define check_newlines_repl() \
do { \
bool __nml; \
match_newlines_repl(self, &__nml); \
if(__nml) return NeedMoreLines(); \
} while(0)
#define check(B) \ #define check(B) \
if((err = B)) return err if((err = B)) return err
@ -1480,8 +1475,6 @@ static NameScope name_scope(Compiler* self) {
#define SyntaxError(...) NULL #define SyntaxError(...) NULL
static Error* NeedMoreLines() { return NULL; }
/* Matchers */ /* Matchers */
static bool is_expression(Compiler* self, bool allow_slice) { static bool is_expression(Compiler* self, bool allow_slice) {
PrattCallback prefix = rules[curr()->type].prefix; PrattCallback prefix = rules[curr()->type].prefix;
@ -1490,14 +1483,13 @@ static bool is_expression(Compiler* self, bool allow_slice) {
#define match(expected) (curr()->type == expected ? (++self->i) : 0) #define match(expected) (curr()->type == expected ? (++self->i) : 0)
static bool match_newlines_repl(Compiler* self, bool* need_more_lines) { static bool match_newlines_impl(Compiler* self) {
bool consumed = false; bool consumed = false;
if(curr()->type == TK_EOL) { if(curr()->type == TK_EOL) {
while(curr()->type == TK_EOL) while(curr()->type == TK_EOL)
advance(); advance();
consumed = true; consumed = true;
} }
if(need_more_lines) { *need_more_lines = (mode() == REPL_MODE && curr()->type == TK_EOF); }
return consumed; return consumed;
} }
@ -1540,11 +1532,11 @@ static Error* EXPR_TUPLE_ALLOW_SLICE(Compiler* self, bool allow_slice) {
// tuple expression // (a, ) // tuple expression // (a, )
int count = 1; int count = 1;
do { do {
if(curr()->brackets_level) check_newlines_repl(); if(curr()->brackets_level) match_newlines();
if(!is_expression(self, allow_slice)) break; if(!is_expression(self, allow_slice)) break;
check(parse_expression(self, PREC_LOWEST + 1, allow_slice)); check(parse_expression(self, PREC_LOWEST + 1, allow_slice));
count += 1; count += 1;
if(curr()->brackets_level) check_newlines_repl(); if(curr()->brackets_level) match_newlines();
} while(match(TK_COMMA)); } while(match(TK_COMMA));
// pop `count` expressions from the stack and merge them into a TupleExpr // pop `count` expressions from the stack and merge them into a TupleExpr
SequenceExpr* e = TupleExpr__new(prev()->line, count); SequenceExpr* e = TupleExpr__new(prev()->line, count);
@ -1791,9 +1783,9 @@ static Error* exprUnaryOp(Compiler* self) {
static Error* exprGroup(Compiler* self) { static Error* exprGroup(Compiler* self) {
Error* err; Error* err;
int line = prev()->line; int line = prev()->line;
check_newlines_repl(); match_newlines();
check(EXPR_TUPLE(self)); // () is just for change precedence check(EXPR_TUPLE(self)); // () is just for change precedence
check_newlines_repl(); match_newlines();
consume(TK_RPAREN); consume(TK_RPAREN);
if(Ctx__s_top(ctx())->vt->is_tuple) return NULL; if(Ctx__s_top(ctx())->vt->is_tuple) return NULL;
GroupedExpr* g = GroupedExpr__new(line, Ctx__s_popx(ctx())); GroupedExpr* g = GroupedExpr__new(line, Ctx__s_popx(ctx()));
@ -1833,7 +1825,7 @@ static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1) {
check(EXPR_VARS(self)); // [expr, vars] check(EXPR_VARS(self)); // [expr, vars]
consume(TK_IN); consume(TK_IN);
check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter] check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter]
check_newlines_repl(); match_newlines();
if(match(TK_IF)) { if(match(TK_IF)) {
check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter, cond] check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter, cond]
has_cond = true; has_cond = true;
@ -1844,7 +1836,7 @@ static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1) {
ce->vars = Ctx__s_popx(ctx()); ce->vars = Ctx__s_popx(ctx());
ce->expr = Ctx__s_popx(ctx()); ce->expr = Ctx__s_popx(ctx());
Ctx__s_push(ctx(), (Expr*)ce); Ctx__s_push(ctx(), (Expr*)ce);
check_newlines_repl(); match_newlines();
return NULL; return NULL;
} }
@ -1853,17 +1845,17 @@ static Error* exprList(Compiler* self) {
int line = prev()->line; int line = prev()->line;
int count = 0; int count = 0;
do { do {
check_newlines_repl(); match_newlines();
if(curr()->type == TK_RBRACKET) break; if(curr()->type == TK_RBRACKET) break;
check(EXPR(self)); check(EXPR(self));
count += 1; count += 1;
check_newlines_repl(); match_newlines();
if(count == 1 && match(TK_FOR)) { if(count == 1 && match(TK_FOR)) {
check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND)); check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND));
consume(TK_RBRACKET); consume(TK_RBRACKET);
return NULL; return NULL;
} }
check_newlines_repl(); match_newlines();
} while(match(TK_COMMA)); } while(match(TK_COMMA));
consume(TK_RBRACKET); consume(TK_RBRACKET);
SequenceExpr* e = ListExpr__new(line, count); SequenceExpr* e = ListExpr__new(line, count);
@ -1880,7 +1872,7 @@ static Error* exprMap(Compiler* self) {
bool parsing_dict = false; // {...} may be dict or set bool parsing_dict = false; // {...} may be dict or set
int count = 0; int count = 0;
do { do {
check_newlines_repl(); match_newlines();
if(curr()->type == TK_RBRACE) break; if(curr()->type == TK_RBRACE) break;
check(EXPR(self)); // [key] check(EXPR(self)); // [key]
if(curr()->type == TK_COLON) { parsing_dict = true; } if(curr()->type == TK_COLON) { parsing_dict = true; }
@ -1889,7 +1881,7 @@ static Error* exprMap(Compiler* self) {
check(EXPR(self)); // [key, value] check(EXPR(self)); // [key, value]
} }
count += 1; // key-value pair count count += 1; // key-value pair count
check_newlines_repl(); match_newlines();
if(count == 1 && match(TK_FOR)) { if(count == 1 && match(TK_FOR)) {
if(parsing_dict) { if(parsing_dict) {
check(consume_comp(self, OP_BUILD_DICT, OP_DICT_ADD)); check(consume_comp(self, OP_BUILD_DICT, OP_DICT_ADD));
@ -1899,7 +1891,7 @@ static Error* exprMap(Compiler* self) {
consume(TK_RBRACE); consume(TK_RBRACE);
return NULL; return NULL;
} }
check_newlines_repl(); match_newlines();
} while(match(TK_COMMA)); } while(match(TK_COMMA));
consume(TK_RBRACE); consume(TK_RBRACE);
@ -1922,7 +1914,7 @@ static Error* exprCall(Compiler* self) {
CallExpr* e = CallExpr__new(prev()->line, Ctx__s_popx(ctx())); CallExpr* e = CallExpr__new(prev()->line, Ctx__s_popx(ctx()));
Ctx__s_push(ctx(), (Expr*)e); // push onto the stack in advance Ctx__s_push(ctx(), (Expr*)e); // push onto the stack in advance
do { do {
check_newlines_repl(); match_newlines();
if(curr()->type == TK_RPAREN) break; if(curr()->type == TK_RPAREN) break;
if(curr()->type == TK_ID && next()->type == TK_ASSIGN) { if(curr()->type == TK_ID && next()->type == TK_ASSIGN) {
consume(TK_ID); consume(TK_ID);
@ -1948,7 +1940,7 @@ static Error* exprCall(Compiler* self) {
c11_vector__push(Expr*, &e->args, Ctx__s_popx(ctx())); c11_vector__push(Expr*, &e->args, Ctx__s_popx(ctx()));
} }
} }
check_newlines_repl(); match_newlines();
} while(match(TK_COMMA)); } while(match(TK_COMMA));
consume(TK_RPAREN); consume(TK_RPAREN);
return NULL; return NULL;
@ -1998,9 +1990,9 @@ static Error* exprSlice1(Compiler* self) {
static Error* exprSubscr(Compiler* self) { static Error* exprSubscr(Compiler* self) {
Error* err; Error* err;
int line = prev()->line; int line = prev()->line;
check_newlines_repl(); match_newlines();
check(EXPR_TUPLE_ALLOW_SLICE(self, true)); check(EXPR_TUPLE_ALLOW_SLICE(self, true));
check_newlines_repl(); match_newlines();
consume(TK_RBRACKET); // [lhs, rhs] consume(TK_RBRACKET); // [lhs, rhs]
SubscrExpr* e = SubscrExpr__new(line); SubscrExpr* e = SubscrExpr__new(line);
e->rhs = Ctx__s_popx(ctx()); // [lhs] e->rhs = Ctx__s_popx(ctx()); // [lhs]
@ -2032,9 +2024,7 @@ static Error* compile_block_body(Compiler* self, PrattCallback callback) {
return NULL; return NULL;
} }
bool need_more_lines; bool consumed = match_newlines();
bool consumed = match_newlines_repl(self, &need_more_lines);
if(need_more_lines) return NeedMoreLines();
if(!consumed) return SyntaxError("expected a new line after ':'"); if(!consumed) return SyntaxError("expected a new line after ':'");
consume(TK_INDENT); consume(TK_INDENT);
@ -2090,17 +2080,18 @@ static Error* compile_while_loop(Compiler* self) {
static Error* compile_for_loop(Compiler* self) { static Error* compile_for_loop(Compiler* self) {
Error* err; Error* err;
check(EXPR_VARS(self)); // [vars] check(EXPR_VARS(self)); // [vars]
consume(TK_IN); consume(TK_IN);
check(EXPR_TUPLE(self)); // [vars, iter] check(EXPR_TUPLE(self)); // [vars, iter]
Ctx__s_emit_top(ctx()); // [vars] Ctx__s_emit_top(ctx()); // [vars]
Ctx__emit_(ctx(), OP_GET_ITER_NEW, BC_NOARG, BC_KEEPLINE); Ctx__emit_(ctx(), OP_GET_ITER_NEW, BC_NOARG, BC_KEEPLINE);
CodeBlock* block = Ctx__enter_block(ctx(), CodeBlockType_FOR_LOOP); CodeBlock* block = Ctx__enter_block(ctx(), CodeBlockType_FOR_LOOP);
int for_codei = Ctx__emit_(ctx(), OP_FOR_ITER, ctx()->curr_iblock, BC_KEEPLINE); int for_codei = Ctx__emit_(ctx(), OP_FOR_ITER, ctx()->curr_iblock, BC_KEEPLINE);
Expr* vars = Ctx__s_popx(ctx()); Expr* vars = Ctx__s_popx(ctx());
bool ok = vtemit_store(vars, ctx()); bool ok = vtemit_store(vars, ctx());
vtdelete(vars); vtdelete(vars);
if(!ok) return SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind if(!ok)
return SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind
// TODO: ?? // TODO: ??
// ctx()->try_merge_for_iter_store(for_codei); // ctx()->try_merge_for_iter_store(for_codei);
@ -2405,14 +2396,14 @@ Error* pk_compile(pk_SourceData_ src, CodeObject* out) {
Error* err = pk_Lexer__process(src, &tokens); Error* err = pk_Lexer__process(src, &tokens);
if(err) return err; if(err) return err;
Token* data = (Token*)tokens.data; // Token* data = (Token*)tokens.data;
printf("%s\n", src->filename->data); // printf("%s\n", src->filename->data);
for(int i = 0; i < tokens.count; i++) { // for(int i = 0; i < tokens.count; i++) {
Token* t = data + i; // Token* t = data + i;
c11_string* tmp = c11_string__new2(t->start, t->length); // c11_string* tmp = c11_string__new2(t->start, t->length);
printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], tmp->data); // printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], tmp->data);
c11_string__delete(tmp); // c11_string__delete(tmp);
} // }
Compiler compiler; Compiler compiler;
Compiler__ctor(&compiler, src, tokens); Compiler__ctor(&compiler, src, tokens);

View File

@ -201,10 +201,6 @@ static Error* SyntaxError(const char* fmt, ...){
return NULL; return NULL;
} }
static Error* NeedMoreLines(){
return NULL;
}
static Error* eat_name(pk_Lexer* self){ static Error* eat_name(pk_Lexer* self){
self->curr_char--; self->curr_char--;
while(true) { while(true) {
@ -246,11 +242,11 @@ static Error* eat_name(pk_Lexer* self){
c11_sv name = {self->token_start, length}; c11_sv name = {self->token_start, length};
if(self->src->mode == JSON_MODE) { if(self->src->mode == JSON_MODE) {
if(c11__sveq(name, "true")) { if(c11__sveq2(name, "true")) {
add_token(self, TK_TRUE); add_token(self, TK_TRUE);
} else if(c11__sveq(name, "false")) { } else if(c11__sveq2(name, "false")) {
add_token(self, TK_FALSE); add_token(self, TK_FALSE);
} else if(c11__sveq(name, "null")) { } else if(c11__sveq2(name, "null")) {
add_token(self, TK_NONE); add_token(self, TK_NONE);
} else { } else {
return SyntaxError("invalid JSON token"); return SyntaxError("invalid JSON token");
@ -265,7 +261,7 @@ static Error* eat_name(pk_Lexer* self){
c11__lower_bound(const char*, KW_BEGIN, KW_COUNT, name, less, &out); c11__lower_bound(const char*, KW_BEGIN, KW_COUNT, name, less, &out);
#undef less #undef less
if(out != KW_COUNT && c11__sveq(name, KW_BEGIN[out])) { if(out != KW_COUNT && c11__sveq2(name, KW_BEGIN[out])) {
add_token(self, (TokenIndex)(out + TK_FALSE)); add_token(self, (TokenIndex)(out + TK_FALSE));
} else { } else {
add_token(self, TK_ID); add_token(self, TK_ID);
@ -288,9 +284,6 @@ static Error* eat_string_until(pk_Lexer* self, char quote, bool raw, c11_string*
break; break;
} }
if(c == '\0') { if(c == '\0') {
if(quote3 && self->src->mode == REPL_MODE){
return NeedMoreLines();
}
return SyntaxError("EOL while scanning string literal"); return SyntaxError("EOL while scanning string literal");
} }
if(c == '\n') { if(c == '\n') {
@ -431,7 +424,6 @@ static Error* lex_one_token(pk_Lexer* self, bool* eof){
// line continuation character // line continuation character
char c = eatchar_include_newline(self); char c = eatchar_include_newline(self);
if(c != '\n') { if(c != '\n') {
if(self->src->mode == REPL_MODE && c == '\0') return NeedMoreLines();
return SyntaxError("expected newline after line continuation character"); return SyntaxError("expected newline after line continuation character");
} }
eat_spaces(self); eat_spaces(self);

View File

@ -98,8 +98,9 @@ void pk_VM__ctor(pk_VM* self) {
validate(tp_int, pk_VM__new_type(self, "int", tp_object, NULL, false)); validate(tp_int, pk_VM__new_type(self, "int", tp_object, NULL, false));
validate(tp_float, pk_VM__new_type(self, "float", tp_object, NULL, false)); validate(tp_float, pk_VM__new_type(self, "float", tp_object, NULL, false));
pk_number__register();
validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false)); validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false));
pk_number__register();
validate(tp_str, pk_str__register()); validate(tp_str, pk_str__register());
validate(tp_list, pk_list__register()); validate(tp_list, pk_list__register());

View File

@ -339,6 +339,53 @@ static bool _py_float__new__(int argc, py_Ref argv) {
return true; return true;
} }
// tp_bool
static bool _py_bool__new__(int argc, py_Ref argv){
PY_CHECK_ARGC(1);
int res = py_bool(argv);
if(res == -1) return false;
py_newbool(py_retval(), res);
return true;
}
static bool _py_bool__hash__(int argc, py_Ref argv){
PY_CHECK_ARGC(1);
bool res = py_tobool(argv);
py_newint(py_retval(), res);
return true;
}
static bool _py_bool__repr__(int argc, py_Ref argv){
PY_CHECK_ARGC(1);
bool res = py_tobool(argv);
py_newstr(py_retval(), res ? "True" : "False");
return true;
}
static bool _py_bool__eq__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
bool lhs = py_tobool(&argv[0]);
if(argv[1].type == tp_bool){
bool rhs = py_tobool(&argv[1]);
py_newbool(py_retval(), lhs == rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
static bool _py_bool__ne__(int argc, py_Ref argv){
PY_CHECK_ARGC(2);
bool lhs = py_tobool(&argv[0]);
if(argv[1].type == tp_bool){
bool rhs = py_tobool(&argv[1]);
py_newbool(py_retval(), lhs != rhs);
} else {
py_newnotimplemented(py_retval());
}
return true;
}
void pk_number__register() { void pk_number__register() {
/****** tp_int & tp_float ******/ /****** tp_int & tp_float ******/
py_bindmagic(tp_int, __add__, _py_int__add__); py_bindmagic(tp_int, __add__, _py_int__add__);
@ -400,4 +447,11 @@ void pk_number__register() {
// int.bit_length // int.bit_length
py_bindmethod(tp_int, "bit_length", _py_int__bit_length); py_bindmethod(tp_int, "bit_length", _py_int__bit_length);
/* tp_bool */
py_bindmagic(tp_bool, __new__, _py_bool__new__);
py_bindmagic(tp_bool, __hash__, _py_bool__hash__);
py_bindmagic(tp_bool, __repr__, _py_bool__repr__);
py_bindmagic(tp_bool, __eq__, _py_bool__eq__);
py_bindmagic(tp_bool, __ne__, _py_bool__ne__);
} }

View File

@ -4,24 +4,9 @@
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#include "pocketpy/common/sstream.h"
py_Type pk_str__register() { void py_newstr(py_Ref out, const char* data) { return py_newstrn(out, data, strlen(data)); }
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "str", tp_object, NULL, false);
// no need to dtor because the memory is controlled by the object
return type;
}
py_Type pk_bytes__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "bytes", tp_object, NULL, false);
// no need to dtor because the memory is controlled by the object
return type;
}
void py_newstr(py_Ref out, const char* data) {
return py_newstrn(out, data, strlen(data));
}
void py_newstrn(py_Ref out, const char* data, int size) { void py_newstrn(py_Ref out, const char* data, int size) {
pk_ManagedHeap* heap = &pk_current_vm->heap; pk_ManagedHeap* heap = &pk_current_vm->heap;
@ -66,3 +51,233 @@ unsigned char* py_tobytes(const py_Ref self, int* size) {
return ud->data; return ud->data;
} }
////////////////////////////////
static bool _py_str__new__(int argc, py_Ref argv) { return true; }
static bool _py_str__hash__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int size;
const char* data = py_tostrn(&argv[0], &size);
py_i64 res = 0;
for(int i = 0; i < size; i++) {
res = res * 31 + data[i];
}
py_newint(py_retval(), res);
return true;
}
static bool _py_str__len__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_string* self = py_touserdata(&argv[0]);
py_newint(py_retval(), self->size);
return true;
}
static bool _py_str__add__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]);
if(py_arg(1)->type != tp_str) {
py_newnotimplemented(py_retval());
} else {
c11_string* other = py_touserdata(&argv[1]);
int total_size = sizeof(c11_string) + self->size + other->size + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size + other->size;
char* p = (char*)res->data;
memcpy(p, self->data, self->size);
memcpy(p + self->size, other->data, other->size);
p[res->size] = '\0';
}
return true;
}
static bool _py_str__mul__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]);
if(py_arg(1)->type != tp_int) {
py_newnotimplemented(py_retval());
} else {
py_i64 n = py_toint(py_arg(1));
if(n <= 0) {
py_newstr(py_retval(), "");
} else {
int total_size = sizeof(c11_string) + self->size * n + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size * n;
char* p = (char*)res->data;
for(int i = 0; i < n; i++) {
memcpy(p + i * self->size, self->data, self->size);
}
p[res->size] = '\0';
}
}
return true;
}
static bool _py_str__rmul__(int argc, py_Ref argv) { return _py_str__mul__(argc, argv); }
static bool _py_str__contains__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]);
if(py_arg(1)->type != tp_str) {
py_newnotimplemented(py_retval());
} else {
c11_string* other = py_touserdata(&argv[1]);
const char* p = strstr(self->data, other->data);
py_newbool(py_retval(), p != NULL);
}
return true;
}
static bool _py_str__str__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
*py_retval() = argv[0];
return true;
}
static bool _py_str__repr__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
assert(false);
return false;
}
static bool _py_str__iter__(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
assert(false);
return false;
}
static bool _py_str__getitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_int);
c11_sv res = c11_string__u8_getitem(self, py_toint(py_arg(1)));
py_newstrn(py_retval(), res.data, res.size);
return true;
}
#define DEF_STR_CMP_OP(op, f, condition) \
static bool _py_str##op(int argc, py_Ref argv) { \
PY_CHECK_ARGC(2); \
c11_string* self = py_touserdata(&argv[0]); \
if(py_arg(1)->type != tp_str) { \
py_newnotimplemented(py_retval()); \
} else { \
c11_string* other = py_touserdata(&argv[1]); \
int res = c11_sv__cmp(c11_string__sv(self), c11_string__sv(other)); \
py_newbool(py_retval(), condition); \
} \
return true; \
}
DEF_STR_CMP_OP(__eq__, c11__sveq, res)
DEF_STR_CMP_OP(__ne__, c11__sveq, !res)
DEF_STR_CMP_OP(__lt__, c11_sv__cmp, res < 0)
DEF_STR_CMP_OP(__le__, c11_sv__cmp, res <= 0)
DEF_STR_CMP_OP(__gt__, c11_sv__cmp, res > 0)
DEF_STR_CMP_OP(__ge__, c11_sv__cmp, res >= 0)
#undef DEF_STR_CMP_OP
static bool _py_str__lower(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_string* self = py_touserdata(&argv[0]);
int total_size = sizeof(c11_string) + self->size + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size;
char* p = (char*)res->data;
for(int i = 0; i < self->size; i++) {
char c = self->data[i];
p[i] = c >= 'A' && c <= 'Z' ? c + 32 : c;
}
p[res->size] = '\0';
return true;
}
static bool _py_str__upper(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
c11_string* self = py_touserdata(&argv[0]);
int total_size = sizeof(c11_string) + self->size + 1;
c11_string* res = py_newobject(py_retval(), tp_str, 0, total_size);
res->size = self->size;
char* p = (char*)res->data;
for(int i = 0; i < self->size; i++) {
char c = self->data[i];
p[i] = c >= 'a' && c <= 'z' ? c - 32 : c;
}
p[res->size] = '\0';
return true;
}
static bool _py_str__startswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* other = py_touserdata(&argv[1]);
c11_sv _0 = c11_sv__slice2(c11_string__sv(self), 0, other->size);
c11_sv _1 = c11_string__sv(other);
py_newbool(py_retval(), c11__sveq(_0, _1));
return true;
}
static bool _py_str__endswith(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
c11_string* self = py_touserdata(&argv[0]);
PY_CHECK_ARG_TYPE(1, tp_str);
c11_string* other = py_touserdata(&argv[1]);
c11_sv _0 = c11_sv__slice2(c11_string__sv(self), self->size - other->size, self->size);
c11_sv _1 = c11_string__sv(other);
py_newbool(py_retval(), c11__sveq(_0, _1));
return true;
}
static bool _py_str__join(int argc, py_Ref argv) {
assert(false);
// PY_CHECK_ARGC(2);
// c11_sbuf buf;
// c11_sbuf__ctor(&buf);
// c11_string* sep = py_touserdata(&argv[0]);
// py_Ref iter = py_pushtmp();
// py_iter(iter, &argv[1]);
return false;
}
py_Type pk_str__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "str", tp_object, NULL, false);
// no need to dtor because the memory is controlled by the object
py_bindmagic(tp_str, __new__, _py_str__new__);
py_bindmagic(tp_str, __hash__, _py_str__hash__);
py_bindmagic(tp_str, __len__, _py_str__len__);
py_bindmagic(tp_str, __add__, _py_str__add__);
py_bindmagic(tp_str, __mul__, _py_str__mul__);
py_bindmagic(tp_str, __rmul__, _py_str__rmul__);
py_bindmagic(tp_str, __contains__, _py_str__contains__);
py_bindmagic(tp_str, __str__, _py_str__str__);
py_bindmagic(tp_str, __repr__, _py_str__repr__);
py_bindmagic(tp_str, __iter__, _py_str__iter__);
py_bindmagic(tp_str, __getitem__, _py_str__getitem__);
py_bindmagic(tp_str, __eq__, _py_str__eq__);
py_bindmagic(tp_str, __ne__, _py_str__ne__);
py_bindmagic(tp_str, __lt__, _py_str__lt__);
py_bindmagic(tp_str, __le__, _py_str__le__);
py_bindmagic(tp_str, __gt__, _py_str__gt__);
py_bindmagic(tp_str, __ge__, _py_str__ge__);
py_bindmethod(tp_str, "lower", _py_str__lower);
py_bindmethod(tp_str, "upper", _py_str__upper);
py_bindmethod(tp_str, "startswith", _py_str__startswith);
py_bindmethod(tp_str, "endswith", _py_str__endswith);
py_bindmethod(tp_str, "join", _py_str__join);
return type;
}
py_Type pk_bytes__register() {
pk_VM* vm = pk_current_vm;
py_Type type = pk_VM__new_type(vm, "bytes", tp_object, NULL, false);
// no need to dtor because the memory is controlled by the object
return type;
}

View File

@ -49,7 +49,7 @@ void py_newfunction(py_Ref out, py_CFunction f, const char* sig) {
void py_newfunction2(py_Ref out, void py_newfunction2(py_Ref out,
py_CFunction f, py_CFunction f,
const char* sig, const char* sig,
BindType bt, enum BindType bt,
const char* docstring, const char* docstring,
const py_Ref upvalue) {} const py_Ref upvalue) {}
@ -63,7 +63,7 @@ void py_bindmethod(py_Type type, const char *name, py_CFunction f){
py_bindmethod2(type, name, f, BindType_FUNCTION); py_bindmethod2(type, name, f, BindType_FUNCTION);
} }
void py_bindmethod2(py_Type type, const char *name, py_CFunction f, BindType bt){ void py_bindmethod2(py_Type type, const char *name, py_CFunction f, enum BindType bt){
py_TValue tmp; py_TValue tmp;
py_newnativefunc(&tmp, f); py_newnativefunc(&tmp, f);
py_setdict(py_tpobject(type), py_name(name), &tmp); py_setdict(py_tpobject(type), py_name(name), &tmp);
@ -82,10 +82,11 @@ void py_newslice(py_Ref out, const py_Ref start, const py_Ref stop, const py_Ref
py_setslot(out, 2, step); py_setslot(out, 2, step);
} }
void py_newobject(py_Ref out, py_Type type, int slots, int udsize) { void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) {
pk_ManagedHeap* heap = &pk_current_vm->heap; pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize); PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);
out->type = type; out->type = type;
out->is_ptr = true; out->is_ptr = true;
out->_obj = obj; out->_obj = obj;
return PyObject__userdata(obj);
} }

View File

@ -168,7 +168,7 @@ static bool
return false; return false;
} }
disassemble(&co); // disassemble(&co);
Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co); Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co);
pk_VM__push_frame(vm, frame); pk_VM__push_frame(vm, frame);
@ -184,6 +184,10 @@ bool py_exec(const char* source) { return pk_VM__exec(pk_current_vm, source, "<e
bool py_eval(const char* source) { return pk_VM__exec(pk_current_vm, source, "<eval>", EVAL_MODE); } bool py_eval(const char* source) { return pk_VM__exec(pk_current_vm, source, "<eval>", EVAL_MODE); }
bool py_exec2(const char* source, const char* filename, enum CompileMode mode){
return pk_VM__exec(pk_current_vm, source, filename, mode);
}
bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; } bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; }
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; } bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }

View File

@ -1,43 +0,0 @@
#include "pocketpy/tools/repl.hpp"
#include "pocketpy/common/export.h"
namespace pkpy {
REPL::REPL(VM* vm) : vm(vm) {
vm->stdout_write("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
vm->stdout_write(_S("[", sizeof(void*) * 8, " bit] on ", kPlatformStrings[PK_SYS_PLATFORM], "\n"));
vm->stdout_write("https://github.com/pocketpy/pocketpy" "\n");
vm->stdout_write("Type \"exit()\" to exit." "\n");
}
bool REPL::input(std::string line) {
CompileMode mode = REPL_MODE;
if(need_more_lines) {
buffer += line;
buffer += '\n';
int n = buffer.size();
if(n >= need_more_lines) {
for(int i = buffer.size() - need_more_lines; i < buffer.size(); i++) {
// no enough lines
if(buffer[i] != '\n') return true;
}
need_more_lines = 0;
line = buffer;
buffer.clear();
mode = CELL_MODE;
} else {
return true;
}
}
try {
vm->exec(line, "<stdin>", mode);
} catch(NeedMoreLines ne) {
buffer += line;
buffer += '\n';
need_more_lines = ne.is_compiling_class ? 3 : 2;
if(need_more_lines) return true;
}
return false;
}
} // namespace pkpy

View File

@ -19,49 +19,40 @@ char* read_file(const char* path) {
return buffer; return buffer;
} }
static char buf[2048];
int main(int argc, char** argv) { int main(int argc, char** argv) {
#if _WIN32 #if _WIN32
SetConsoleCP(CP_UTF8); SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
#endif #endif
#if 0 if(argc > 2){
py_initialize(); printf("Usage: pocketpy [filename]\n");
const char* source = "1 < 2"; return 0;
if(py_eval(source)) {
// handle the result
bool _L0 = py_tobool(py_retval());
printf("%d\n", _L0);
} }
py_Ref r0 = py_reg(0);
py_Ref r1 = py_reg(1);
py_newint(r0, 1);
py_newfloat(r1, 2.5);
bool ok = py_binaryadd(r0, r1);
assert(ok);
double res = py_tofloat(py_retval());
printf("%f\n", res);
py_finalize();
return 0;
#endif
if(argc != 2) goto __HELP;
char* source = read_file(argv[1]);
py_initialize(); py_initialize();
if(!py_exec(source)) py_printexc(); if(argc == 1){
printf("pocketpy " PK_VERSION " (" __DATE__ ", " __TIME__ ") ");
printf("[%d bit] on %s" "\n", (int)(sizeof(void*) * 8), PY_SYS_PLATFORM_STRING);
printf("https://github.com/pocketpy/pocketpy" "\n");
printf("Type \"exit()\" to exit." "\n");
py_finalize(); while(true){
free(source); int size = py_replinput(buf);
assert(size < sizeof(buf));
return 0; if(size >= 0){
if(!py_exec2(buf, "<stdin>", REPL_MODE)) py_printexc();
}
}
}else{
char* source = read_file(argv[1]);
if(!py_exec(source)) py_printexc();
free(source);
}
__HELP: py_finalize();
printf("Usage: pocketpy [filename]\n");
return 0; return 0;
} }