mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
Add std
This commit is contained in:
parent
0ac63d8362
commit
b997c685dd
9 changed files with 113 additions and 25 deletions
|
@ -18,6 +18,15 @@ members = [
|
||||||
"compiler/erg_type",
|
"compiler/erg_type",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.5.8"
|
||||||
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
edition = "2021"
|
||||||
|
repository = "https://github.com/erg-lang/erg"
|
||||||
|
documentation = "https://docs.rs/erg"
|
||||||
|
homepage = "https://erg-lang.org/"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# when "debug" feature is turned on, that of the following crates will also be turned on.
|
# when "debug" feature is turned on, that of the following crates will also be turned on.
|
||||||
debug = [
|
debug = [
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.5.8"
|
|
||||||
description = "Centimetre: the Erg compiler"
|
description = "Centimetre: the Erg compiler"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
build = "build.rs"
|
||||||
license = "MIT OR Apache-2.0"
|
version.workspace = true
|
||||||
edition = "2021"
|
authors.workspace = true
|
||||||
repository = "https://github.com/erg-lang/erg/tree/main/src/compiler/erg_compiler"
|
license.workspace = true
|
||||||
documentation = "https://docs.rs/erg_compiler"
|
edition.workspace = true
|
||||||
homepage = "https://erg-lang.github.io/"
|
repository.workspace = true
|
||||||
|
documentation.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# when "debug" feature is turned on, that of parser will also be turned on.
|
# when "debug" feature is turned on, that of parser will also be turned on.
|
||||||
|
|
33
compiler/erg_compiler/build.rs
Normal file
33
compiler/erg_compiler/build.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::path;
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
// Create a ".erg" directory
|
||||||
|
let erg_path = env::home_dir()
|
||||||
|
.expect("failed to get the location of the home dir")
|
||||||
|
.to_str()
|
||||||
|
.expect("invalid encoding of the home dir name")
|
||||||
|
.to_string()
|
||||||
|
+ "/.erg";
|
||||||
|
if !path::Path::new(&erg_path).exists() {
|
||||||
|
fs::create_dir(&erg_path)?;
|
||||||
|
fs::create_dir(format!("{erg_path}/std"))?;
|
||||||
|
}
|
||||||
|
println!("cargo:rustc-env=ERG_PATH={erg_path}");
|
||||||
|
println!("cargo:rustc-env=ERG_STD_PATH={erg_path}/std");
|
||||||
|
// create a std library in ".erg"
|
||||||
|
for res in fs::read_dir("std")? {
|
||||||
|
let entry = res?;
|
||||||
|
let path = entry.path();
|
||||||
|
let filename = path
|
||||||
|
.file_name()
|
||||||
|
.expect("this is not a file")
|
||||||
|
.to_str()
|
||||||
|
.unwrap();
|
||||||
|
fs::copy(&path, format!("{erg_path}/std/{filename}"))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -867,7 +867,7 @@ impl CodeGenerator {
|
||||||
self.write_instr(MAKE_FUNCTION);
|
self.write_instr(MAKE_FUNCTION);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.emit_load_const(def.sig.ident().inspect().clone());
|
self.emit_load_const(def.sig.ident().inspect().clone());
|
||||||
self.emit_load_name_instr(Identifier::private(Str::ever("#ABCMeta")));
|
self.emit_load_name_instr(Identifier::private("#ABCMeta"));
|
||||||
self.emit_load_const(vec![ValueObj::from("metaclass")]);
|
self.emit_load_const(vec![ValueObj::from("metaclass")]);
|
||||||
let subclasses_len = 1;
|
let subclasses_len = 1;
|
||||||
self.write_instr(Opcode::CALL_FUNCTION_KW);
|
self.write_instr(Opcode::CALL_FUNCTION_KW);
|
||||||
|
@ -917,7 +917,7 @@ impl CodeGenerator {
|
||||||
self.emit_empty_func(
|
self.emit_empty_func(
|
||||||
Some(sig.ident().inspect()),
|
Some(sig.ident().inspect()),
|
||||||
def.sig.into_ident(),
|
def.sig.into_ident(),
|
||||||
Some(Identifier::private(Str::ever("#abstractmethod"))),
|
Some(Identifier::private("#abstractmethod")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
|
@ -1150,6 +1150,9 @@ impl CodeGenerator {
|
||||||
self.emit_load_name_instr(Identifier::public("range"));
|
self.emit_load_name_instr(Identifier::public("range"));
|
||||||
}
|
}
|
||||||
TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(),
|
TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(),
|
||||||
|
TokenKind::InOp => {
|
||||||
|
self.emit_load_name_instr(Identifier::private("#in_operator"));
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t());
|
let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t());
|
||||||
|
@ -1170,9 +1173,11 @@ impl CodeGenerator {
|
||||||
| TokenKind::NotEq
|
| TokenKind::NotEq
|
||||||
| TokenKind::Gre
|
| TokenKind::Gre
|
||||||
| TokenKind::GreEq => COMPARE_OP,
|
| TokenKind::GreEq => COMPARE_OP,
|
||||||
TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Closed | TokenKind::Open => {
|
TokenKind::LeftOpen
|
||||||
CALL_FUNCTION
|
| TokenKind::RightOpen
|
||||||
} // ERG_BINARY_RANGE,
|
| TokenKind::Closed
|
||||||
|
| TokenKind::Open
|
||||||
|
| TokenKind::InOp => CALL_FUNCTION, // ERG_BINARY_RANGE,
|
||||||
_ => {
|
_ => {
|
||||||
CompileError::feature_error(
|
CompileError::feature_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
@ -1191,14 +1196,22 @@ impl CodeGenerator {
|
||||||
TokenKind::NotEq => 3,
|
TokenKind::NotEq => 3,
|
||||||
TokenKind::Gre => 4,
|
TokenKind::Gre => 4,
|
||||||
TokenKind::GreEq => 5,
|
TokenKind::GreEq => 5,
|
||||||
TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Closed | TokenKind::Open => 2,
|
TokenKind::LeftOpen
|
||||||
|
| TokenKind::RightOpen
|
||||||
|
| TokenKind::Closed
|
||||||
|
| TokenKind::Open
|
||||||
|
| TokenKind::InOp => 2,
|
||||||
_ => type_pair as u8,
|
_ => type_pair as u8,
|
||||||
};
|
};
|
||||||
self.write_instr(instr);
|
self.write_instr(instr);
|
||||||
self.write_arg(arg);
|
self.write_arg(arg);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
match &bin.op.kind {
|
match &bin.op.kind {
|
||||||
TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Open | TokenKind::Closed => {
|
TokenKind::LeftOpen
|
||||||
|
| TokenKind::RightOpen
|
||||||
|
| TokenKind::Open
|
||||||
|
| TokenKind::Closed
|
||||||
|
| TokenKind::InOp => {
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1597,7 +1610,7 @@ impl CodeGenerator {
|
||||||
log!(info "entered {} ({rec})", fn_name!());
|
log!(info "entered {} ({rec})", fn_name!());
|
||||||
let attrs_len = rec.attrs.len();
|
let attrs_len = rec.attrs.len();
|
||||||
// making record type
|
// making record type
|
||||||
let ident = Identifier::private(Str::ever("#NamedTuple"));
|
let ident = Identifier::private("#NamedTuple");
|
||||||
self.emit_load_name_instr(ident);
|
self.emit_load_name_instr(ident);
|
||||||
// record name, let it be anonymous
|
// record name, let it be anonymous
|
||||||
self.emit_load_const("Record");
|
self.emit_load_const("Record");
|
||||||
|
@ -1615,10 +1628,10 @@ impl CodeGenerator {
|
||||||
self.write_arg(2);
|
self.write_arg(2);
|
||||||
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
||||||
self.stack_dec_n((1 + 2 + 0) - 1);
|
self.stack_dec_n((1 + 2 + 0) - 1);
|
||||||
let ident = Identifier::private(Str::ever("#rec"));
|
let ident = Identifier::private("#rec");
|
||||||
self.emit_store_instr(ident, Name);
|
self.emit_store_instr(ident, Name);
|
||||||
// making record instance
|
// making record instance
|
||||||
let ident = Identifier::private(Str::ever("#rec"));
|
let ident = Identifier::private("#rec");
|
||||||
self.emit_load_name_instr(ident);
|
self.emit_load_name_instr(ident);
|
||||||
for field in rec.attrs.into_iter() {
|
for field in rec.attrs.into_iter() {
|
||||||
self.emit_frameless_block(field.body.block, vec![]);
|
self.emit_frameless_block(field.body.block, vec![]);
|
||||||
|
@ -2007,15 +2020,40 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn load_prelude(&mut self) {
|
fn load_prelude(&mut self) {
|
||||||
self.load_record_type();
|
self.load_record_type();
|
||||||
|
self.load_prelude_py();
|
||||||
self.record_type_loaded = true;
|
self.record_type_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_prelude_py(&mut self) {
|
||||||
|
self.emit_global_import_items(
|
||||||
|
Identifier::public("sys"),
|
||||||
|
vec![(
|
||||||
|
Identifier::public("path"),
|
||||||
|
Some(Identifier::private("#path")),
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
self.emit_load_name_instr(Identifier::private("#path"));
|
||||||
|
self.emit_load_method_instr("Array!", None, Identifier::public("push!"));
|
||||||
|
self.emit_load_const(env!("ERG_STD_PATH"));
|
||||||
|
self.write_instr(CALL_METHOD);
|
||||||
|
self.write_arg(1u8);
|
||||||
|
self.stack_dec();
|
||||||
|
self.emit_pop_top();
|
||||||
|
self.emit_global_import_items(
|
||||||
|
Identifier::public("prelude"),
|
||||||
|
vec![(
|
||||||
|
Identifier::public("in_operator"),
|
||||||
|
Some(Identifier::private("#in_operator")),
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn load_record_type(&mut self) {
|
fn load_record_type(&mut self) {
|
||||||
self.emit_global_import_items(
|
self.emit_global_import_items(
|
||||||
Identifier::public("collections"),
|
Identifier::public("collections"),
|
||||||
vec![(
|
vec![(
|
||||||
Identifier::public("namedtuple"),
|
Identifier::public("namedtuple"),
|
||||||
Some(Identifier::private(Str::ever("#NamedTuple"))),
|
Some(Identifier::private("#NamedTuple")),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2026,11 +2064,11 @@ impl CodeGenerator {
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Identifier::public("ABCMeta"),
|
Identifier::public("ABCMeta"),
|
||||||
Some(Identifier::private(Str::ever("#ABCMeta"))),
|
Some(Identifier::private("#ABCMeta")),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Identifier::public("abstractmethod"),
|
Identifier::public("abstractmethod"),
|
||||||
Some(Identifier::private(Str::ever("#abstractmethod"))),
|
Some(Identifier::private("#abstractmethod")),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -2041,7 +2079,7 @@ impl CodeGenerator {
|
||||||
Identifier::public("types"),
|
Identifier::public("types"),
|
||||||
vec![(
|
vec![(
|
||||||
Identifier::public("ModuleType"),
|
Identifier::public("ModuleType"),
|
||||||
Some(Identifier::private(Str::ever("#ModuleType"))),
|
Some(Identifier::private("#ModuleType")),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,8 +365,8 @@ impl Identifier {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn private(name: Str) -> Self {
|
pub fn private(name: &'static str) -> Self {
|
||||||
Self::bare(None, VarName::from_str(name))
|
Self::bare(None, VarName::from_static(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn private_with_line(name: Str, line: usize) -> Self {
|
pub fn private_with_line(name: Str, line: usize) -> Self {
|
||||||
|
|
8
compiler/erg_compiler/std/prelude.py
Normal file
8
compiler/erg_compiler/std/prelude.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
def in_operator(x, y):
|
||||||
|
if type(y) == type:
|
||||||
|
if isinstance(x, y):
|
||||||
|
return True
|
||||||
|
# TODO: trait check
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return x in y
|
|
@ -13,8 +13,7 @@ fn exec_addition() -> Result<(), ()> {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_assert_cast() -> Result<(), ()> {
|
fn exec_assert_cast() -> Result<(), ()> {
|
||||||
// runtime `in` is not implemented
|
expect_success("examples/assert_cast.er")
|
||||||
expect_end_with("examples/assert_cast.er", 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue