mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 18:58:30 +00:00
Add PyCodeGenerator::deopt_instr
This commit is contained in:
parent
bdfe59ac7c
commit
eaded7ac5d
6 changed files with 40 additions and 6 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -17,6 +17,7 @@
|
|||
/*/.DS_Store
|
||||
/.idea/
|
||||
/timeit.dat
|
||||
**/__pycache__/
|
||||
|
||||
# Nix
|
||||
.direnv
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
even for and while expressions are just one of the subroutines, so this is possible.
|
||||
|
||||
```python
|
||||
loop! block = while! do(True), block
|
||||
loop! block! = while! do! True, block!
|
||||
|
||||
# equals to `while! do(True), do! print! "hello"`
|
||||
loop! do!:
|
||||
|
@ -202,7 +202,7 @@ nix build
|
|||
By enabling the `--features` flag, you can customize the installation and build.
|
||||
|
||||
- You can change the language of the error message by using `--features {language}`
|
||||
```sh
|
||||
```sh
|
||||
--features japanese
|
||||
--features simplified_chinese
|
||||
--features traditional_chinese
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
Ergでは特別扱いされる構文要素がとても少なく、例えば予約語が一つもありません。以下のような芸当も可能です。
|
||||
|
||||
```python
|
||||
loop! block = while! do(True), block
|
||||
loop! block! = while! do! True, block!
|
||||
|
||||
# `while! do(True), do! print! "hello"`と同じです
|
||||
loop! do!:
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
在Erg中,很少有东西被认为是特殊的,没有关键字,因此for和while表达式也只是子程序之一
|
||||
|
||||
```python
|
||||
loop! block = while! do(True), block
|
||||
loop! block! = while! do! True, block!
|
||||
|
||||
# equals to `while! do(True), do! print! "hello"`
|
||||
loop! do!:
|
||||
|
|
|
@ -77,9 +77,9 @@
|
|||
在Erg中,很少有東西被認為是特殊的,沒有關鍵字,因此for和while表達式也只是子程序之一
|
||||
|
||||
```python
|
||||
loop! block = while! do(True), block
|
||||
loop! block! = while! do! True, block!
|
||||
|
||||
# equals to `while! do(True), do! print! "hello"`
|
||||
# equals to `while! do! True, do! print! "hello"`
|
||||
loop! do!:
|
||||
print! "hello"
|
||||
```
|
||||
|
|
|
@ -46,6 +46,18 @@ use crate::ty::{HasType, Type, TypeCode, TypePair};
|
|||
use erg_common::fresh::fresh_varname;
|
||||
use AccessKind::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum ControlKind {
|
||||
If,
|
||||
While,
|
||||
For,
|
||||
Match,
|
||||
With,
|
||||
Discard,
|
||||
Assert,
|
||||
}
|
||||
|
||||
/// patch method -> function
|
||||
/// patch attr -> variable
|
||||
fn debind(ident: &Identifier) -> Option<Str> {
|
||||
|
@ -1604,6 +1616,21 @@ impl PyCodeGenerator {
|
|||
self.emit_load_const(ValueObj::None);
|
||||
}
|
||||
|
||||
fn deopt_instr(&mut self, kind: ControlKind, args: Args) {
|
||||
if !self.control_loaded {
|
||||
self.load_control();
|
||||
}
|
||||
let local = match kind {
|
||||
ControlKind::If => Identifier::public("if__"),
|
||||
ControlKind::For => Identifier::public("for__"),
|
||||
ControlKind::While => Identifier::public("while__"),
|
||||
ControlKind::With => Identifier::public("with__"),
|
||||
ControlKind::Discard => Identifier::public("discard__"),
|
||||
kind => todo!("{kind:?}"),
|
||||
};
|
||||
self.emit_call_local(local, args);
|
||||
}
|
||||
|
||||
fn emit_if_instr(&mut self, mut args: Args) {
|
||||
log!(info "entered {}", fn_name!());
|
||||
let init_stack_len = self.stack_len();
|
||||
|
@ -1670,6 +1697,9 @@ impl PyCodeGenerator {
|
|||
|
||||
fn emit_for_instr(&mut self, mut args: Args) {
|
||||
log!(info "entered {} ({})", fn_name!(), args);
|
||||
if !matches!(args.get(1).unwrap(), Expr::Lambda(_)) {
|
||||
return self.deopt_instr(ControlKind::For, args);
|
||||
}
|
||||
let _init_stack_len = self.stack_len();
|
||||
let iterable = args.remove(0);
|
||||
self.emit_expr(iterable);
|
||||
|
@ -1716,6 +1746,9 @@ impl PyCodeGenerator {
|
|||
|
||||
fn emit_while_instr(&mut self, mut args: Args) {
|
||||
log!(info "entered {} ({})", fn_name!(), args);
|
||||
if !matches!(args.get(1).unwrap(), Expr::Lambda(_)) {
|
||||
return self.deopt_instr(ControlKind::While, args);
|
||||
}
|
||||
let _init_stack_len = self.stack_len();
|
||||
// e.g. is_foo!: () => Bool, do!(is_bar)
|
||||
let cond_block = args.remove(0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue