Skip to content

Commit

Permalink
Merge pull request #185 from erg-lang/with-func
Browse files Browse the repository at this point in the history
Implement `with!`
  • Loading branch information
mtshiba authored Sep 30, 2022
2 parents 6d515dc + a08b691 commit 77084aa
Show file tree
Hide file tree
Showing 18 changed files with 275 additions and 30 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "erg"
version = "0.5.5-nightly.2"
version = "0.5.5"
description = "The Erg programming language"
authors = ["erg-lang team <[email protected]>"]
license = "MIT OR Apache-2.0"
Expand Down Expand Up @@ -46,10 +46,10 @@ traditional_chinese = [
]

[dependencies]
erg_common = { version = "0.5.5-nightly.2", path = "./compiler/erg_common" }
erg_parser = { version = "0.5.5-nightly.2", path = "./compiler/erg_parser" }
erg_compiler = { version = "0.5.5-nightly.2", path = "./compiler/erg_compiler" }
erg_type = { version = "0.5.5-nightly.2", path = "./compiler/erg_type" }
erg_common = { version = "0.5.5", path = "./compiler/erg_common" }
erg_parser = { version = "0.5.5", path = "./compiler/erg_parser" }
erg_compiler = { version = "0.5.5", path = "./compiler/erg_compiler" }
erg_type = { version = "0.5.5", path = "./compiler/erg_type" }

