|
|
@@ -1,11 +1,12 @@
|
|
|
#pragma once
|
|
|
|
|
|
#include "pocketpy/compiler/expr.hpp"
|
|
|
+#include "pocketpy/objects/error.hpp"
|
|
|
|
|
|
namespace pkpy {
|
|
|
|
|
|
-class Compiler;
|
|
|
-typedef void (Compiler::*PrattCallback)();
|
|
|
+struct Compiler;
|
|
|
+typedef Error* (Compiler::*PrattCallback)() noexcept;
|
|
|
|
|
|
struct PrattRule {
|
|
|
PrattCallback prefix;
|
|
|
@@ -13,7 +14,7 @@ struct PrattRule {
|
|
|
Precedence precedence;
|
|
|
};
|
|
|
|
|
|
-class Compiler {
|
|
|
+struct Compiler {
|
|
|
PK_ALWAYS_PASS_BY_POINTER(Compiler)
|
|
|
|
|
|
static PrattRule rules[kTokenCount];
|
|
|
@@ -24,47 +25,41 @@ class Compiler {
|
|
|
bool unknown_global_scope; // for eval/exec() call
|
|
|
// for parsing token stream
|
|
|
int i = 0;
|
|
|
- vector<Token> tokens;
|
|
|
|
|
|
- const Token& prev() const { return tokens[i - 1]; }
|
|
|
+ const Token& tk(int i) const noexcept{ return lexer.nexts[i]; }
|
|
|
+ const Token& prev() const noexcept{ return tk(i - 1); }
|
|
|
+ const Token& curr() const noexcept{ return tk(i); }
|
|
|
+ const Token& next() const noexcept{ return tk(i + 1); }
|
|
|
|
|
|
- const Token& curr() const { return tokens[i]; }
|
|
|
-
|
|
|
- const Token& next() const { return tokens[i + 1]; }
|
|
|
-
|
|
|
- const Token& err() const {
|
|
|
- if(i >= tokens.size()) return prev();
|
|
|
+ const Token& err() const noexcept{
|
|
|
+ if(i >= lexer.nexts.size()) return prev();
|
|
|
return curr();
|
|
|
}
|
|
|
|
|
|
- void advance(int delta = 1) { i += delta; }
|
|
|
-
|
|
|
- CodeEmitContext* ctx() { return &contexts.back(); }
|
|
|
+ void advance(int delta = 1) noexcept{ i += delta; }
|
|
|
|
|
|
- CompileMode mode() const { return lexer.src->mode; }
|
|
|
+ CodeEmitContext* ctx() noexcept{ return &contexts.back(); }
|
|
|
+ vector<Expr*>& s_expr() noexcept{ return ctx()->s_expr; }
|
|
|
|
|
|
- NameScope name_scope() const;
|
|
|
- CodeObject_ push_global_context();
|
|
|
- FuncDecl_ push_f_context(Str name);
|
|
|
- void pop_context();
|
|
|
+ CompileMode mode() const noexcept{ return lexer.src->mode; }
|
|
|
|
|
|
- static void init_pratt_rules();
|
|
|
+ NameScope name_scope() const noexcept;
|
|
|
+ CodeObject_ push_global_context() noexcept;
|
|
|
+ FuncDecl_ push_f_context(Str name) noexcept;
|
|
|
|
|
|
- bool match(TokenIndex expected);
|
|
|
- void consume(TokenIndex expected);
|
|
|
- bool match_newlines_repl();
|
|
|
-
|
|
|
- bool match_newlines(bool repl_throw = false);
|
|
|
- bool match_end_stmt();
|
|
|
- void consume_end_stmt();
|
|
|
+ static void init_pratt_rules() noexcept;
|
|
|
|
|
|
+ bool match(TokenIndex expected) noexcept;
|
|
|
+ bool match_newlines_repl() noexcept{ return match_newlines(mode() == REPL_MODE); }
|
|
|
+ bool match_newlines(bool repl_throw = false) noexcept;
|
|
|
+ bool match_end_stmt() noexcept;
|
|
|
/*************************************************/
|
|
|
- void EXPR();
|
|
|
- void EXPR_TUPLE(bool allow_slice = false);
|
|
|
- Expr* EXPR_VARS(); // special case for `for loop` and `comp`
|
|
|
+ [[nodiscard]] Error* EXPR() noexcept{ return parse_expression(PREC_LOWEST + 1); }
|
|
|
+ [[nodiscard]] Error* EXPR_TUPLE(bool allow_slice = false) noexcept;
|
|
|
+ [[nodiscard]] Error* EXPR_VARS() noexcept; // special case for `for loop` and `comp`
|
|
|
|
|
|
template <typename T, typename... Args>
|
|
|
- T* make_expr(Args&&... args) {
|
|
|
+ T* make_expr(Args&&... args) noexcept{
|
|
|
static_assert(sizeof(T) <= kPoolExprBlockSize);
|
|
|
static_assert(std::is_base_of_v<Expr, T>);
|
|
|
void* p = PoolExpr_alloc();
|
|
|
@@ -73,87 +68,63 @@ class Compiler {
|
|
|
return expr;
|
|
|
}
|
|
|
|
|
|
- void consume_comp(CompExpr* ce, Expr* expr);
|
|
|
-
|
|
|
- void exprLiteral();
|
|
|
- void exprLong();
|
|
|
- void exprImag();
|
|
|
- void exprBytes();
|
|
|
- void exprFString();
|
|
|
- void exprLambda();
|
|
|
- void exprOr();
|
|
|
- void exprAnd();
|
|
|
- void exprTernary();
|
|
|
- void exprBinaryOp();
|
|
|
- void exprNot();
|
|
|
- void exprUnaryOp();
|
|
|
- void exprGroup();
|
|
|
- void exprList();
|
|
|
- void exprMap();
|
|
|
- void exprCall();
|
|
|
- void exprName();
|
|
|
- void exprAttrib();
|
|
|
- void exprSlice0();
|
|
|
- void exprSlice1();
|
|
|
- void exprSubscr();
|
|
|
- void exprLiteral0();
|
|
|
-
|
|
|
- void compile_block_body(void (Compiler::*callback)() = nullptr);
|
|
|
- void compile_normal_import();
|
|
|
- void compile_from_import();
|
|
|
- bool is_expression(bool allow_slice = false);
|
|
|
- void parse_expression(int precedence, bool allow_slice = false);
|
|
|
- void compile_if_stmt();
|
|
|
- void compile_while_loop();
|
|
|
- void compile_for_loop();
|
|
|
- void compile_try_except();
|
|
|
- void compile_decorated();
|
|
|
-
|
|
|
- bool try_compile_assignment();
|
|
|
- void compile_stmt();
|
|
|
- void consume_type_hints();
|
|
|
- void _add_decorators(const Expr_vector& decorators);
|
|
|
- void compile_class(const Expr_vector& decorators = {});
|
|
|
- void _compile_f_args(FuncDecl_ decl, bool enable_type_hints);
|
|
|
- void compile_function(const Expr_vector& decorators = {});
|
|
|
-
|
|
|
- PyVar to_object(const TokenValue& value);
|
|
|
- PyVar read_literal();
|
|
|
-
|
|
|
- void SyntaxError(Str msg) { lexer.throw_err("SyntaxError", msg, err().line, err().start); }
|
|
|
-
|
|
|
- void SyntaxError() { lexer.throw_err("SyntaxError", "invalid syntax", err().line, err().start); }
|
|
|
-
|
|
|
- void IndentationError(Str msg) { lexer.throw_err("IndentationError", msg, err().line, err().start); }
|
|
|
+ [[nodiscard]] Error* consume_comp(Opcode op0, Opcode op1) noexcept;
|
|
|
+ [[nodiscard]] Error* pop_context() noexcept;
|
|
|
+
|
|
|
+ Error* exprLiteral() noexcept;
|
|
|
+ Error* exprLong() noexcept;
|
|
|
+ Error* exprImag() noexcept;
|
|
|
+ Error* exprBytes() noexcept;
|
|
|
+ Error* exprFString() noexcept;
|
|
|
+ Error* exprLambda() noexcept;
|
|
|
+ Error* exprOr() noexcept;
|
|
|
+ Error* exprAnd() noexcept;
|
|
|
+ Error* exprTernary() noexcept;
|
|
|
+ Error* exprBinaryOp() noexcept;
|
|
|
+ Error* exprNot() noexcept;
|
|
|
+ Error* exprUnaryOp() noexcept;
|
|
|
+ Error* exprGroup() noexcept;
|
|
|
+ Error* exprList() noexcept;
|
|
|
+ Error* exprMap() noexcept;
|
|
|
+ Error* exprCall() noexcept;
|
|
|
+ Error* exprName() noexcept;
|
|
|
+ Error* exprAttrib() noexcept;
|
|
|
+ Error* exprSlice0() noexcept;
|
|
|
+ Error* exprSlice1() noexcept;
|
|
|
+ Error* exprSubscr() noexcept;
|
|
|
+ Error* exprLiteral0() noexcept;
|
|
|
+
|
|
|
+ bool is_expression(bool allow_slice = false) noexcept;
|
|
|
+
|
|
|
+ [[nodiscard]] Error* compile_block_body(PrattCallback callback = NULL) noexcept;
|
|
|
+ [[nodiscard]] Error* compile_normal_import() noexcept;
|
|
|
+ [[nodiscard]] Error* compile_from_import() noexcept;
|
|
|
+ [[nodiscard]] Error* parse_expression(int precedence, bool allow_slice = false) noexcept;
|
|
|
+ [[nodiscard]] Error* compile_if_stmt() noexcept;
|
|
|
+ [[nodiscard]] Error* compile_while_loop() noexcept;
|
|
|
+ [[nodiscard]] Error* compile_for_loop() noexcept;
|
|
|
+ [[nodiscard]] Error* compile_try_except() noexcept;
|
|
|
+ [[nodiscard]] Error* compile_decorated() noexcept;
|
|
|
+
|
|
|
+ [[nodiscard]] Error* try_compile_assignment(bool* is_assign) noexcept;
|
|
|
+ [[nodiscard]] Error* compile_stmt() noexcept;
|
|
|
+ [[nodiscard]] Error* consume_type_hints() noexcept;
|
|
|
+ [[nodiscard]] Error* _compile_f_args(FuncDecl_ decl, bool enable_type_hints) noexcept;
|
|
|
+ [[nodiscard]] Error* compile_function(int decorators = 0) noexcept;
|
|
|
+ [[nodiscard]] Error* compile_class(int decorators = 0) noexcept;
|
|
|
+
|
|
|
+ PyVar to_object(const TokenValue& value) noexcept;
|
|
|
+
|
|
|
+ [[nodiscard]] Error* read_literal(PyVar* out) noexcept;
|
|
|
+
|
|
|
+ [[nodiscard]] Error* SyntaxError(const char* msg = "invalid syntax", ...) noexcept;
|
|
|
+ [[nodiscard]] Error* IndentationError(const char* msg) noexcept{ return lexer._error(false, "IndentationError", msg, {}); }
|
|
|
+ [[nodiscard]] Error* NeedMoreLines() noexcept{ return lexer._error(false, "NeedMoreLines", "", {}, (i64)ctx()->is_compiling_class); }
|
|
|
|
|
|
public:
|
|
|
- Compiler(VM* vm, std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope = false);
|
|
|
- Str precompile();
|
|
|
- void from_precompiled(const char* source);
|
|
|
- CodeObject_ compile();
|
|
|
-};
|
|
|
-
|
|
|
-struct TokenDeserializer {
|
|
|
- const char* curr;
|
|
|
- const char* source;
|
|
|
-
|
|
|
- TokenDeserializer(const char* source) : curr(source), source(source) {}
|
|
|
-
|
|
|
- char read_char() { return *curr++; }
|
|
|
-
|
|
|
- bool match_char(char c) {
|
|
|
- if(*curr == c) {
|
|
|
- curr++;
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- std::string_view read_string(char c);
|
|
|
- Str read_string_from_hex(char c);
|
|
|
- int read_count();
|
|
|
- i64 read_uint(char c);
|
|
|
- f64 read_float(char c);
|
|
|
+ Compiler(VM* vm, std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope = false) noexcept;
|
|
|
+ [[nodiscard]] Error* compile(CodeObject_* out) noexcept;
|
|
|
+ ~Compiler();
|
|
|
};
|
|
|
|
|
|
} // namespace pkpy
|