mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
Compare commits
3 Commits
84004349db
...
f93aefdbe5
Author | SHA1 | Date | |
---|---|---|---|
|
f93aefdbe5 | ||
|
d74ca31f68 | ||
|
a86c134377 |
@ -1,39 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
// clang-format off
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
|
||||
//define something for Windows (32-bit and 64-bit, this part is common)
|
||||
#define PK_EXPORT __declspec(dllexport)
|
||||
#define PK_SYS_PLATFORM 0
|
||||
#define PY_SYS_PLATFORM 0
|
||||
#define PY_SYS_PLATFORM_STRING "win32"
|
||||
#elif __EMSCRIPTEN__
|
||||
#define PK_EXPORT
|
||||
#define PK_SYS_PLATFORM 1
|
||||
#define PY_SYS_PLATFORM 1
|
||||
#define PY_SYS_PLATFORM_STRING "emscripten"
|
||||
#elif __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_IPHONE_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
|
||||
// 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
|
||||
#define PK_SYS_PLATFORM 3
|
||||
#define PY_SYS_PLATFORM 3
|
||||
#define PY_SYS_PLATFORM_STRING "darwin"
|
||||
#else
|
||||
# error "Unknown Apple platform"
|
||||
#endif
|
||||
#define PK_EXPORT __attribute__((visibility("default")))
|
||||
#elif __ANDROID__
|
||||
#define PK_EXPORT __attribute__((visibility("default")))
|
||||
#define PK_SYS_PLATFORM 4
|
||||
#define PY_SYS_PLATFORM 4
|
||||
#define PY_SYS_PLATFORM_STRING "android"
|
||||
#elif __linux__
|
||||
#define PK_EXPORT __attribute__((visibility("default")))
|
||||
#define PK_SYS_PLATFORM 5
|
||||
#define PY_SYS_PLATFORM 5
|
||||
#define PY_SYS_PLATFORM_STRING "linux"
|
||||
#else
|
||||
#define PK_EXPORT
|
||||
#define PK_SYS_PLATFORM 6
|
||||
#define PY_SYS_PLATFORM 6
|
||||
#define PY_SYS_PLATFORM_STRING "unknown"
|
||||
#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
|
||||
#else
|
||||
#define PK_IS_DESKTOP_PLATFORM 0
|
||||
|
@ -32,7 +32,8 @@ int c11_sv__cmp(c11_sv self, c11_sv other);
|
||||
int c11_sv__cmp2(c11_sv self, const char* other);
|
||||
|
||||
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__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);
|
||||
|
||||
// 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__slice2(c11_sv sv, int start, int stop);
|
||||
c11_sv c11_sv__strip(c11_sv sv, bool left, bool right);
|
||||
|
@ -21,8 +21,6 @@ extern "C" {
|
||||
// global constants
|
||||
#define PK_HEX_TABLE "0123456789abcdef"
|
||||
|
||||
extern const char* kPlatformStrings[];
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define c11__unreachedable() __assume(0)
|
||||
#else
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include "pocketpy/common/str.h"
|
||||
#include "pocketpy/common/vector.h"
|
||||
|
||||
@ -8,7 +9,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum CompileMode { EXEC_MODE, EVAL_MODE, REPL_MODE, JSON_MODE, CELL_MODE };
|
||||
|
||||
struct pk_SourceData {
|
||||
RefCounted rc;
|
||||
|
@ -4,6 +4,9 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "pocketpy/common/config.h"
|
||||
#include "pocketpy/common/export.h"
|
||||
|
||||
/************* Public Types *************/
|
||||
typedef struct py_TValue py_TValue;
|
||||
typedef uint16_t py_Name;
|
||||
@ -29,11 +32,19 @@ typedef py_TValue* py_TmpRef;
|
||||
/// @return true if the function is successful.
|
||||
typedef bool (*py_CFunction)(int argc, py_StackRef argv);
|
||||
|
||||
typedef enum BindType {
|
||||
enum BindType {
|
||||
BindType_FUNCTION,
|
||||
BindType_STATICMETHOD,
|
||||
BindType_CLASSMETHOD,
|
||||
} BindType;
|
||||
};
|
||||
|
||||
enum CompileMode {
|
||||
EXEC_MODE,
|
||||
EVAL_MODE,
|
||||
REPL_MODE,
|
||||
JSON_MODE,
|
||||
CELL_MODE
|
||||
};
|
||||
|
||||
/************* Global VMs *************/
|
||||
void py_initialize();
|
||||
@ -44,6 +55,7 @@ bool py_exec(const char* source);
|
||||
/// Eval a simple expression.
|
||||
/// The result will be set to `py_retval()`.
|
||||
bool py_eval(const char* source);
|
||||
bool py_exec2(const char* source, const char* filename, enum CompileMode mode);
|
||||
|
||||
/************* Values Creation *************/
|
||||
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,
|
||||
py_CFunction,
|
||||
const char* sig,
|
||||
BindType bt,
|
||||
enum BindType bt,
|
||||
const char* docstring,
|
||||
const py_Ref upvalue);
|
||||
// old style argc-based function
|
||||
@ -92,7 +104,7 @@ void py_newnativefunc(py_Ref out, py_CFunction);
|
||||
/// @param type type of the object.
|
||||
/// @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.
|
||||
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 *************/
|
||||
py_i64 py_toint(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);
|
||||
|
||||
/************* References *************/
|
||||
#define PY_CHECK_ARGC(n) \
|
||||
#define PY_CHECK_ARGC(n) \
|
||||
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)
|
||||
|
||||
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,
|
||||
const char* sig,
|
||||
py_CFunction f,
|
||||
BindType bt,
|
||||
enum BindType bt,
|
||||
const char* docstring,
|
||||
const py_Ref upvalue);
|
||||
// old style argc-based bindings
|
||||
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);
|
||||
|
||||
/// 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);
|
||||
|
||||
/// Check if the object is an instance of the given type.
|
||||
/// Re
|
||||
bool py_checktype(const py_Ref self, py_Type type);
|
||||
|
||||
int py_replinput(char* buf);
|
||||
|
||||
/// Python favored string formatting.
|
||||
/// %d: int
|
||||
/// %i: py_i64 (int64_t)
|
||||
@ -379,12 +393,13 @@ enum py_PredefinedTypes {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Some notes:
|
||||
|
||||
## Macros
|
||||
1. Function macros are partial functions. They can be used as normal expressions. Use the same naming convention as functions.
|
||||
2. Snippet macros are `do {...} while(0)` blocks. They cannot be used as expressions. Use `UPPER_CASE` naming convention.
|
||||
1. Function macros are partial functions. They can be used as normal expressions. Use the same
|
||||
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.
|
||||
*/
|
@ -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
|
@ -220,3 +220,38 @@ void pk_sprintf(c11_sbuf* ss, const char* fmt, ...) {
|
||||
pk_vsprintf(ss, fmt, 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;
|
||||
}
|
@ -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__slice2(c11_sv sv, int start, int stop) {
|
||||
if(start < 0) start = 0;
|
||||
if(stop < start) stop = start;
|
||||
if(stop > sv.size) stop = sv.size;
|
||||
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__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);
|
||||
if(a.size != size) return false;
|
||||
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)};
|
||||
if(base == -1) {
|
||||
if(c11__sveq(prefix, "0b"))
|
||||
if(c11__sveq2(prefix, "0b"))
|
||||
base = 2;
|
||||
else if(c11__sveq(prefix, "0o"))
|
||||
else if(c11__sveq2(prefix, "0o"))
|
||||
base = 8;
|
||||
else if(c11__sveq(prefix, "0x"))
|
||||
else if(c11__sveq2(prefix, "0x"))
|
||||
base = 16;
|
||||
else
|
||||
base = 10;
|
||||
@ -276,7 +267,7 @@ IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base) {
|
||||
return IntParsing_SUCCESS;
|
||||
} else if(base == 2) {
|
||||
// 2-base 0b101010
|
||||
if(c11__sveq(prefix, "0b")) {
|
||||
if(c11__sveq2(prefix, "0b")) {
|
||||
// text.remove_prefix(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;
|
||||
} else if(base == 8) {
|
||||
// 8-base 0o123
|
||||
if(c11__sveq(prefix, "0o")) {
|
||||
if(c11__sveq2(prefix, "0o")) {
|
||||
// text.remove_prefix(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;
|
||||
} else if(base == 16) {
|
||||
// 16-base 0x123
|
||||
if(c11__sveq(prefix, "0x")) {
|
||||
if(c11__sveq2(prefix, "0x")) {
|
||||
// text.remove_prefix(2);
|
||||
text = (c11_sv){text.data + 2, text.size - 2};
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
const char* kPlatformStrings[] = {
|
||||
"win32", // 0
|
||||
"emscripten", // 1
|
||||
"ios", // 2
|
||||
"darwin", // 3
|
||||
"android", // 4
|
||||
"linux", // 5
|
||||
"unknown" // 6
|
||||
};
|
@ -1454,7 +1454,7 @@ static void Compiler__dtor(Compiler* self) {
|
||||
#define mode() self->src->mode
|
||||
#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) \
|
||||
if(!match(expected)) \
|
||||
@ -1463,12 +1463,7 @@ static void Compiler__dtor(Compiler* self) {
|
||||
pk_TokenSymbols[curr()->type]);
|
||||
#define consume_end_stmt() \
|
||||
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) \
|
||||
if((err = B)) return err
|
||||
|
||||
@ -1480,8 +1475,6 @@ static NameScope name_scope(Compiler* self) {
|
||||
|
||||
#define SyntaxError(...) NULL
|
||||
|
||||
static Error* NeedMoreLines() { return NULL; }
|
||||
|
||||
/* Matchers */
|
||||
static bool is_expression(Compiler* self, bool allow_slice) {
|
||||
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)
|
||||
|
||||
static bool match_newlines_repl(Compiler* self, bool* need_more_lines) {
|
||||
static bool match_newlines_impl(Compiler* self) {
|
||||
bool consumed = false;
|
||||
if(curr()->type == TK_EOL) {
|
||||
while(curr()->type == TK_EOL)
|
||||
advance();
|
||||
consumed = true;
|
||||
}
|
||||
if(need_more_lines) { *need_more_lines = (mode() == REPL_MODE && curr()->type == TK_EOF); }
|
||||
return consumed;
|
||||
}
|
||||
|
||||
@ -1540,11 +1532,11 @@ static Error* EXPR_TUPLE_ALLOW_SLICE(Compiler* self, bool allow_slice) {
|
||||
// tuple expression // (a, )
|
||||
int count = 1;
|
||||
do {
|
||||
if(curr()->brackets_level) check_newlines_repl();
|
||||
if(curr()->brackets_level) match_newlines();
|
||||
if(!is_expression(self, allow_slice)) break;
|
||||
check(parse_expression(self, PREC_LOWEST + 1, allow_slice));
|
||||
count += 1;
|
||||
if(curr()->brackets_level) check_newlines_repl();
|
||||
if(curr()->brackets_level) match_newlines();
|
||||
} while(match(TK_COMMA));
|
||||
// pop `count` expressions from the stack and merge them into a TupleExpr
|
||||
SequenceExpr* e = TupleExpr__new(prev()->line, count);
|
||||
@ -1791,9 +1783,9 @@ static Error* exprUnaryOp(Compiler* self) {
|
||||
static Error* exprGroup(Compiler* self) {
|
||||
Error* err;
|
||||
int line = prev()->line;
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
check(EXPR_TUPLE(self)); // () is just for change precedence
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
consume(TK_RPAREN);
|
||||
if(Ctx__s_top(ctx())->vt->is_tuple) return NULL;
|
||||
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]
|
||||
consume(TK_IN);
|
||||
check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter]
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
if(match(TK_IF)) {
|
||||
check(parse_expression(self, PREC_TERNARY + 1, false)); // [expr, vars, iter, cond]
|
||||
has_cond = true;
|
||||
@ -1844,7 +1836,7 @@ static Error* consume_comp(Compiler* self, Opcode op0, Opcode op1) {
|
||||
ce->vars = Ctx__s_popx(ctx());
|
||||
ce->expr = Ctx__s_popx(ctx());
|
||||
Ctx__s_push(ctx(), (Expr*)ce);
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1853,17 +1845,17 @@ static Error* exprList(Compiler* self) {
|
||||
int line = prev()->line;
|
||||
int count = 0;
|
||||
do {
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
if(curr()->type == TK_RBRACKET) break;
|
||||
check(EXPR(self));
|
||||
count += 1;
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
if(count == 1 && match(TK_FOR)) {
|
||||
check(consume_comp(self, OP_BUILD_LIST, OP_LIST_APPEND));
|
||||
consume(TK_RBRACKET);
|
||||
return NULL;
|
||||
}
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
} while(match(TK_COMMA));
|
||||
consume(TK_RBRACKET);
|
||||
SequenceExpr* e = ListExpr__new(line, count);
|
||||
@ -1880,7 +1872,7 @@ static Error* exprMap(Compiler* self) {
|
||||
bool parsing_dict = false; // {...} may be dict or set
|
||||
int count = 0;
|
||||
do {
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
if(curr()->type == TK_RBRACE) break;
|
||||
check(EXPR(self)); // [key]
|
||||
if(curr()->type == TK_COLON) { parsing_dict = true; }
|
||||
@ -1889,7 +1881,7 @@ static Error* exprMap(Compiler* self) {
|
||||
check(EXPR(self)); // [key, value]
|
||||
}
|
||||
count += 1; // key-value pair count
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
if(count == 1 && match(TK_FOR)) {
|
||||
if(parsing_dict) {
|
||||
check(consume_comp(self, OP_BUILD_DICT, OP_DICT_ADD));
|
||||
@ -1899,7 +1891,7 @@ static Error* exprMap(Compiler* self) {
|
||||
consume(TK_RBRACE);
|
||||
return NULL;
|
||||
}
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
} while(match(TK_COMMA));
|
||||
consume(TK_RBRACE);
|
||||
|
||||
@ -1922,7 +1914,7 @@ static Error* exprCall(Compiler* self) {
|
||||
CallExpr* e = CallExpr__new(prev()->line, Ctx__s_popx(ctx()));
|
||||
Ctx__s_push(ctx(), (Expr*)e); // push onto the stack in advance
|
||||
do {
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
if(curr()->type == TK_RPAREN) break;
|
||||
if(curr()->type == TK_ID && next()->type == TK_ASSIGN) {
|
||||
consume(TK_ID);
|
||||
@ -1948,7 +1940,7 @@ static Error* exprCall(Compiler* self) {
|
||||
c11_vector__push(Expr*, &e->args, Ctx__s_popx(ctx()));
|
||||
}
|
||||
}
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
} while(match(TK_COMMA));
|
||||
consume(TK_RPAREN);
|
||||
return NULL;
|
||||
@ -1998,9 +1990,9 @@ static Error* exprSlice1(Compiler* self) {
|
||||
static Error* exprSubscr(Compiler* self) {
|
||||
Error* err;
|
||||
int line = prev()->line;
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
check(EXPR_TUPLE_ALLOW_SLICE(self, true));
|
||||
check_newlines_repl();
|
||||
match_newlines();
|
||||
consume(TK_RBRACKET); // [lhs, rhs]
|
||||
SubscrExpr* e = SubscrExpr__new(line);
|
||||
e->rhs = Ctx__s_popx(ctx()); // [lhs]
|
||||
@ -2032,9 +2024,7 @@ static Error* compile_block_body(Compiler* self, PrattCallback callback) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool need_more_lines;
|
||||
bool consumed = match_newlines_repl(self, &need_more_lines);
|
||||
if(need_more_lines) return NeedMoreLines();
|
||||
bool consumed = match_newlines();
|
||||
if(!consumed) return SyntaxError("expected a new line after ':'");
|
||||
|
||||
consume(TK_INDENT);
|
||||
@ -2090,17 +2080,18 @@ static Error* compile_while_loop(Compiler* self) {
|
||||
|
||||
static Error* compile_for_loop(Compiler* self) {
|
||||
Error* err;
|
||||
check(EXPR_VARS(self)); // [vars]
|
||||
check(EXPR_VARS(self)); // [vars]
|
||||
consume(TK_IN);
|
||||
check(EXPR_TUPLE(self)); // [vars, iter]
|
||||
Ctx__s_emit_top(ctx()); // [vars]
|
||||
check(EXPR_TUPLE(self)); // [vars, iter]
|
||||
Ctx__s_emit_top(ctx()); // [vars]
|
||||
Ctx__emit_(ctx(), OP_GET_ITER_NEW, BC_NOARG, BC_KEEPLINE);
|
||||
CodeBlock* block = Ctx__enter_block(ctx(), CodeBlockType_FOR_LOOP);
|
||||
int for_codei = Ctx__emit_(ctx(), OP_FOR_ITER, ctx()->curr_iblock, BC_KEEPLINE);
|
||||
Expr* vars = Ctx__s_popx(ctx());
|
||||
bool ok = vtemit_store(vars, ctx());
|
||||
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: ??
|
||||
// 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);
|
||||
if(err) return err;
|
||||
|
||||
Token* data = (Token*)tokens.data;
|
||||
printf("%s\n", src->filename->data);
|
||||
for(int i = 0; i < tokens.count; i++) {
|
||||
Token* t = data + i;
|
||||
c11_string* tmp = c11_string__new2(t->start, t->length);
|
||||
printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], tmp->data);
|
||||
c11_string__delete(tmp);
|
||||
}
|
||||
// Token* data = (Token*)tokens.data;
|
||||
// printf("%s\n", src->filename->data);
|
||||
// for(int i = 0; i < tokens.count; i++) {
|
||||
// Token* t = data + i;
|
||||
// c11_string* tmp = c11_string__new2(t->start, t->length);
|
||||
// printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], tmp->data);
|
||||
// c11_string__delete(tmp);
|
||||
// }
|
||||
|
||||
Compiler compiler;
|
||||
Compiler__ctor(&compiler, src, tokens);
|
||||
|
@ -201,10 +201,6 @@ static Error* SyntaxError(const char* fmt, ...){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* NeedMoreLines(){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Error* eat_name(pk_Lexer* self){
|
||||
self->curr_char--;
|
||||
while(true) {
|
||||
@ -246,11 +242,11 @@ static Error* eat_name(pk_Lexer* self){
|
||||
c11_sv name = {self->token_start, length};
|
||||
|
||||
if(self->src->mode == JSON_MODE) {
|
||||
if(c11__sveq(name, "true")) {
|
||||
if(c11__sveq2(name, "true")) {
|
||||
add_token(self, TK_TRUE);
|
||||
} else if(c11__sveq(name, "false")) {
|
||||
} else if(c11__sveq2(name, "false")) {
|
||||
add_token(self, TK_FALSE);
|
||||
} else if(c11__sveq(name, "null")) {
|
||||
} else if(c11__sveq2(name, "null")) {
|
||||
add_token(self, TK_NONE);
|
||||
} else {
|
||||
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);
|
||||
#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));
|
||||
} else {
|
||||
add_token(self, TK_ID);
|
||||
@ -288,9 +284,6 @@ static Error* eat_string_until(pk_Lexer* self, char quote, bool raw, c11_string*
|
||||
break;
|
||||
}
|
||||
if(c == '\0') {
|
||||
if(quote3 && self->src->mode == REPL_MODE){
|
||||
return NeedMoreLines();
|
||||
}
|
||||
return SyntaxError("EOL while scanning string literal");
|
||||
}
|
||||
if(c == '\n') {
|
||||
@ -431,7 +424,6 @@ static Error* lex_one_token(pk_Lexer* self, bool* eof){
|
||||
// line continuation character
|
||||
char c = eatchar_include_newline(self);
|
||||
if(c != '\n') {
|
||||
if(self->src->mode == REPL_MODE && c == '\0') return NeedMoreLines();
|
||||
return SyntaxError("expected newline after line continuation character");
|
||||
}
|
||||
eat_spaces(self);
|
||||
|
@ -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_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));
|
||||
pk_number__register();
|
||||
|
||||
validate(tp_str, pk_str__register());
|
||||
|
||||
validate(tp_list, pk_list__register());
|
||||
|
@ -339,6 +339,53 @@ static bool _py_float__new__(int argc, py_Ref argv) {
|
||||
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() {
|
||||
/****** tp_int & tp_float ******/
|
||||
py_bindmagic(tp_int, __add__, _py_int__add__);
|
||||
@ -400,4 +447,11 @@ void pk_number__register() {
|
||||
|
||||
// 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__);
|
||||
}
|
@ -4,24 +4,9 @@
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
|
||||
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
|
||||
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_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) {
|
||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||
@ -66,3 +51,233 @@ unsigned char* py_tobytes(const py_Ref self, int* size) {
|
||||
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;
|
||||
}
|
@ -49,7 +49,7 @@ void py_newfunction(py_Ref out, py_CFunction f, const char* sig) {
|
||||
void py_newfunction2(py_Ref out,
|
||||
py_CFunction f,
|
||||
const char* sig,
|
||||
BindType bt,
|
||||
enum BindType bt,
|
||||
const char* docstring,
|
||||
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);
|
||||
}
|
||||
|
||||
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_newnativefunc(&tmp, f);
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);
|
||||
out->type = type;
|
||||
out->is_ptr = true;
|
||||
out->_obj = obj;
|
||||
return PyObject__userdata(obj);
|
||||
}
|
||||
|
@ -168,7 +168,7 @@ static bool
|
||||
return false;
|
||||
}
|
||||
|
||||
disassemble(&co);
|
||||
// disassemble(&co);
|
||||
|
||||
Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co);
|
||||
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_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_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
||||
|
@ -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
|
55
src2/main.c
55
src2/main.c
@ -19,49 +19,40 @@ char* read_file(const char* path) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char buf[2048];
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
#if _WIN32
|
||||
SetConsoleCP(CP_UTF8);
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
py_initialize();
|
||||
const char* source = "1 < 2";
|
||||
|
||||
if(py_eval(source)) {
|
||||
// handle the result
|
||||
bool _L0 = py_tobool(py_retval());
|
||||
printf("%d\n", _L0);
|
||||
if(argc > 2){
|
||||
printf("Usage: pocketpy [filename]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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();
|
||||
free(source);
|
||||
|
||||
return 0;
|
||||
while(true){
|
||||
int size = py_replinput(buf);
|
||||
assert(size < sizeof(buf));
|
||||
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:
|
||||
printf("Usage: pocketpy [filename]\n");
|
||||
py_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user