فهرست منبع

remove stack<>

blueloveTH 1 سال پیش
والد
کامیت
be3d4ffaf9

+ 6 - 49
include/pocketpy/common/vector.hpp

@@ -213,6 +213,12 @@ struct vector {
         if constexpr(!std::is_trivially_destructible_v<T>) { _data[_size].~T(); }
     }
 
+    T popx_back() {
+        T retval = std::move(back());
+        pop_back();
+        return retval;
+    }
+
     void clear() {
         std::destroy(begin(), end());
         _size = 0;
@@ -240,55 +246,6 @@ struct vector {
     }
 };
 
-template <typename T, typename Container = vector<T>>
-class stack {
-    Container vec;
-
-public:
-    void push(const T& t) { vec.push_back(t); }
-
-    void push(T&& t) { vec.push_back(std::move(t)); }
-
-    template <typename... Args>
-    void emplace(Args&&... args) {
-        vec.emplace_back(std::forward<Args>(args)...);
-    }
-
-    void pop() { vec.pop_back(); }
-
-    void clear() { vec.clear(); }
-
-    bool empty() const { return vec.empty(); }
-
-    typename Container::size_type size() const { return vec.size(); }
-
-    T& top() { return vec.back(); }
-
-    const T& top() const { return vec.back(); }
-
-    T popx() {
-        T t = std::move(vec.back());
-        vec.pop_back();
-        return t;
-    }
-
-    void reserve(int n) { vec.reserve(n); }
-
-    Container& container() { return vec; }
-
-    const Container& container() const { return vec; }
-};
-
-template <typename T, typename Container = vector<T>>
-class stack_no_copy : public stack<T, Container> {
-public:
-    stack_no_copy() = default;
-    stack_no_copy(const stack_no_copy& other) = delete;
-    stack_no_copy& operator= (const stack_no_copy& other) = delete;
-    stack_no_copy(stack_no_copy&& other) noexcept = default;
-    stack_no_copy& operator= (stack_no_copy&& other) noexcept = default;
-};
-
 }  // namespace pkpy
 
 namespace pkpy {

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

@@ -19,7 +19,7 @@ class Compiler {
     static PrattRule rules[kTokenCount];
 
     Lexer lexer;
-    stack_no_copy<CodeEmitContext> contexts;
+    vector<CodeEmitContext> contexts;
     VM* vm;
     bool unknown_global_scope;  // for eval/exec() call
     // for parsing token stream
@@ -39,7 +39,7 @@ class Compiler {
 
     void advance(int delta = 1) { i += delta; }
 
-    CodeEmitContext* ctx() { return &contexts.top(); }
+    CodeEmitContext* ctx() { return &contexts.back(); }
 
     CompileMode mode() const { return lexer.src->mode; }
 

+ 2 - 4
include/pocketpy/compiler/expr.hpp

@@ -110,9 +110,7 @@ struct CodeEmitContext {
     VM* vm;
     FuncDecl_ func;  // optional
     CodeObject_ co;  // 1 CodeEmitContext <=> 1 CodeObject_
-    // some bugs on MSVC (error C2280) when using Expr_vector
-    // so we use stack_no_copy instead
-    stack_no_copy<Expr_> s_expr;
+    vector<Expr_> s_expr;
     int level;
     vector<Str> global_names;
 
@@ -441,7 +439,7 @@ struct BinaryExpr : Expr {
     BinaryExpr(bool inplace = false) : inplace(inplace) {}
 
     bool is_compare() const override;
-    void _emit_compare(CodeEmitContext*, small_vector_2<int, 6>&);
+    void _emit_compare(CodeEmitContext*, small_vector_2<int, 8>&);
     void emit_(CodeEmitContext* ctx) override;
 };
 

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

@@ -105,7 +105,7 @@ struct Lexer {
     const char* curr_char;
     int current_line = 1;
     vector<Token> nexts;
-    stack_no_copy<int, small_vector_2<int, 8>> indents;
+    small_vector_2<int, 8> indents;
     int brackets_level = 0;
 
     char peekchar() const { return *curr_char; }

+ 1 - 1
include/pocketpy/interpreter/profiler.hpp

@@ -26,7 +26,7 @@ struct _FrameRecord {
 struct LineProfiler {
     // filename -> records
     std::map<std::string_view, vector<_LineRecord>> records;
-    stack_no_copy<_FrameRecord> frames;
+    vector<_FrameRecord> frames;
     vector<FuncDecl*> functions;
 
     void begin();

+ 1 - 1
include/pocketpy/interpreter/vm.hpp

@@ -174,7 +174,7 @@ public:
 
     struct {
         PyObject* error;
-        stack_no_copy<ArgsView> s_view;
+        vector<ArgsView> s_view;
     } __c;
 
     PyVar StopIteration;  // a special Exception class

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

@@ -120,7 +120,7 @@ struct FuncDecl {
 
     CodeObject_ code;  // code object of this function
 
-    small_vector_2<int, 6> args;      // indices in co->varnames
+    small_vector_2<int, 8> args;      // indices in co->varnames
     small_vector_2<KwArg, 6> kwargs;  // indices in co->varnames
 
     int starred_arg = -1;    // index in co->varnames, -1 if no *arg

+ 2 - 2
include/pocketpy/objects/error.hpp

@@ -44,7 +44,7 @@ struct Exception {
             src(src), lineno(lineno), cursor(cursor), name(name) {}
     };
 
-    stack<Frame> stacktrace;
+    vector<Frame> stacktrace;
 
     Exception(StrName type) : type(type), is_re(true), _ip_on_error(-1), _code_on_error(nullptr), _self(nullptr) {}
 
@@ -56,7 +56,7 @@ struct Exception {
     template <typename... Args>
     void st_push(Args&&... args) {
         if(stacktrace.size() >= 7) return;
-        stacktrace.emplace(std::forward<Args>(args)...);
+        stacktrace.emplace_back(std::forward<Args>(args)...);
     }
 
     Str summary() const;

+ 84 - 84
src/compiler/compiler.cpp

@@ -16,7 +16,7 @@ NameScope Compiler::name_scope() const {
 CodeObject_ Compiler::push_global_context() {
     CodeObject_ co = std::make_shared<CodeObject>(lexer.src, lexer.src->filename);
     co->start_line = i == 0 ? 1 : prev().line;
-    contexts.push(CodeEmitContext(vm, co, contexts.size()));
+    contexts.push_back(CodeEmitContext(vm, co, contexts.size()));
     return co;
 }
 
@@ -25,8 +25,8 @@ FuncDecl_ Compiler::push_f_context(Str name) {
     decl->code = std::make_shared<CodeObject>(lexer.src, name);
     decl->code->start_line = i == 0 ? 1 : prev().line;
     decl->nested = name_scope() == NAME_LOCAL;
-    contexts.push(CodeEmitContext(vm, decl->code, contexts.size()));
-    contexts.top().func = decl;
+    contexts.push_back(CodeEmitContext(vm, decl->code, contexts.size()));
+    contexts.back().func = decl;
     return decl;
 }
 
@@ -56,7 +56,7 @@ void Compiler::pop_context() {
         }
     }
     // pre-compute func->is_simple
-    FuncDecl_ func = contexts.top().func;
+    FuncDecl_ func = contexts.back().func;
     if(func) {
         // check generator
         for(Bytecode bc: func->code->codes) {
@@ -91,7 +91,7 @@ void Compiler::pop_context() {
 
         assert(func->type != FuncType::UNSET);
     }
-    contexts.pop();
+    contexts.pop_back();
 }
 
 void Compiler::init_pratt_rules() {
@@ -199,15 +199,15 @@ void Compiler::EXPR_TUPLE(bool allow_slice) {
     if(!match(TK(","))) return;
     // tuple expression
     Expr_vector items;
-    items.push_back(ctx()->s_expr.popx());
+    items.push_back(ctx()->s_expr.popx_back());
     do {
         if(curr().brackets_level) match_newlines_repl();
         if(!is_expression(allow_slice)) break;
         parse_expression(PREC_LOWEST + 1, allow_slice);
-        items.push_back(ctx()->s_expr.popx());
+        items.push_back(ctx()->s_expr.popx_back());
         if(curr().brackets_level) match_newlines_repl();
     } while(match(TK(",")));
-    ctx()->s_expr.push(make_expr<TupleExpr>(std::move(items)));
+    ctx()->s_expr.push_back(make_expr<TupleExpr>(std::move(items)));
 }
 
 // special case for `for loop` and `comp`
@@ -221,15 +221,15 @@ Expr_ Compiler::EXPR_VARS() {
     return make_expr<TupleExpr>(std::move(items));
 }
 
-void Compiler::exprLiteral() { ctx()->s_expr.push(make_expr<LiteralExpr>(prev().value)); }
+void Compiler::exprLiteral() { ctx()->s_expr.push_back(make_expr<LiteralExpr>(prev().value)); }
 
-void Compiler::exprLong() { ctx()->s_expr.push(make_expr<LongExpr>(prev().str())); }
+void Compiler::exprLong() { ctx()->s_expr.push_back(make_expr<LongExpr>(prev().str())); }
 
-void Compiler::exprImag() { ctx()->s_expr.push(make_expr<ImagExpr>(std::get<f64>(prev().value))); }
+void Compiler::exprImag() { ctx()->s_expr.push_back(make_expr<ImagExpr>(std::get<f64>(prev().value))); }
 
-void Compiler::exprBytes() { ctx()->s_expr.push(make_expr<BytesExpr>(std::get<Str>(prev().value))); }
+void Compiler::exprBytes() { ctx()->s_expr.push_back(make_expr<BytesExpr>(std::get<Str>(prev().value))); }
 
-void Compiler::exprFString() { ctx()->s_expr.push(make_expr<FStringExpr>(std::get<Str>(prev().value))); }
+void Compiler::exprFString() { ctx()->s_expr.push_back(make_expr<FStringExpr>(std::get<Str>(prev().value))); }
 
 void Compiler::exprLambda() {
     FuncDecl_ decl = push_f_context("<lambda>");
@@ -243,60 +243,60 @@ void Compiler::exprLambda() {
     ctx()->emit_expr();
     ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
     pop_context();
-    ctx()->s_expr.push(std::move(e));
+    ctx()->s_expr.push_back(std::move(e));
 }
 
 void Compiler::exprOr() {
     auto e = make_expr<OrExpr>();
-    e->lhs = ctx()->s_expr.popx();
+    e->lhs = ctx()->s_expr.popx_back();
     parse_expression(PREC_LOGICAL_OR + 1);
-    e->rhs = ctx()->s_expr.popx();
-    ctx()->s_expr.push(std::move(e));
+    e->rhs = ctx()->s_expr.popx_back();
+    ctx()->s_expr.push_back(std::move(e));
 }
 
 void Compiler::exprAnd() {
     auto e = make_expr<AndExpr>();
-    e->lhs = ctx()->s_expr.popx();
+    e->lhs = ctx()->s_expr.popx_back();
     parse_expression(PREC_LOGICAL_AND + 1);
-    e->rhs = ctx()->s_expr.popx();
-    ctx()->s_expr.push(std::move(e));
+    e->rhs = ctx()->s_expr.popx_back();
+    ctx()->s_expr.push_back(std::move(e));
 }
 
 void Compiler::exprTernary() {
     auto e = make_expr<TernaryExpr>();
-    e->true_expr = ctx()->s_expr.popx();
+    e->true_expr = ctx()->s_expr.popx_back();
     // cond
     parse_expression(PREC_TERNARY + 1);
-    e->cond = ctx()->s_expr.popx();
+    e->cond = ctx()->s_expr.popx_back();
     consume(TK("else"));
     // if false
     parse_expression(PREC_TERNARY + 1);
-    e->false_expr = ctx()->s_expr.popx();
-    ctx()->s_expr.push(std::move(e));
+    e->false_expr = ctx()->s_expr.popx_back();
+    ctx()->s_expr.push_back(std::move(e));
 }
 
 void Compiler::exprBinaryOp() {
     auto e = make_expr<BinaryExpr>();
     e->op = prev().type;
-    e->lhs = ctx()->s_expr.popx();
+    e->lhs = ctx()->s_expr.popx_back();
     parse_expression(rules[e->op].precedence + 1);
-    e->rhs = ctx()->s_expr.popx();
-    ctx()->s_expr.push(std::move(e));
+    e->rhs = ctx()->s_expr.popx_back();
+    ctx()->s_expr.push_back(std::move(e));
 }
 
 void Compiler::exprNot() {
     parse_expression(PREC_LOGICAL_NOT + 1);
-    ctx()->s_expr.push(make_expr<NotExpr>(ctx()->s_expr.popx()));
+    ctx()->s_expr.push_back(make_expr<NotExpr>(ctx()->s_expr.popx_back()));
 }
 
 void Compiler::exprUnaryOp() {
     TokenIndex op = prev().type;
     parse_expression(PREC_UNARY + 1);
     switch(op) {
-        case TK("-"): ctx()->s_expr.push(make_expr<NegatedExpr>(ctx()->s_expr.popx())); break;
-        case TK("~"): ctx()->s_expr.push(make_expr<InvertExpr>(ctx()->s_expr.popx())); break;
-        case TK("*"): ctx()->s_expr.push(make_expr<StarredExpr>(1, ctx()->s_expr.popx())); break;
-        case TK("**"): ctx()->s_expr.push(make_expr<StarredExpr>(2, ctx()->s_expr.popx())); break;
+        case TK("-"): ctx()->s_expr.push_back(make_expr<NegatedExpr>(ctx()->s_expr.popx_back())); break;
+        case TK("~"): ctx()->s_expr.push_back(make_expr<InvertExpr>(ctx()->s_expr.popx_back())); break;
+        case TK("*"): ctx()->s_expr.push_back(make_expr<StarredExpr>(1, ctx()->s_expr.popx_back())); break;
+        case TK("**"): ctx()->s_expr.push_back(make_expr<StarredExpr>(2, ctx()->s_expr.popx_back())); break;
         default: assert(false);
     }
 }
@@ -306,9 +306,9 @@ void Compiler::exprGroup() {
     EXPR_TUPLE();  // () is just for change precedence
     match_newlines_repl();
     consume(TK(")"));
-    if(ctx()->s_expr.top()->is_tuple()) return;
-    Expr_ g = make_expr<GroupedExpr>(ctx()->s_expr.popx());
-    ctx()->s_expr.push(std::move(g));
+    if(ctx()->s_expr.back()->is_tuple()) return;
+    Expr_ g = make_expr<GroupedExpr>(ctx()->s_expr.popx_back());
+    ctx()->s_expr.push_back(std::move(g));
 }
 
 void Compiler::consume_comp(unique_ptr_128<CompExpr> ce, Expr_ expr) {
@@ -316,13 +316,13 @@ void Compiler::consume_comp(unique_ptr_128<CompExpr> ce, Expr_ expr) {
     ce->vars = EXPR_VARS();
     consume(TK("in"));
     parse_expression(PREC_TERNARY + 1);
-    ce->iter = ctx()->s_expr.popx();
+    ce->iter = ctx()->s_expr.popx_back();
     match_newlines_repl();
     if(match(TK("if"))) {
         parse_expression(PREC_TERNARY + 1);
-        ce->cond = ctx()->s_expr.popx();
+        ce->cond = ctx()->s_expr.popx_back();
     }
-    ctx()->s_expr.push(std::move(ce));
+    ctx()->s_expr.push_back(std::move(ce));
     match_newlines_repl();
 }
 
@@ -333,7 +333,7 @@ void Compiler::exprList() {
         match_newlines_repl();
         if(curr().type == TK("]")) break;
         EXPR();
-        items.push_back(ctx()->s_expr.popx());
+        items.push_back(ctx()->s_expr.popx_back());
         match_newlines_repl();
         if(items.size() == 1 && match(TK("for"))) {
             consume_comp(make_expr<ListCompExpr>(), std::move(items[0]));
@@ -345,7 +345,7 @@ void Compiler::exprList() {
     consume(TK("]"));
     auto e = make_expr<ListExpr>(std::move(items));
     e->line = line;  // override line
-    ctx()->s_expr.push(std::move(e));
+    ctx()->s_expr.push_back(std::move(e));
 }
 
 void Compiler::exprMap() {
@@ -355,22 +355,22 @@ void Compiler::exprMap() {
         match_newlines_repl();
         if(curr().type == TK("}")) break;
         EXPR();
-        int star_level = ctx()->s_expr.top()->star_level();
+        int star_level = ctx()->s_expr.back()->star_level();
         if(star_level == 2 || curr().type == TK(":")) { parsing_dict = true; }
         if(parsing_dict) {
             auto dict_item = make_expr<DictItemExpr>();
             if(star_level == 2) {
                 dict_item->key = nullptr;
-                dict_item->value = ctx()->s_expr.popx();
+                dict_item->value = ctx()->s_expr.popx_back();
             } else {
                 consume(TK(":"));
                 EXPR();
-                dict_item->key = ctx()->s_expr.popx();
-                dict_item->value = ctx()->s_expr.popx();
+                dict_item->key = ctx()->s_expr.popx_back();
+                dict_item->value = ctx()->s_expr.popx_back();
             }
             items.push_back(std::move(dict_item));
         } else {
-            items.push_back(ctx()->s_expr.popx());
+            items.push_back(ctx()->s_expr.popx_back());
         }
         match_newlines_repl();
         if(items.size() == 1 && match(TK("for"))) {
@@ -386,16 +386,16 @@ void Compiler::exprMap() {
     consume(TK("}"));
     if(items.size() == 0 || parsing_dict) {
         auto e = make_expr<DictExpr>(std::move(items));
-        ctx()->s_expr.push(std::move(e));
+        ctx()->s_expr.push_back(std::move(e));
     } else {
         auto e = make_expr<SetExpr>(std::move(items));
-        ctx()->s_expr.push(std::move(e));
+        ctx()->s_expr.push_back(std::move(e));
     }
 }
 
 void Compiler::exprCall() {
     auto e = make_expr<CallExpr>();
-    e->callable = ctx()->s_expr.popx();
+    e->callable = ctx()->s_expr.popx_back();
     do {
         match_newlines_repl();
         if(curr().type == TK(")")) break;
@@ -404,16 +404,16 @@ void Compiler::exprCall() {
             Str key = prev().str();
             consume(TK("="));
             EXPR();
-            e->kwargs.push_back({key, ctx()->s_expr.popx()});
+            e->kwargs.push_back({key, ctx()->s_expr.popx_back()});
         } else {
             EXPR();
-            if(ctx()->s_expr.top()->star_level() == 2) {
+            if(ctx()->s_expr.back()->star_level() == 2) {
                 // **kwargs
-                e->kwargs.push_back({"**", ctx()->s_expr.popx()});
+                e->kwargs.push_back({"**", ctx()->s_expr.popx_back()});
             } else {
                 // positional argument
                 if(!e->kwargs.empty()) SyntaxError("positional argument follows keyword argument");
-                e->args.push_back(ctx()->s_expr.popx());
+                e->args.push_back(ctx()->s_expr.popx_back());
             }
         }
         match_newlines_repl();
@@ -421,70 +421,70 @@ void Compiler::exprCall() {
     consume(TK(")"));
     if(e->args.size() > 32767) SyntaxError("too many positional arguments");
     if(e->kwargs.size() > 32767) SyntaxError("too many keyword arguments");
-    ctx()->s_expr.push(std::move(e));
+    ctx()->s_expr.push_back(std::move(e));
 }
 
 void Compiler::exprName() {
     Str name = prev().str();
     NameScope scope = name_scope();
     if(ctx()->global_names.contains(name)) { scope = NAME_GLOBAL; }
-    ctx()->s_expr.push(make_expr<NameExpr>(name, scope));
+    ctx()->s_expr.push_back(make_expr<NameExpr>(name, scope));
 }
 
 void Compiler::exprAttrib() {
     consume(TK("@id"));
-    ctx()->s_expr.push(make_expr<AttribExpr>(ctx()->s_expr.popx(), StrName::get(prev().sv())));
+    ctx()->s_expr.push_back(make_expr<AttribExpr>(ctx()->s_expr.popx_back(), StrName::get(prev().sv())));
 }
 
 void Compiler::exprSlice0() {
     auto slice = make_expr<SliceExpr>();
     if(is_expression()) {  // :<stop>
         EXPR();
-        slice->stop = ctx()->s_expr.popx();
+        slice->stop = ctx()->s_expr.popx_back();
         // try optional step
         if(match(TK(":"))) {  // :<stop>:<step>
             EXPR();
-            slice->step = ctx()->s_expr.popx();
+            slice->step = ctx()->s_expr.popx_back();
         }
     } else if(match(TK(":"))) {
         if(is_expression()) {  // ::<step>
             EXPR();
-            slice->step = ctx()->s_expr.popx();
+            slice->step = ctx()->s_expr.popx_back();
         }  // else ::
     }  // else :
-    ctx()->s_expr.push(std::move(slice));
+    ctx()->s_expr.push_back(std::move(slice));
 }
 
 void Compiler::exprSlice1() {
     auto slice = make_expr<SliceExpr>();
-    slice->start = ctx()->s_expr.popx();
+    slice->start = ctx()->s_expr.popx_back();
     if(is_expression()) {  // <start>:<stop>
         EXPR();
-        slice->stop = ctx()->s_expr.popx();
+        slice->stop = ctx()->s_expr.popx_back();
         // try optional step
         if(match(TK(":"))) {  // <start>:<stop>:<step>
             EXPR();
-            slice->step = ctx()->s_expr.popx();
+            slice->step = ctx()->s_expr.popx_back();
         }
     } else if(match(TK(":"))) {  // <start>::<step>
         EXPR();
-        slice->step = ctx()->s_expr.popx();
+        slice->step = ctx()->s_expr.popx_back();
     }  // else <start>:
-    ctx()->s_expr.push(std::move(slice));
+    ctx()->s_expr.push_back(std::move(slice));
 }
 
 void Compiler::exprSubscr() {
     auto e = make_expr<SubscrExpr>();
     match_newlines_repl();
-    e->a = ctx()->s_expr.popx();  // a
+    e->a = ctx()->s_expr.popx_back();  // a
     EXPR_TUPLE(true);
-    e->b = ctx()->s_expr.popx();  // a[<expr>]
+    e->b = ctx()->s_expr.popx_back();  // a[<expr>]
     match_newlines_repl();
     consume(TK("]"));
-    ctx()->s_expr.push(std::move(e));
+    ctx()->s_expr.push_back(std::move(e));
 }
 
-void Compiler::exprLiteral0() { ctx()->s_expr.push(make_expr<Literal0Expr>(prev().type)); }
+void Compiler::exprLiteral0() { ctx()->s_expr.push_back(make_expr<Literal0Expr>(prev().type)); }
 
 void Compiler::compile_block_body(void (Compiler::*callback)()) {
     if(callback == nullptr) callback = &Compiler::compile_stmt;
@@ -674,7 +674,7 @@ void Compiler::compile_try_except() {
     ctx()->enter_block(CodeBlockType::TRY_EXCEPT);
     ctx()->emit_(OP_TRY_ENTER, BC_NOARG, prev().line);
     compile_block_body();
-    small_vector_2<int, 6> patches;
+    small_vector_2<int, 8> patches;
     patches.push_back(ctx()->emit_(OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE));
     ctx()->exit_block();
 
@@ -739,7 +739,7 @@ void Compiler::compile_decorated() {
     Expr_vector decorators;
     do {
         EXPR();
-        decorators.push_back(ctx()->s_expr.popx());
+        decorators.push_back(ctx()->s_expr.popx_back());
         if(!match_newlines_repl()) SyntaxError();
     } while(match(TK("@")));
 
@@ -764,7 +764,7 @@ bool Compiler::try_compile_assignment() {
         case TK("&="):
         case TK("|="):
         case TK("^="): {
-            Expr* lhs_p = ctx()->s_expr.top().get();
+            Expr* lhs_p = ctx()->s_expr.back().get();
             if(lhs_p->is_starred()) SyntaxError();
             if(ctx()->is_compiling_class) SyntaxError("can't use inplace operator in class definition");
             advance();
@@ -772,9 +772,9 @@ bool Compiler::try_compile_assignment() {
             // a.x += 1;    a should be evaluated only once
             auto e = make_expr<BinaryExpr>(true);  // inplace=true
             e->op = prev().type - 1;               // -1 to remove =
-            e->lhs = ctx()->s_expr.popx();
+            e->lhs = ctx()->s_expr.popx_back();
             EXPR_TUPLE();
-            e->rhs = ctx()->s_expr.popx();
+            e->rhs = ctx()->s_expr.popx_back();
             if(e->rhs->is_starred()) SyntaxError();
             e->emit_(ctx());
             bool ok = lhs_p->emit_store_inplace(ctx());
@@ -788,12 +788,12 @@ bool Compiler::try_compile_assignment() {
                 n += 1;
             }
             // stack size is n+1
-            Expr_ val = ctx()->s_expr.popx();
+            Expr_ val = ctx()->s_expr.popx_back();
             val->emit_(ctx());
             for(int j = 1; j < n; j++)
                 ctx()->emit_(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
             for(int j = 0; j < n; j++) {
-                auto e = ctx()->s_expr.popx();
+                auto e = ctx()->s_expr.popx_back();
                 if(e->is_starred()) SyntaxError();
                 bool ok = e->emit_store(ctx());
                 if(!ok) SyntaxError();
@@ -919,7 +919,7 @@ void Compiler::compile_stmt() {
         } break;
         case TK("del"): {
             EXPR_TUPLE();
-            Expr_ e = ctx()->s_expr.popx();
+            Expr_ e = ctx()->s_expr.popx_back();
             bool ok = e->emit_del(ctx());
             if(!ok) SyntaxError();
             consume_end_stmt();
@@ -968,19 +968,19 @@ void Compiler::compile_stmt() {
 
             bool is_typed_name = false;  // e.g. x: int
             // eat variable's type hint if it is a single name
-            if(ctx()->s_expr.top()->is_name()) {
+            if(ctx()->s_expr.back()->is_name()) {
                 if(match(TK(":"))) {
                     consume_type_hints();
                     is_typed_name = true;
 
                     if(ctx()->is_compiling_class) {
-                        NameExpr* ne = static_cast<NameExpr*>(ctx()->s_expr.top().get());
+                        NameExpr* ne = static_cast<NameExpr*>(ctx()->s_expr.back().get());
                         ctx()->emit_(OP_ADD_CLASS_ANNOTATION, ne->name.index, BC_KEEPLINE);
                     }
                 }
             }
             if(!try_compile_assignment()) {
-                if(!ctx()->s_expr.empty() && ctx()->s_expr.top()->is_starred()) { SyntaxError(); }
+                if(!ctx()->s_expr.empty() && ctx()->s_expr.back()->is_starred()) { SyntaxError(); }
                 if(!is_typed_name) {
                     ctx()->emit_expr();
                     if((mode() == CELL_MODE || mode() == REPL_MODE) && name_scope() == NAME_GLOBAL) {
@@ -990,7 +990,7 @@ void Compiler::compile_stmt() {
                     }
                 } else {
                     assert(ctx()->s_expr.size() == 1);
-                    ctx()->s_expr.pop();
+                    ctx()->s_expr.pop_back();
                 }
             }
             consume_end_stmt();
@@ -1000,7 +1000,7 @@ void Compiler::compile_stmt() {
 
 void Compiler::consume_type_hints() {
     EXPR();
-    ctx()->s_expr.pop();
+    ctx()->s_expr.pop_back();
 }
 
 void Compiler::_add_decorators(const Expr_vector& decorators) {
@@ -1021,7 +1021,7 @@ void Compiler::compile_class(const Expr_vector& decorators) {
     if(match(TK("("))) {
         if(is_expression()) {
             EXPR();
-            base = ctx()->s_expr.popx();
+            base = ctx()->s_expr.popx_back();
         }
         consume(TK(")"));
     }
@@ -1032,7 +1032,7 @@ void Compiler::compile_class(const Expr_vector& decorators) {
     }
     ctx()->emit_(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
 
-    for(auto& c: this->contexts.container()) {
+    for(auto& c: this->contexts) {
         if(c.is_compiling_class) { SyntaxError("nested class is not allowed"); }
     }
     ctx()->is_compiling_class = true;
@@ -1319,7 +1319,7 @@ CodeObject_ Compiler::compile() {
         return code;
     } else if(mode() == JSON_MODE) {
         EXPR();
-        Expr_ e = ctx()->s_expr.popx();
+        Expr_ e = ctx()->s_expr.popx_back();
         if(!e->is_json_object()) SyntaxError("expect a JSON object, literal or array");
         consume(TK("@eof"));
         e->emit_(ctx());

+ 4 - 4
src/compiler/expr.cpp

@@ -43,8 +43,8 @@ void CodeEmitContext::exit_block() {
 // clear the expression stack and generate bytecode
 void CodeEmitContext::emit_expr() {
     assert(s_expr.size() == 1);
-    Expr_ expr = s_expr.popx();
-    expr->emit_(this);
+    s_expr.back()->emit_(this);
+    s_expr.pop_back();
 }
 
 int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtual) {
@@ -690,7 +690,7 @@ bool BinaryExpr::is_compare() const {
     }
 }
 
-void BinaryExpr::_emit_compare(CodeEmitContext* ctx, small_vector_2<int, 6>& jmps) {
+void BinaryExpr::_emit_compare(CodeEmitContext* ctx, small_vector_2<int, 8>& jmps) {
     if(lhs->is_compare()) {
         static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
     } else {
@@ -714,7 +714,7 @@ void BinaryExpr::_emit_compare(CodeEmitContext* ctx, small_vector_2<int, 6>& jmp
 }
 
 void BinaryExpr::emit_(CodeEmitContext* ctx) {
-    small_vector_2<int, 6> jmps;
+    small_vector_2<int, 8> jmps;
     if(is_compare() && lhs->is_compare()) {
         // (a < b) < c
         static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);

+ 8 - 8
src/compiler/lexer.cpp

@@ -69,15 +69,15 @@ bool Lexer::eat_indentation() {
     if(peekchar() == '#') skip_line_comment();
     if(peekchar() == '\0' || peekchar() == '\n') return true;
     // https://docs.python.org/3/reference/lexical_analysis.html#indentation
-    if(spaces > indents.top()) {
-        indents.push(spaces);
+    if(spaces > indents.back()) {
+        indents.push_back(spaces);
         nexts.push_back(Token{TK("@indent"), token_start, 0, current_line, brackets_level, {}});
-    } else if(spaces < indents.top()) {
-        while(spaces < indents.top()) {
-            indents.pop();
+    } else if(spaces < indents.back()) {
+        while(spaces < indents.back()) {
+            indents.pop_back();
             nexts.push_back(Token{TK("@dedent"), token_start, 0, current_line, brackets_level, {}});
         }
-        if(spaces != indents.top()) { return false; }
+        if(spaces != indents.back()) { return false; }
     }
     return true;
 }
@@ -496,7 +496,7 @@ bool Lexer::lex_one_token() {
 
     token_start = curr_char;
     while(indents.size() > 1) {
-        indents.pop();
+        indents.pop_back();
         add_token(TK("@dedent"));
         return true;
     }
@@ -518,7 +518,7 @@ Lexer::Lexer(VM* vm, std::shared_ptr<SourceData> src) : vm(vm), src(src) {
     this->token_start = src->source.c_str();
     this->curr_char = src->source.c_str();
     this->nexts.push_back(Token{TK("@sof"), token_start, 0, current_line, brackets_level, {}});
-    this->indents.push(0);
+    this->indents.push_back(0);
 }
 
 vector<Token> Lexer::run() {

+ 7 - 7
src/interpreter/profiler.cpp

@@ -23,7 +23,7 @@ void LineProfiler::_step(int callstack_size, Frame* frame) {
     int line = line_info.lineno;
 
     if(frames.empty()) {
-        frames.push({callstack_size, frame, clock(), nullptr});
+        frames.push_back({callstack_size, frame, clock(), nullptr});
     } else {
         _step_end(callstack_size, frame, line);
     }
@@ -38,12 +38,12 @@ void LineProfiler::_step(int callstack_size, Frame* frame) {
         }
     }
 
-    frames.top().prev_record = &file_records[line];
+    frames.back().prev_record = &file_records[line];
 }
 
 void LineProfiler::_step_end(int callstack_size, Frame* frame, int line) {
     clock_t now = clock();
-    _FrameRecord& top_frame_record = frames.top();
+    _FrameRecord& top_frame_record = frames.back();
     _LineRecord* prev_record = top_frame_record.prev_record;
 
     int id_delta = callstack_size - top_frame_record.callstack_size;
@@ -58,15 +58,15 @@ void LineProfiler::_step_end(int callstack_size, Frame* frame, int line) {
     }
 
     if(id_delta == 1) {
-        frames.push({callstack_size, frame, now, nullptr});
+        frames.push_back({callstack_size, frame, now, nullptr});
     } else {
-        if(id_delta == -1) frames.pop();
+        if(id_delta == -1) frames.pop_back();
     }
 }
 
 void LineProfiler::end() {
     clock_t now = clock();
-    _FrameRecord& top_frame_record = frames.top();
+    _FrameRecord& top_frame_record = frames.back();
     _LineRecord* prev_record = top_frame_record.prev_record;
 
     clock_t delta = now - top_frame_record.prev_time;
@@ -74,7 +74,7 @@ void LineProfiler::end() {
     prev_record->hits++;
     prev_record->time += delta;
 
-    frames.pop();
+    frames.pop_back();
     assert(frames.empty());
 }
 

+ 2 - 3
src/objects/error.cpp

@@ -8,9 +8,8 @@ Str Exception::summary() const {
     //     ss << st.top().snapshot() << '\n';
     //     st.pop();
     // }
-    const auto& container = stacktrace.container();
-    for(int i = container.size() - 1; i >= 0; i--) {
-        ss << container[i].snapshot() << '\n';
+    for(int i = stacktrace.size() - 1; i >= 0; i--) {
+        ss << stacktrace[i].snapshot() << '\n';
     }
     if(!msg.empty())
         ss << type.sv() << ": " << msg;

+ 6 - 6
src/pocketpy_c.cpp

@@ -21,7 +21,7 @@ using namespace pkpy;
 static int count_extra_elements(VM* vm, int n) {
     if(vm->callstack.empty()) { return vm->s_data.size(); }
     assert(!vm->__c.s_view.empty());
-    return vm->s_data._sp - vm->__c.s_view.top().end();
+    return vm->s_data._sp - vm->__c.s_view.back().end();
 }
 
 static PyVar stack_item(VM* vm, int index) {
@@ -31,7 +31,7 @@ static PyVar stack_item(VM* vm, int index) {
         begin = vm->s_data.begin();
     } else {
         assert(!vm->__c.s_view.empty());
-        begin = vm->__c.s_view.top().begin();
+        begin = vm->__c.s_view.back().begin();
     }
     int size = end - begin;
     if(index < 0) index += size;
@@ -134,7 +134,7 @@ int pkpy_stack_size(pkpy_vm* vm_handle) {
     PK_ASSERT_NO_ERROR()
     if(vm->callstack.empty()) { return vm->s_data.size(); }
     if(vm->__c.s_view.empty()) exit(127);
-    return vm->s_data._sp - vm->__c.s_view.top().begin();
+    return vm->s_data._sp - vm->__c.s_view.back().begin();
 }
 
 // int
@@ -314,7 +314,7 @@ struct TempViewPopper {
 
     void restore() noexcept {
         if(used) return;
-        vm->__c.s_view.pop();
+        vm->__c.s_view.pop_back();
         used = true;
     }
 
@@ -326,7 +326,7 @@ static PyVar c_function_wrapper(VM* vm, ArgsView args) {
     pkpy_CFunction f = lambda_get_userdata<pkpy_CFunction>(args.begin());
     PyVar* curr_sp = vm->s_data._sp;
 
-    vm->__c.s_view.push(args);
+    vm->__c.s_view.push_back(args);
     TempViewPopper _tvp(vm);
     int retc = f((pkpy_vm*)vm);  // may raise, _tvp will handle this via RAII
     _tvp.restore();
@@ -526,7 +526,7 @@ bool pkpy_clear_error(pkpy_vm* vm_handle, char** message) {
         vm->s_data.clear();
     } else {
         if(vm->__c.s_view.empty()) exit(127);
-        vm->s_data.reset(vm->__c.s_view.top().end());
+        vm->s_data.reset(vm->__c.s_view.back().end());
     }
     return true;
 }