# [workspace]
# member = ["cm", "dyne"]
Expand Down
2 changes: 1 addition & 1 deletion compiler/erg_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "erg_common"
version = "0.5.5-nightly.2"
version = "0.5.5"
description = "A common components library of Erg"
authors = ["erg-lang team <[email protected]>"]
license = "MIT OR Apache-2.0"
Expand Down
8 changes: 8 additions & 0 deletions compiler/erg_common/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ pub enum Opcode {
LOAD_ASSERTION_ERROR = 74,
LIST_TO_TUPLE = 82,
RETURN_VALUE = 83,
POP_BLOCK = 87,
POP_EXCEPT = 89,
/* ↓ These opcodes take an arg */
STORE_NAME = 90,
DELETE_NAME = 91,
Expand Down Expand Up @@ -92,6 +94,7 @@ pub enum Opcode {
LOAD_GLOBAL = 116,
IS_OP = 117,
CONTAINS_OP = 118,
RERAISE = 119,
LOAD_FAST = 124,
STORE_FAST = 125,
DELETE_FAST = 126,
Expand All @@ -103,6 +106,7 @@ pub enum Opcode {
STORE_DEREF = 137,
CALL_FUNCTION_KW = 141,
CALL_FUNCTION_EX = 142,
SETUP_WITH = 143,
LOAD_METHOD = 160,
CALL_METHOD = 161,
LIST_EXTEND = 162,
Expand Down Expand Up @@ -210,6 +214,8 @@ impl From<u8> for Opcode {
74 => LOAD_ASSERTION_ERROR,
82 => LIST_TO_TUPLE,
83 => RETURN_VALUE,
87 => POP_BLOCK,
89 => POP_EXCEPT,
/* ↓ These opcodes take an arg */
90 => STORE_NAME,
91 => DELETE_NAME,
Expand Down Expand Up @@ -237,6 +243,7 @@ impl From<u8> for Opcode {
116 => LOAD_GLOBAL,
117 => IS_OP,
118 => CONTAINS_OP,
119 => RERAISE,
124 => LOAD_FAST,
125 => STORE_FAST,
126 => DELETE_FAST,
Expand All @@ -248,6 +255,7 @@ impl From<u8> for Opcode {
137 => STORE_DEREF,
141 => CALL_FUNCTION_KW,
142 => CALL_FUNCTION_EX,
143 => SETUP_WITH,
160 => LOAD_METHOD,
161 => CALL_METHOD,
162 => LIST_EXTEND,
Expand Down
8 changes: 4 additions & 4 deletions compiler/erg_compiler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "erg_compiler"
version = "0.5.5-nightly.2"
version = "0.5.5"
description = "Centimetre: the Erg compiler"
authors = ["erg-lang team <[email protected]>"]
license = "MIT OR Apache-2.0"
Expand All @@ -17,9 +17,9 @@ simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_c
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ]

[dependencies]
erg_common = { version = "0.5.5-nightly.2", path = "../erg_common" }
erg_parser = { version = "0.5.5-nightly.2", path = "../erg_parser" }
erg_type = { version = "0.5.5-nightly.2", path = "../erg_type" }
erg_common = { version = "0.5.5", path = "../erg_common" }
erg_parser = { version = "0.5.5", path = "../erg_parser" }
erg_type = { version = "0.5.5", path = "../erg_type" }

[lib]
path = "lib.rs"
Expand Down
87 changes: 83 additions & 4 deletions compiler/erg_compiler/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -
("Array!", _, "push!") => Str::ever("append"),
("Complex" | "Float" | "Ratio" | "Int" | "Nat" | "Bool", _, "Real") => Str::ever("real"),
("Complex" | "Float" | "Ratio" | "Int" | "Nat" | "Bool", _, "Imag") => Str::ever("imag"),
("File!", _, "read") => Str::ever("read"),
(_, _, "__new__") => Str::ever("__call__"),
("StringIO!", _, "getvalue!") => Str::ever("getvalue"),
("Module", Some("importlib"), "reload!") => Str::ever("reload"),
Expand Down Expand Up @@ -257,6 +258,7 @@ fn convert_to_python_name(name: Str) -> Str {
"import" => Str::ever("__import__"),
"input!" => Str::ever("input"),
"log" => Str::ever("print"), // TODO: log != print (prints after executing)
"open!" => Str::ever("open"),
"print!" => Str::ever("print"),
"py" | "pyimport" => Str::ever("__import__"),
"quit" | "exit" => Str::ever("quit"),
Expand Down Expand Up @@ -1354,6 +1356,60 @@ impl CodeGenerator {
pop_jump_points
}

fn emit_with_instr(&mut self, args: Args) {
log!(info "entered {}", fn_name!());
let mut args = args;
let expr = args.remove(0);
let lambda = enum_unwrap!(args.remove(0), Expr::Lambda);
let params = self.gen_param_names(&lambda.params);
self.emit_expr(expr);
let idx_setup_with = self.cur_block().lasti;
self.write_instr(SETUP_WITH);
self.write_arg(0);
// push __exit__, __enter__() to the stack
self.stack_inc_n(2);
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
self.emit_with_block(lambda.body, params);
let stash = Identifier::private_with_line(Str::from(fresh_varname()), lambda_line);
self.emit_store_instr(stash.clone(), Name);
self.write_instr(POP_BLOCK);
self.write_arg(0);
self.emit_load_const(ValueObj::None);
self.write_instr(DUP_TOP);
self.write_arg(0);
self.stack_inc();
self.write_instr(DUP_TOP);
self.write_arg(0);
self.stack_inc();
self.write_instr(CALL_FUNCTION);
self.write_arg(3);
self.stack_dec_n((1 + 3) - 1);
self.emit_pop_top();
let idx_jump_forward = self.cur_block().lasti;
self.write_instr(JUMP_FORWARD);
self.write_arg(0);
self.edit_code(
idx_setup_with + 1,
(self.cur_block().lasti - idx_setup_with - 2) / 2,
);
self.write_instr(WITH_EXCEPT_START);
self.write_arg(0);
let idx_pop_jump_if_true = self.cur_block().lasti;
self.write_instr(POP_JUMP_IF_TRUE);
self.write_arg(0);
self.write_instr(RERAISE);
self.write_arg(1);
self.edit_code(idx_pop_jump_if_true + 1, self.cur_block().lasti / 2);
// self.emit_pop_top();
// self.emit_pop_top();
self.emit_pop_top();
self.write_instr(POP_EXCEPT);
self.write_arg(0);
let idx_end = self.cur_block().lasti;
self.edit_code(idx_jump_forward + 1, (idx_end - idx_jump_forward - 2) / 2);
self.emit_load_name_instr(stash);
}

fn emit_call(&mut self, call: Call) {
log!(info "entered {} ({call})", fn_name!());
if let Some(method_name) = call.method_name {
Expand All @@ -1379,6 +1435,7 @@ impl CodeGenerator {
"for" | "for!" => self.emit_for_instr(args),
"if" | "if!" => self.emit_if_instr(args),
"match" | "match!" => self.emit_match_instr(args, true),
"with!" => self.emit_with_instr(args),
"import" => {
if !self.module_type_loaded {
self.load_module_type();
Expand Down Expand Up @@ -1418,14 +1475,14 @@ impl CodeGenerator {
}
if let Some(var_args) = &args.var_args {
if pos_len > 0 {
self.write_instr(Opcode::BUILD_LIST);
self.write_instr(BUILD_LIST);
self.write_arg(pos_len as u8);
}
self.emit_expr(var_args.expr.clone());
if pos_len > 0 {
self.write_instr(Opcode::LIST_EXTEND);
self.write_instr(LIST_EXTEND);
self.write_arg(1);
self.write_instr(Opcode::LIST_TO_TUPLE);
self.write_instr(LIST_TO_TUPLE);
self.write_arg(0);
}
}
Expand Down Expand Up @@ -1652,8 +1709,12 @@ impl CodeGenerator {
/// forブロックなどで使う
fn emit_frameless_block(&mut self, block: Block, params: Vec<Str>) {
log!(info "entered {}", fn_name!());
let line = block.ln_begin().unwrap_or(0);
for param in params {
self.emit_store_instr(Identifier::private(param), Name);
self.emit_store_instr(
Identifier::public_with_line(Token::dummy(), param, line),
Name,
);
}
for expr in block.into_iter() {
self.emit_expr(expr);
Expand All @@ -1666,6 +1727,24 @@ impl CodeGenerator {
self.cancel_pop_top();
}

fn emit_with_block(&mut self, block: Block, params: Vec<Str>) {
log!(info "entered {}", fn_name!());
let line = block.ln_begin().unwrap_or(0);
for param in params {
self.emit_store_instr(
Identifier::public_with_line(Token::dummy(), param, line),
Name,
);
}
for expr in block.into_iter() {
self.emit_expr(expr);
if self.cur_block().stack_len != 0 {
self.emit_pop_top();
}
}
self.cancel_pop_top();
}

fn emit_class_block(&mut self, class: ClassDef) -> CodeObj {
log!(info "entered {}", fn_name!());
let name = class.sig.ident().inspect().clone();
Expand Down
18 changes: 17 additions & 1 deletion compiler/erg_compiler/context/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use erg_parser::ast::*;
use erg_parser::token::{Token, TokenKind};

use erg_type::constructors::{
builtin_mono, builtin_poly, mono_proj, poly, ref_, ref_mut, refinement, subr_t, v_enum,
and, builtin_mono, builtin_poly, mono_proj, not, or, poly, ref_, ref_mut, refinement, subr_t,
v_enum,
};
use erg_type::typaram::{OpKind, TyParam};
use erg_type::value::ValueObj;
Expand Down Expand Up @@ -807,6 +808,21 @@ impl Context {
}
Ok(poly(path, name, params))
}
Type::And(l, r) => {
let l = self.eval_t_params(*l, level, t_loc)?;
let r = self.eval_t_params(*r, level, t_loc)?;
Ok(and(l, r))
}
Type::Or(l, r) => {
let l = self.eval_t_params(*l, level, t_loc)?;
let r = self.eval_t_params(*r, level, t_loc)?;
Ok(or(l, r))
}
Type::Not(l, r) => {
let l = self.eval_t_params(*l, level, t_loc)?;
let r = self.eval_t_params(*r, level, t_loc)?;
Ok(not(l, r))
}
other if other.is_monomorphic() => Ok(other),
other => todo!("{other}"),
}
Expand Down
Loading

0 comments on commit 77084aa

Please sign in to comment.