mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
Merge branch 'main' into dict
This commit is contained in:
commit
c784ba261e
53 changed files with 1336 additions and 818 deletions
|
@ -1,25 +1,34 @@
|
|||
[package]
|
||||
name = "erg_compiler"
|
||||
version = "0.5.7"
|
||||
description = "Centimetre: the Erg compiler"
|
||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/erg-lang/erg/tree/main/src/compiler/erg_compiler"
|
||||
documentation = "https://docs.rs/erg_compiler"
|
||||
homepage = "https://erg-lang.github.io/"
|
||||
documentation = "http://docs.rs/erg_compiler"
|
||||
build = "build.rs"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
[features]
|
||||
# when "debug" feature is turned on, that of parser will also be turned on.
|
||||
debug = [ "erg_common/debug", "erg_parser/debug", "erg_type/debug" ]
|
||||
japanese = [ "erg_common/japanese", "erg_parser/japanese", "erg_type/japanese" ]
|
||||
simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_chinese", "erg_type/simplified_chinese" ]
|
||||
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ]
|
||||
debug = ["erg_common/debug", "erg_parser/debug", "erg_type/debug"]
|
||||
japanese = ["erg_common/japanese", "erg_parser/japanese", "erg_type/japanese"]
|
||||
simplified_chinese = [
|
||||
"erg_common/simplified_chinese",
|
||||
"erg_parser/simplified_chinese",
|
||||
"erg_type/simplified_chinese",
|
||||
]
|
||||
traditional_chinese = [
|
||||
"erg_common/traditional_chinese",
|
||||
"erg_parser/traditional_chinese",
|
||||
"erg_type/traditional_chinese",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
erg_common = { version = "0.5.7", path = "../erg_common" }
|
||||
erg_parser = { version = "0.5.7", path = "../erg_parser" }
|
||||
erg_type = { version = "0.5.7", path = "../erg_type" }
|
||||
erg_common = { version = "0.5.9-nightly.0", path = "../erg_common" }
|
||||
erg_parser = { version = "0.5.9-nightly.0", path = "../erg_parser" }
|
||||
erg_type = { version = "0.5.9-nightly.0", path = "../erg_type" }
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
|
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(())
|
||||
}
|
|
@ -29,7 +29,7 @@ use erg_type::value::ValueObj;
|
|||
use erg_type::{HasType, Type, TypeCode, TypePair};
|
||||
|
||||
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||
use crate::context::eval::eval_lit;
|
||||
use crate::context::eval::type_from_token_kind;
|
||||
use crate::error::CompileError;
|
||||
use crate::hir::{
|
||||
Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr,
|
||||
|
@ -867,7 +867,7 @@ impl CodeGenerator {
|
|||
self.write_instr(MAKE_FUNCTION);
|
||||
self.write_arg(0);
|
||||
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")]);
|
||||
let subclasses_len = 1;
|
||||
self.write_instr(Opcode::CALL_FUNCTION_KW);
|
||||
|
@ -917,7 +917,7 @@ impl CodeGenerator {
|
|||
self.emit_empty_func(
|
||||
Some(sig.ident().inspect()),
|
||||
def.sig.into_ident(),
|
||||
Some(Identifier::private(Str::ever("#abstractmethod"))),
|
||||
Some(Identifier::private("#abstractmethod")),
|
||||
);
|
||||
}
|
||||
self.emit_load_const(ValueObj::None);
|
||||
|
@ -1129,7 +1129,7 @@ impl CodeGenerator {
|
|||
CompileError::feature_error(
|
||||
self.cfg.input.clone(),
|
||||
unary.op.loc(),
|
||||
"",
|
||||
&unary.op.inspect().clone(),
|
||||
AtomicStr::from(unary.op.content),
|
||||
)
|
||||
.write_to_stderr();
|
||||
|
@ -1150,6 +1150,9 @@ impl CodeGenerator {
|
|||
self.emit_load_name_instr(Identifier::public("range"));
|
||||
}
|
||||
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());
|
||||
|
@ -1170,14 +1173,16 @@ impl CodeGenerator {
|
|||
| TokenKind::NotEq
|
||||
| TokenKind::Gre
|
||||
| TokenKind::GreEq => COMPARE_OP,
|
||||
TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Closed | TokenKind::Open => {
|
||||
CALL_FUNCTION
|
||||
} // ERG_BINARY_RANGE,
|
||||
TokenKind::LeftOpen
|
||||
| TokenKind::RightOpen
|
||||
| TokenKind::Closed
|
||||
| TokenKind::Open
|
||||
| TokenKind::InOp => CALL_FUNCTION, // ERG_BINARY_RANGE,
|
||||
_ => {
|
||||
CompileError::feature_error(
|
||||
self.cfg.input.clone(),
|
||||
bin.op.loc(),
|
||||
"",
|
||||
&bin.op.inspect().clone(),
|
||||
AtomicStr::from(bin.op.content),
|
||||
)
|
||||
.write_to_stderr();
|
||||
|
@ -1191,14 +1196,22 @@ impl CodeGenerator {
|
|||
TokenKind::NotEq => 3,
|
||||
TokenKind::Gre => 4,
|
||||
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,
|
||||
};
|
||||
self.write_instr(instr);
|
||||
self.write_arg(arg);
|
||||
self.stack_dec();
|
||||
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();
|
||||
}
|
||||
_ => {}
|
||||
|
@ -1339,7 +1352,11 @@ impl CodeGenerator {
|
|||
self.emit_store_instr(ident, AccessKind::Name);
|
||||
}
|
||||
ParamPattern::Lit(lit) => {
|
||||
self.emit_load_const(eval_lit(&lit));
|
||||
let value = {
|
||||
let t = type_from_token_kind(lit.token.kind);
|
||||
ValueObj::from_str(t, lit.token.content).unwrap()
|
||||
};
|
||||
self.emit_load_const(value);
|
||||
self.write_instr(Opcode::COMPARE_OP);
|
||||
self.write_arg(2); // ==
|
||||
self.stack_dec();
|
||||
|
@ -1597,7 +1614,7 @@ impl CodeGenerator {
|
|||
log!(info "entered {} ({rec})", fn_name!());
|
||||
let attrs_len = rec.attrs.len();
|
||||
// making record type
|
||||
let ident = Identifier::private(Str::ever("#NamedTuple"));
|
||||
let ident = Identifier::private("#NamedTuple");
|
||||
self.emit_load_name_instr(ident);
|
||||
// record name, let it be anonymous
|
||||
self.emit_load_const("Record");
|
||||
|
@ -1615,10 +1632,10 @@ impl CodeGenerator {
|
|||
self.write_arg(2);
|
||||
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
||||
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);
|
||||
// making record instance
|
||||
let ident = Identifier::private(Str::ever("#rec"));
|
||||
let ident = Identifier::private("#rec");
|
||||
self.emit_load_name_instr(ident);
|
||||
for field in rec.attrs.into_iter() {
|
||||
self.emit_frameless_block(field.body.block, vec![]);
|
||||
|
@ -1687,6 +1704,15 @@ impl CodeGenerator {
|
|||
self.stack_dec_n(len - 1);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
self.emit_expr(*arr.elem);
|
||||
self.write_instr(BUILD_LIST);
|
||||
self.write_arg(1u8);
|
||||
self.emit_expr(*arr.len);
|
||||
self.write_instr(BINARY_MULTIPLY);
|
||||
self.write_arg(0);
|
||||
self.stack_dec();
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
},
|
||||
// TODO: tuple comprehension
|
||||
|
@ -1720,7 +1746,11 @@ impl CodeGenerator {
|
|||
self.stack_dec_n(len - 1);
|
||||
}
|
||||
}
|
||||
crate::hir::Set::WithLength(_) => todo!(),
|
||||
crate::hir::Set::WithLength(st) => {
|
||||
self.emit_expr(*st.elem);
|
||||
self.write_instr(BUILD_SET);
|
||||
self.write_arg(1u8);
|
||||
}
|
||||
},
|
||||
Expr::Record(rec) => self.emit_record(rec),
|
||||
Expr::Code(code) => {
|
||||
|
@ -1739,7 +1769,7 @@ impl CodeGenerator {
|
|||
}
|
||||
// Dict,
|
||||
other => {
|
||||
CompileError::feature_error(self.cfg.input.clone(), other.loc(), "???", "".into())
|
||||
CompileError::feature_error(self.cfg.input.clone(), other.loc(), "Dict", "".into())
|
||||
.write_to_stderr();
|
||||
self.crash("cannot compile this expression at this time");
|
||||
}
|
||||
|
@ -1894,7 +1924,7 @@ impl CodeGenerator {
|
|||
attrs.push(Expr::AttrDef(attr_def));
|
||||
}
|
||||
let none = Token::new(TokenKind::NoneLit, "None", line, 0);
|
||||
attrs.push(Expr::Lit(Literal::from(none)));
|
||||
attrs.push(Expr::Lit(Literal::try_from(none).unwrap()));
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
}
|
||||
|
@ -2007,15 +2037,40 @@ impl CodeGenerator {
|
|||
|
||||
fn load_prelude(&mut self) {
|
||||
self.load_record_type();
|
||||
self.load_prelude_py();
|
||||
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("_erg_std_prelude"),
|
||||
vec![(
|
||||
Identifier::public("in_operator"),
|
||||
Some(Identifier::private("#in_operator")),
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
||||
fn load_record_type(&mut self) {
|
||||
self.emit_global_import_items(
|
||||
Identifier::public("collections"),
|
||||
vec![(
|
||||
Identifier::public("namedtuple"),
|
||||
Some(Identifier::private(Str::ever("#NamedTuple"))),
|
||||
Some(Identifier::private("#NamedTuple")),
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
@ -2026,11 +2081,11 @@ impl CodeGenerator {
|
|||
vec![
|
||||
(
|
||||
Identifier::public("ABCMeta"),
|
||||
Some(Identifier::private(Str::ever("#ABCMeta"))),
|
||||
Some(Identifier::private("#ABCMeta")),
|
||||
),
|
||||
(
|
||||
Identifier::public("abstractmethod"),
|
||||
Some(Identifier::private(Str::ever("#abstractmethod"))),
|
||||
Some(Identifier::private("#abstractmethod")),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -2041,7 +2096,7 @@ impl CodeGenerator {
|
|||
Identifier::public("types"),
|
||||
vec![(
|
||||
Identifier::public("ModuleType"),
|
||||
Some(Identifier::private(Str::ever("#ModuleType"))),
|
||||
Some(Identifier::private("#ModuleType")),
|
||||
)],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -681,25 +681,26 @@ impl Context {
|
|||
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
|
||||
let subst_ctx = SubstContext::new(rhs, self, Location::Unknown);
|
||||
if let Some(super_traits) = self.get_nominal_type_ctx(rhs).map(|ctx| &ctx.super_traits) {
|
||||
for sup_trait in super_traits {
|
||||
let sup_trait = if sup_trait.has_qvar() {
|
||||
subst_ctx.substitute(sup_trait.clone()).unwrap()
|
||||
for super_trait in super_traits {
|
||||
let sup_trait = if super_trait.has_qvar() {
|
||||
subst_ctx.substitute(super_trait.clone()).unwrap()
|
||||
} else {
|
||||
sup_trait.clone()
|
||||
super_trait.clone()
|
||||
};
|
||||
if self.sup_conforms(lhs, rhs, &sup_trait) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(sup_classes) = self.get_nominal_type_ctx(rhs).map(|ctx| &ctx.super_classes) {
|
||||
for sup_class in sup_classes {
|
||||
let sup_class = if sup_class.has_qvar() {
|
||||
subst_ctx.substitute(sup_class.clone()).unwrap()
|
||||
if let Some(super_classes) = self.get_super_classes(rhs) {
|
||||
for super_class in super_classes {
|
||||
let sup_class = if super_class.has_qvar() {
|
||||
subst_ctx.substitute(super_class).unwrap()
|
||||
} else {
|
||||
sup_class.clone()
|
||||
super_class
|
||||
};
|
||||
if self.cyclic_supertype_of(lhs, &sup_class) {
|
||||
log!(err "引っかかった: {lhs}, {sup_class}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -849,6 +850,9 @@ impl Context {
|
|||
|
||||
/// returns union of two types (A or B)
|
||||
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||
if lhs == rhs {
|
||||
return lhs.clone();
|
||||
}
|
||||
// `?T or ?U` will not be unified
|
||||
// `Set!(?T, 3) or Set(?T, 3)` wii be unified to Set(?T, 3)
|
||||
if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
|
||||
|
@ -888,6 +892,9 @@ impl Context {
|
|||
|
||||
/// returns intersection of two types (A and B)
|
||||
pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||
if lhs == rhs {
|
||||
return lhs.clone();
|
||||
}
|
||||
// ?T and ?U will not be unified
|
||||
if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
|
||||
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
||||
|
|
|
@ -100,12 +100,6 @@ fn op_to_name(op: OpKind) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn eval_lit(lit: &Literal) -> ValueObj {
|
||||
let t = type_from_token_kind(lit.token.kind);
|
||||
ValueObj::from_str(t, lit.token.content.clone())
|
||||
}
|
||||
|
||||
/// Instantiate the polymorphic type from the quantified state.
|
||||
///
|
||||
/// e.g.
|
||||
|
@ -577,13 +571,26 @@ impl Context {
|
|||
Ok(ValueObj::Subr(subr))
|
||||
}
|
||||
|
||||
pub(crate) fn eval_lit(&self, lit: &Literal) -> EvalResult<ValueObj> {
|
||||
let t = type_from_token_kind(lit.token.kind);
|
||||
ValueObj::from_str(t, lit.token.content.clone()).ok_or_else(|| {
|
||||
EvalError::invalid_literal(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
lit.token.loc(),
|
||||
self.caused_by(),
|
||||
)
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn eval_const_expr(
|
||||
&self,
|
||||
expr: &Expr,
|
||||
__name__: Option<&Str>,
|
||||
) -> EvalResult<ValueObj> {
|
||||
match expr {
|
||||
Expr::Lit(lit) => Ok(eval_lit(lit)),
|
||||
Expr::Lit(lit) => self.eval_lit(lit),
|
||||
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
||||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||
|
@ -603,7 +610,7 @@ impl Context {
|
|||
__name__: Option<&Str>,
|
||||
) -> EvalResult<ValueObj> {
|
||||
match expr {
|
||||
Expr::Lit(lit) => Ok(eval_lit(lit)),
|
||||
Expr::Lit(lit) => self.eval_lit(lit),
|
||||
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
||||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||
|
|
|
@ -109,9 +109,14 @@ impl Context {
|
|||
panic!("{} has already been registered as const", t.name());
|
||||
} else {
|
||||
let name = VarName::from_str(t.name());
|
||||
let meta_t = match ctx.kind {
|
||||
ContextKind::Class => Type::ClassType,
|
||||
ContextKind::Trait => Type::TraitType,
|
||||
_ => Type::Type,
|
||||
};
|
||||
self.locals.insert(
|
||||
name.clone(),
|
||||
VarInfo::new(Type, muty, Private, Builtin, None),
|
||||
VarInfo::new(meta_t, muty, Private, Builtin, None),
|
||||
);
|
||||
self.consts
|
||||
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
||||
|
@ -156,9 +161,14 @@ impl Context {
|
|||
root_ctx.methods_list.push((ClassDefType::Simple(t), ctx));
|
||||
} else {
|
||||
let name = VarName::from_str(t.name());
|
||||
let meta_t = match ctx.kind {
|
||||
ContextKind::Class => Type::ClassType,
|
||||
ContextKind::Trait => Type::TraitType,
|
||||
_ => Type::Type,
|
||||
};
|
||||
self.locals.insert(
|
||||
name.clone(),
|
||||
VarInfo::new(Type, muty, Private, Builtin, None),
|
||||
VarInfo::new(meta_t, muty, Private, Builtin, None),
|
||||
);
|
||||
self.consts
|
||||
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
||||
|
@ -203,7 +213,7 @@ impl Context {
|
|||
let name = VarName::from_static(name);
|
||||
self.locals.insert(
|
||||
name.clone(),
|
||||
VarInfo::new(Type, muty, Private, Builtin, None),
|
||||
VarInfo::new(Patch, muty, Private, Builtin, None),
|
||||
);
|
||||
for method_name in ctx.locals.keys() {
|
||||
if let Some(patches) = self.method_impl_patches.get_mut(method_name) {
|
||||
|
@ -454,7 +464,7 @@ impl Context {
|
|||
/* Obj */
|
||||
let mut obj = Self::builtin_mono_class("Obj", 2);
|
||||
let t = fn0_met(mono_q("Self"), mono_q("Self"));
|
||||
let t = quant(t, set! {subtypeof(mono_q("Self"), builtin_mono("Obj"))});
|
||||
let t = quant(t, set! {subtypeof(mono_q("Self"), Obj)});
|
||||
obj.register_builtin_impl("clone", t, Const, Public);
|
||||
obj.register_builtin_impl("__module__", Str, Const, Public);
|
||||
obj.register_builtin_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public);
|
||||
|
@ -469,10 +479,11 @@ impl Context {
|
|||
);
|
||||
let mut obj_in = Self::builtin_methods("In", 2);
|
||||
obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public);
|
||||
obj.register_trait(Obj, builtin_poly("Eq", vec![ty_tp(Type)]), obj_in);
|
||||
obj.register_trait(Obj, builtin_poly("In", vec![ty_tp(Type)]), obj_in);
|
||||
let mut obj_mutizable = Self::builtin_methods("Mutizable", 1);
|
||||
obj_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Obj!")));
|
||||
obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable);
|
||||
// Obj does not implement Eq
|
||||
|
||||
/* Float */
|
||||
let mut float = Self::builtin_mono_class("Float", 2);
|
||||
|
@ -760,6 +771,24 @@ impl Context {
|
|||
let mut str_show = Self::builtin_methods("Show", 1);
|
||||
str_show.register_builtin_impl("to_str", fn0_met(Str, Str), Immutable, Public);
|
||||
str_.register_trait(Str, builtin_mono("Show"), str_show);
|
||||
/* NoneType */
|
||||
let mut nonetype = Self::builtin_mono_class("NoneType", 10);
|
||||
nonetype.register_superclass(Obj, &obj);
|
||||
let mut nonetype_eq = Self::builtin_methods("Eq", 2);
|
||||
nonetype_eq.register_builtin_impl(
|
||||
"__eq__",
|
||||
fn1_met(NoneType, NoneType, Bool),
|
||||
Const,
|
||||
Public,
|
||||
);
|
||||
nonetype.register_trait(
|
||||
NoneType,
|
||||
builtin_poly("Eq", vec![ty_tp(NoneType)]),
|
||||
nonetype_eq,
|
||||
);
|
||||
let mut nonetype_show = Self::builtin_methods("Show", 1);
|
||||
nonetype_show.register_builtin_impl("to_str", fn0_met(NoneType, Str), Immutable, Public);
|
||||
nonetype.register_trait(NoneType, builtin_mono("Show"), nonetype_show);
|
||||
/* Type */
|
||||
let mut type_ = Self::builtin_mono_class("Type", 2);
|
||||
type_.register_superclass(Obj, &obj);
|
||||
|
@ -783,6 +812,21 @@ impl Context {
|
|||
builtin_poly("Eq", vec![ty_tp(ClassType)]),
|
||||
class_eq,
|
||||
);
|
||||
let mut trait_type = Self::builtin_mono_class("TraitType", 2);
|
||||
trait_type.register_superclass(Type, &type_);
|
||||
trait_type.register_marker_trait(builtin_mono("Named"));
|
||||
let mut trait_eq = Self::builtin_methods("Eq", 2);
|
||||
trait_eq.register_builtin_impl(
|
||||
"__eq__",
|
||||
fn1_met(TraitType, TraitType, Bool),
|
||||
Const,
|
||||
Public,
|
||||
);
|
||||
trait_type.register_trait(
|
||||
TraitType,
|
||||
builtin_poly("Eq", vec![ty_tp(TraitType)]),
|
||||
trait_eq,
|
||||
);
|
||||
let g_module_t = builtin_mono("GenericModule");
|
||||
let mut generic_module = Self::builtin_mono_class("GenericModule", 2);
|
||||
generic_module.register_superclass(Obj, &obj);
|
||||
|
@ -849,7 +893,15 @@ impl Context {
|
|||
Immutable,
|
||||
Public,
|
||||
);
|
||||
array_.register_trait(array_t, builtin_mono("Show"), array_show);
|
||||
array_.register_trait(array_t.clone(), builtin_mono("Show"), array_show);
|
||||
let array_type_t = builtin_poly("ArrayType", vec![mono_q_tp("T"), mono_q_tp("N")]);
|
||||
let mut array_type = Self::builtin_poly_class(
|
||||
"ArrayType",
|
||||
vec![PS::named_nd("T", Type), PS::named_nd("N", Nat)],
|
||||
2,
|
||||
);
|
||||
array_type.register_superclass(array_t.clone(), &array_);
|
||||
array_type.register_superclass(Type, &type_);
|
||||
/* Set */
|
||||
let mut set_ =
|
||||
Self::builtin_poly_class("Set", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
||||
|
@ -892,6 +944,14 @@ impl Context {
|
|||
let mut set_show = Self::builtin_methods("Show", 1);
|
||||
set_show.register_builtin_impl("to_str", fn0_met(set_t.clone(), Str), Immutable, Public);
|
||||
set_.register_trait(set_t.clone(), builtin_mono("Show"), set_show);
|
||||
let set_type_t = builtin_poly("SetType", vec![mono_q_tp("T"), mono_q_tp("N")]);
|
||||
let mut set_type = Self::builtin_poly_class(
|
||||
"SetType",
|
||||
vec![PS::named_nd("T", Type), PS::named_nd("N", Nat)],
|
||||
2,
|
||||
);
|
||||
set_type.register_superclass(set_t.clone(), &set_);
|
||||
set_type.register_superclass(Type, &type_);
|
||||
/* Bytes */
|
||||
let mut bytes = Self::builtin_mono_class("Bytes", 2);
|
||||
bytes.register_superclass(Obj, &obj);
|
||||
|
@ -1117,243 +1177,16 @@ impl Context {
|
|||
),
|
||||
tuple5_eq,
|
||||
);
|
||||
let mut tuple6 = Self::builtin_poly_class(
|
||||
"Tuple6",
|
||||
vec![
|
||||
PS::t_nd("A"),
|
||||
PS::t_nd("B"),
|
||||
PS::t_nd("C"),
|
||||
PS::t_nd("D"),
|
||||
PS::t_nd("E"),
|
||||
PS::t_nd("F"),
|
||||
],
|
||||
2,
|
||||
);
|
||||
tuple6.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
let mut tuple6_eq = Self::builtin_methods("Eq", 2);
|
||||
tuple6_eq.register_builtin_impl(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
builtin_poly(
|
||||
"Tuple6",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
],
|
||||
),
|
||||
builtin_poly(
|
||||
"Tuple6",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
],
|
||||
),
|
||||
Bool,
|
||||
),
|
||||
Const,
|
||||
Public,
|
||||
);
|
||||
tuple6.register_trait(
|
||||
builtin_poly(
|
||||
"Tuple6",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
],
|
||||
),
|
||||
builtin_poly(
|
||||
"Eq",
|
||||
vec![ty_tp(builtin_poly(
|
||||
"Tuple6",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
],
|
||||
))],
|
||||
),
|
||||
tuple6_eq,
|
||||
);
|
||||
let mut tuple7 = Self::builtin_poly_class(
|
||||
"Tuple7",
|
||||
vec![
|
||||
PS::t_nd("A"),
|
||||
PS::t_nd("B"),
|
||||
PS::t_nd("C"),
|
||||
PS::t_nd("D"),
|
||||
PS::t_nd("E"),
|
||||
PS::t_nd("F"),
|
||||
PS::t_nd("G"),
|
||||
],
|
||||
2,
|
||||
);
|
||||
tuple7.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
let mut tuple7_eq = Self::builtin_methods("Eq", 2);
|
||||
tuple7_eq.register_builtin_impl(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
builtin_poly(
|
||||
"Tuple7",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
],
|
||||
),
|
||||
builtin_poly(
|
||||
"Tuple7",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
],
|
||||
),
|
||||
Bool,
|
||||
),
|
||||
Const,
|
||||
Public,
|
||||
);
|
||||
tuple7.register_trait(
|
||||
builtin_poly(
|
||||
"Tuple7",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
],
|
||||
),
|
||||
builtin_poly(
|
||||
"Eq",
|
||||
vec![ty_tp(builtin_poly(
|
||||
"Tuple7",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
],
|
||||
))],
|
||||
),
|
||||
tuple7_eq,
|
||||
);
|
||||
let mut tuple8 = Self::builtin_poly_class(
|
||||
"Tuple8",
|
||||
vec![
|
||||
PS::t_nd("A"),
|
||||
PS::t_nd("B"),
|
||||
PS::t_nd("C"),
|
||||
PS::t_nd("D"),
|
||||
PS::t_nd("E"),
|
||||
PS::t_nd("F"),
|
||||
PS::t_nd("G"),
|
||||
PS::t_nd("H"),
|
||||
],
|
||||
2,
|
||||
);
|
||||
tuple8.register_superclass(builtin_mono("Tuple"), &tuple_);
|
||||
let mut tuple8_eq = Self::builtin_methods("Eq", 2);
|
||||
tuple8_eq.register_builtin_impl(
|
||||
"__eq__",
|
||||
fn1_met(
|
||||
builtin_poly(
|
||||
"Tuple8",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
ty_tp(mono_q("H")),
|
||||
],
|
||||
),
|
||||
builtin_poly(
|
||||
"Tuple8",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
ty_tp(mono_q("H")),
|
||||
],
|
||||
),
|
||||
Bool,
|
||||
),
|
||||
Const,
|
||||
Public,
|
||||
);
|
||||
tuple8.register_trait(
|
||||
builtin_poly(
|
||||
"Tuple8",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
ty_tp(mono_q("H")),
|
||||
],
|
||||
),
|
||||
builtin_poly(
|
||||
"Eq",
|
||||
vec![ty_tp(builtin_poly(
|
||||
"Tuple8",
|
||||
vec![
|
||||
ty_tp(mono_q("A")),
|
||||
ty_tp(mono_q("B")),
|
||||
ty_tp(mono_q("C")),
|
||||
ty_tp(mono_q("D")),
|
||||
ty_tp(mono_q("E")),
|
||||
ty_tp(mono_q("F")),
|
||||
ty_tp(mono_q("G")),
|
||||
ty_tp(mono_q("H")),
|
||||
],
|
||||
))],
|
||||
),
|
||||
tuple8_eq,
|
||||
);
|
||||
/* record */
|
||||
let mut record = Self::builtin_mono_class("Record", 2);
|
||||
record.register_superclass(Obj, &obj);
|
||||
let mut record_type = Self::builtin_mono_class("RecordType", 2);
|
||||
record_type.register_superclass(builtin_mono("Record"), &record);
|
||||
record_type.register_superclass(builtin_mono("Type"), &type_);
|
||||
record_type.register_superclass(Type, &type_);
|
||||
/* Or (true or type) */
|
||||
let or_t = builtin_poly("Or", vec![ty_tp(mono_q("L")), ty_tp(mono_q("R"))]);
|
||||
let mut or = Self::builtin_poly_class("Or", vec![PS::t_nd("L"), PS::t_nd("R")], 2);
|
||||
or.register_superclass(Obj, &obj);
|
||||
/* Float_mut */
|
||||
let mut float_mut = Self::builtin_mono_class("Float!", 2);
|
||||
float_mut.register_superclass(Float, &float);
|
||||
|
@ -1378,15 +1211,7 @@ impl Context {
|
|||
ratio_mut.register_superclass(Ratio, &ratio);
|
||||
let mut ratio_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||
ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio));
|
||||
let f_t = kw(
|
||||
"f",
|
||||
func(
|
||||
vec![kw("old", builtin_mono("Ratio"))],
|
||||
None,
|
||||
vec![],
|
||||
builtin_mono("Ratio"),
|
||||
),
|
||||
);
|
||||
let f_t = kw("f", func(vec![kw("old", Ratio)], None, vec![], Ratio));
|
||||
let t = pr_met(
|
||||
ref_mut(builtin_mono("Ratio!"), None),
|
||||
vec![f_t],
|
||||
|
@ -1462,7 +1287,7 @@ impl Context {
|
|||
);
|
||||
/* Str_mut */
|
||||
let mut str_mut = Self::builtin_mono_class("Str!", 2);
|
||||
str_mut.register_superclass(Str, &str_);
|
||||
str_mut.register_superclass(Str, &nonetype);
|
||||
let mut str_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||
str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str));
|
||||
let f_t = kw("f", func(vec![kw("old", Str)], None, vec![], Str));
|
||||
|
@ -1500,7 +1325,6 @@ impl Context {
|
|||
file_mut_readable,
|
||||
);
|
||||
/* Array_mut */
|
||||
let array_t = builtin_poly("Array", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
|
||||
let array_mut_t = builtin_poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
|
||||
let mut array_mut_ = Self::builtin_poly_class(
|
||||
"Array!",
|
||||
|
@ -1617,7 +1441,8 @@ impl Context {
|
|||
/* Range */
|
||||
let range_t = builtin_poly("Range", vec![TyParam::t(mono_q("T"))]);
|
||||
let mut range = Self::builtin_poly_class("Range", vec![PS::t_nd("T")], 2);
|
||||
range.register_superclass(Obj, &obj);
|
||||
// range.register_superclass(Obj, &obj);
|
||||
range.register_superclass(Type, &type_);
|
||||
range.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))]));
|
||||
let mut range_eq = Self::builtin_methods("Eq", 2);
|
||||
range_eq.register_builtin_impl(
|
||||
|
@ -1653,12 +1478,16 @@ impl Context {
|
|||
self.register_builtin_type(Ratio, ratio, Const);
|
||||
self.register_builtin_type(Bool, bool_, Const);
|
||||
self.register_builtin_type(Str, str_, Const);
|
||||
self.register_builtin_type(NoneType, nonetype, Const);
|
||||
self.register_builtin_type(Type, type_, Const);
|
||||
self.register_builtin_type(ClassType, class_type, Const);
|
||||
self.register_builtin_type(TraitType, trait_type, Const);
|
||||
self.register_builtin_type(g_module_t, generic_module, Const);
|
||||
self.register_builtin_type(module_t, module, Const);
|
||||
self.register_builtin_type(array_t, array_, Const);
|
||||
self.register_builtin_type(array_type_t, array_type, Const);
|
||||
self.register_builtin_type(set_t, set_, Const);
|
||||
self.register_builtin_type(set_type_t, set_type, Const);
|
||||
self.register_builtin_type(builtin_mono("Bytes"), bytes, Const);
|
||||
self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const);
|
||||
self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const);
|
||||
|
@ -1683,47 +1512,9 @@ impl Context {
|
|||
tuple5,
|
||||
Const,
|
||||
);
|
||||
self.register_builtin_type(
|
||||
tuple(vec![
|
||||
mono_q("A"),
|
||||
mono_q("B"),
|
||||
mono_q("C"),
|
||||
mono_q("D"),
|
||||
mono_q("E"),
|
||||
mono_q("F"),
|
||||
]),
|
||||
tuple6,
|
||||
Const,
|
||||
);
|
||||
self.register_builtin_type(
|
||||
tuple(vec![
|
||||
mono_q("A"),
|
||||
mono_q("B"),
|
||||
mono_q("C"),
|
||||
mono_q("D"),
|
||||
mono_q("E"),
|
||||
mono_q("F"),
|
||||
mono_q("G"),
|
||||
]),
|
||||
tuple7,
|
||||
Const,
|
||||
);
|
||||
self.register_builtin_type(
|
||||
tuple(vec![
|
||||
mono_q("A"),
|
||||
mono_q("B"),
|
||||
mono_q("C"),
|
||||
mono_q("D"),
|
||||
mono_q("E"),
|
||||
mono_q("F"),
|
||||
mono_q("G"),
|
||||
mono_q("H"),
|
||||
]),
|
||||
tuple8,
|
||||
Const,
|
||||
);
|
||||
self.register_builtin_type(builtin_mono("Record"), record, Const);
|
||||
self.register_builtin_type(builtin_mono("RecordType"), record_type, Const);
|
||||
self.register_builtin_type(or_t, or, Const);
|
||||
self.register_builtin_type(builtin_mono("Int!"), int_mut, Const);
|
||||
self.register_builtin_type(builtin_mono("Nat!"), nat_mut, Const);
|
||||
self.register_builtin_type(builtin_mono("Float!"), float_mut, Const);
|
||||
|
@ -1744,12 +1535,19 @@ impl Context {
|
|||
|
||||
fn init_builtin_funcs(&mut self) {
|
||||
let t_abs = nd_func(vec![kw("n", builtin_mono("Num"))], None, Nat);
|
||||
let t_ascii = nd_func(vec![kw("object", Obj)], None, Str);
|
||||
let t_assert = func(
|
||||
vec![kw("condition", Bool)],
|
||||
None,
|
||||
vec![kw("err_message", Str)],
|
||||
NoneType,
|
||||
);
|
||||
let t_bin = nd_func(vec![kw("n", Int)], None, Str);
|
||||
let t_chr = nd_func(
|
||||
vec![kw("i", Type::from(value(0usize)..=value(1_114_111usize)))],
|
||||
None,
|
||||
Str,
|
||||
);
|
||||
let t_classof = nd_func(vec![kw("old", Obj)], None, ClassType);
|
||||
let t_compile = nd_func(vec![kw("src", Str)], None, Code);
|
||||
let t_cond = nd_func(
|
||||
|
@ -1786,6 +1584,27 @@ impl Context {
|
|||
module(mono_q_tp("Path")),
|
||||
);
|
||||
let t_import = quant(t_import, set! {static_instance("Path", Str)});
|
||||
let t_isinstance = nd_func(
|
||||
vec![
|
||||
kw("object", Obj),
|
||||
kw("classinfo", ClassType), // TODO: => ClassInfo
|
||||
],
|
||||
None,
|
||||
Bool,
|
||||
);
|
||||
let t_issubclass = nd_func(
|
||||
vec![
|
||||
kw("subclass", ClassType),
|
||||
kw("classinfo", ClassType), // TODO: => ClassInfo
|
||||
],
|
||||
None,
|
||||
Bool,
|
||||
);
|
||||
let t_len = nd_func(
|
||||
vec![kw("s", builtin_poly("Seq", vec![TyParam::erased(Type)]))],
|
||||
None,
|
||||
Nat,
|
||||
);
|
||||
let t_log = func(
|
||||
vec![],
|
||||
Some(kw("objects", ref_(Obj))),
|
||||
|
@ -1797,31 +1616,57 @@ impl Context {
|
|||
],
|
||||
NoneType,
|
||||
);
|
||||
let t_oct = nd_func(vec![kw("x", Int)], None, Str);
|
||||
let t_ord = nd_func(vec![kw("c", Str)], None, Nat);
|
||||
let t_panic = nd_func(vec![kw("err_message", Str)], None, Never);
|
||||
let m = mono_q("M");
|
||||
// TODO: mod
|
||||
let t_pow = nd_func(
|
||||
vec![kw("base", m.clone()), kw("exp", m.clone())],
|
||||
None,
|
||||
m.clone(),
|
||||
);
|
||||
let t_pow = quant(
|
||||
t_pow,
|
||||
set! {static_instance("M", builtin_poly("Mul", vec![ty_tp(m)]))},
|
||||
);
|
||||
let t_pyimport = nd_func(
|
||||
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
|
||||
None,
|
||||
module(mono_q_tp("Path")),
|
||||
);
|
||||
let t_panic = nd_func(vec![kw("err_message", Str)], None, NoneType);
|
||||
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
|
||||
let t_quit = func(vec![], None, vec![kw("code", Int)], NoneType);
|
||||
let t_exit = t_quit.clone();
|
||||
let t_repr = nd_func(vec![kw("object", Obj)], None, Str);
|
||||
let t_round = nd_func(vec![kw("number", Float)], None, Int);
|
||||
self.register_builtin_impl("abs", t_abs, Immutable, Private);
|
||||
self.register_builtin_impl("ascii", t_ascii, Immutable, Private);
|
||||
self.register_builtin_impl("assert", t_assert, Const, Private); // assert casting に悪影響が出る可能性があるため、Constとしておく
|
||||
self.register_builtin_impl("bin", t_bin, Immutable, Private);
|
||||
self.register_builtin_impl("chr", t_chr, Immutable, Private);
|
||||
self.register_builtin_impl("classof", t_classof, Immutable, Private);
|
||||
self.register_builtin_impl("compile", t_compile, Immutable, Private);
|
||||
self.register_builtin_impl("cond", t_cond, Immutable, Private);
|
||||
self.register_builtin_impl("discard", t_discard, Immutable, Private);
|
||||
self.register_builtin_impl("exit", t_exit, Immutable, Private);
|
||||
self.register_builtin_impl("if", t_if, Immutable, Private);
|
||||
self.register_builtin_impl("log", t_log, Immutable, Private);
|
||||
self.register_builtin_impl("import", t_import, Immutable, Private);
|
||||
self.register_builtin_impl("isinstance", t_isinstance, Immutable, Private);
|
||||
self.register_builtin_impl("issubclass", t_issubclass, Immutable, Private);
|
||||
self.register_builtin_impl("len", t_len, Immutable, Private);
|
||||
self.register_builtin_impl("log", t_log, Immutable, Private);
|
||||
self.register_builtin_impl("oct", t_oct, Immutable, Private);
|
||||
self.register_builtin_impl("ord", t_ord, Immutable, Private);
|
||||
self.register_builtin_impl("panic", t_panic, Immutable, Private);
|
||||
self.register_builtin_impl("pow", t_pow, Immutable, Private);
|
||||
if cfg!(feature = "debug") {
|
||||
self.register_builtin_impl("py", t_pyimport.clone(), Immutable, Private);
|
||||
}
|
||||
self.register_builtin_impl("pyimport", t_pyimport, Immutable, Private);
|
||||
self.register_builtin_impl("quit", t_quit, Immutable, Private);
|
||||
self.register_builtin_impl("repr", t_repr, Immutable, Private);
|
||||
self.register_builtin_impl("round", t_round, Immutable, Private);
|
||||
}
|
||||
|
||||
fn init_builtin_const_funcs(&mut self) {
|
||||
|
@ -2051,7 +1896,7 @@ impl Context {
|
|||
self.register_builtin_decl("__rorng__", op_t.clone(), Private);
|
||||
self.register_builtin_decl("__orng__", op_t, Private);
|
||||
// TODO: use existential type: |T: Type| (T, In(T)) -> Bool
|
||||
let op_t = bin_op(mono_q("T"), mono_q("I"), Bool);
|
||||
let op_t = bin_op(mono_q("I"), mono_q("T"), Bool);
|
||||
let op_t = quant(
|
||||
op_t,
|
||||
set! { static_instance("T", Type), subtypeof(mono_q("I"), builtin_poly("In", vec![ty_tp(mono_q("T"))])) },
|
||||
|
|
|
@ -17,7 +17,7 @@ use erg_parser::ast::{self, Identifier};
|
|||
use erg_parser::token::Token;
|
||||
|
||||
use erg_type::constructors::{
|
||||
anon, builtin_mono, free_var, func, module, mono_proj, subr_t, v_enum,
|
||||
anon, builtin_mono, builtin_poly, free_var, func, module, mono_proj, subr_t, v_enum,
|
||||
};
|
||||
use erg_type::free::Constraint;
|
||||
use erg_type::typaram::TyParam;
|
||||
|
@ -87,6 +87,31 @@ impl Context {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_mut_current_scope_var(&mut self, name: &str) -> Option<&mut VarInfo> {
|
||||
self.locals
|
||||
.get_mut(name)
|
||||
.or_else(|| self.decls.get_mut(name))
|
||||
.or_else(|| {
|
||||
self.params
|
||||
.iter_mut()
|
||||
.find(|(opt_name, _)| {
|
||||
opt_name
|
||||
.as_ref()
|
||||
.map(|n| &n.inspect()[..] == name)
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.map(|(_, vi)| vi)
|
||||
})
|
||||
.or_else(|| {
|
||||
for (_, methods) in self.methods_list.iter_mut() {
|
||||
if let Some(vi) = methods.get_mut_current_scope_var(name) {
|
||||
return Some(vi);
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_local_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
|
||||
self.locals.get_key_value(name)
|
||||
}
|
||||
|
@ -1160,8 +1185,19 @@ impl Context {
|
|||
}
|
||||
|
||||
pub(crate) fn get_similar_name(&self, name: &str) -> Option<&str> {
|
||||
match name {
|
||||
"true" => return Some("True"),
|
||||
"false" => return Some("False"),
|
||||
"Null" | "Nil" | "null" | "nil" | "none" => return Some("None"),
|
||||
"del" => return Some("Del"),
|
||||
"int" => return Some("Int"),
|
||||
"nat" => return Some("Nat"),
|
||||
"str" => return Some("Str"),
|
||||
"bool" => return Some("Bool"),
|
||||
_ => {}
|
||||
}
|
||||
let name = readable_name(name);
|
||||
// TODO: add decls
|
||||
// REVIEW: add decls?
|
||||
get_similar_name(
|
||||
self.params
|
||||
.iter()
|
||||
|
@ -1298,35 +1334,6 @@ impl Context {
|
|||
concatenated
|
||||
}
|
||||
|
||||
pub(crate) fn _get_nominal_super_trait_ctxs<'a>(
|
||||
&'a self,
|
||||
t: &Type,
|
||||
) -> Option<impl Iterator<Item = &'a Context>> {
|
||||
let ctx = self.get_nominal_type_ctx(t)?;
|
||||
Some(ctx.super_traits.iter().map(|sup| {
|
||||
let sup_ctx = self
|
||||
.get_nominal_type_ctx(sup)
|
||||
.unwrap_or_else(|| todo!("{} not found", sup));
|
||||
sup_ctx
|
||||
}))
|
||||
}
|
||||
|
||||
pub(crate) fn _get_nominal_super_class_ctxs<'a>(
|
||||
&'a self,
|
||||
t: &Type,
|
||||
) -> Option<impl Iterator<Item = &'a Context>> {
|
||||
// if `t` is {S: Str | ...}, `ctx_t` will be Str
|
||||
// else if `t` is Array(Int, 10), `ctx_t` will be Array(T, N) (if Array(Int, 10) is not specialized)
|
||||
let ctx = self.get_nominal_type_ctx(t)?;
|
||||
// t: {S: Str | ...} => ctx.super_traits: [Eq(Str), Mul(Nat), ...]
|
||||
// => return: [(Str, Eq(Str)), (Str, Mul(Nat)), ...] (the content of &'a Type isn't {S: Str | ...})
|
||||
Some(
|
||||
ctx.super_classes
|
||||
.iter()
|
||||
.map(|sup| self.get_nominal_type_ctx(sup).unwrap()),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option<Vec<&'a Context>> {
|
||||
match t {
|
||||
Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()),
|
||||
|
@ -1364,6 +1371,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
/// include `t` itself
|
||||
fn get_simple_nominal_super_type_ctxs<'a>(
|
||||
&'a self,
|
||||
t: &Type,
|
||||
|
@ -1377,6 +1385,19 @@ impl Context {
|
|||
Some(vec![ctx].into_iter().chain(sups))
|
||||
}
|
||||
|
||||
/// if `typ` is a refinement type, include the base type (refine.t)
|
||||
pub(crate) fn get_super_classes(&self, typ: &Type) -> Option<impl Iterator<Item = Type>> {
|
||||
self.get_nominal_type_ctx(typ).map(|ctx| {
|
||||
let super_classes = ctx.super_classes.clone();
|
||||
let derefined = typ.derefine();
|
||||
if typ != &derefined {
|
||||
vec![derefined].into_iter().chain(super_classes)
|
||||
} else {
|
||||
vec![].into_iter().chain(super_classes)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Never
|
||||
pub(crate) fn get_nominal_type_ctx<'a>(&'a self, typ: &Type) -> Option<&'a Context> {
|
||||
match typ {
|
||||
|
@ -1433,7 +1454,7 @@ impl Context {
|
|||
}
|
||||
Type::Poly { path, name, .. } => {
|
||||
if self.path() == path {
|
||||
if let Some((_, ctx)) = self.rec_get_mono_type(name) {
|
||||
if let Some((_, ctx)) = self.rec_get_poly_type(name) {
|
||||
return Some(ctx);
|
||||
}
|
||||
}
|
||||
|
@ -1448,7 +1469,7 @@ impl Context {
|
|||
.and_then(|cache| cache.ref_ctx(path.as_path()))
|
||||
})
|
||||
{
|
||||
if let Some((_, ctx)) = ctx.rec_get_mono_type(name) {
|
||||
if let Some((_, ctx)) = ctx.rec_get_poly_type(name) {
|
||||
return Some(ctx);
|
||||
}
|
||||
}
|
||||
|
@ -1495,16 +1516,10 @@ impl Context {
|
|||
return Some(res);
|
||||
}
|
||||
}
|
||||
Type::Or(l, r) => {
|
||||
let lctx = self.get_nominal_type_ctx(l)?;
|
||||
let rctx = self.get_nominal_type_ctx(r)?;
|
||||
// use smaller context
|
||||
return match (self.supertype_of(l, r), self.supertype_of(r, l)) {
|
||||
(true, true) => Some(lctx),
|
||||
(true, false) => Some(rctx),
|
||||
(false, true) => Some(lctx),
|
||||
(false, false) => None,
|
||||
};
|
||||
Type::Or(_l, _r) => {
|
||||
if let Some(ctx) = self.get_nominal_type_ctx(&builtin_poly("Or", vec![])) {
|
||||
return Some(ctx);
|
||||
}
|
||||
}
|
||||
// FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
|
||||
other if other.is_monomorphic() => {
|
||||
|
|
|
@ -26,7 +26,6 @@ use erg_type::{HasType, ParamTy, Predicate, SubrKind, TyBound, Type};
|
|||
use TyParamOrdering::*;
|
||||
use Type::*;
|
||||
|
||||
use crate::context::eval::eval_lit;
|
||||
use crate::context::{Context, RegistrationMode};
|
||||
use crate::error::{SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult};
|
||||
use crate::hir;
|
||||
|
@ -577,7 +576,7 @@ impl Context {
|
|||
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tmp_tv_ctx, mode)?
|
||||
} else {
|
||||
match &sig.pat {
|
||||
ast::ParamPattern::Lit(lit) => v_enum(set![eval_lit(lit)]),
|
||||
ast::ParamPattern::Lit(lit) => v_enum(set![self.eval_lit(lit)?]),
|
||||
// TODO: Array<Lit>
|
||||
_ => {
|
||||
let level = if mode == PreRegister {
|
||||
|
@ -613,7 +612,7 @@ impl Context {
|
|||
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||
match (sig.inspect(), &sig.opt_default_val) {
|
||||
(Some(name), Some(default)) => {
|
||||
let default = self.instantiate_const_expr(default);
|
||||
let default = self.instantiate_const_expr(default)?;
|
||||
Ok(ParamTy::kw_default(
|
||||
name.clone(),
|
||||
t,
|
||||
|
@ -665,7 +664,7 @@ impl Context {
|
|||
if let Some(first) = args.next() {
|
||||
let t = self.instantiate_const_expr_as_type(&first.expr)?;
|
||||
let len = args.next().unwrap();
|
||||
let len = self.instantiate_const_expr(&len.expr);
|
||||
let len = self.instantiate_const_expr(&len.expr)?;
|
||||
Ok(array(t, len))
|
||||
} else {
|
||||
Ok(builtin_mono("GenericArray"))
|
||||
|
@ -707,23 +706,28 @@ impl Context {
|
|||
}
|
||||
other => {
|
||||
// FIXME: kw args
|
||||
let params = simple.args.pos_args().map(|arg| match &arg.expr {
|
||||
ast::ConstExpr::Lit(lit) => TyParam::Value(eval_lit(lit)),
|
||||
_ => {
|
||||
todo!()
|
||||
let mut new_params = vec![];
|
||||
for arg in simple.args.pos_args() {
|
||||
match &arg.expr {
|
||||
ast::ConstExpr::Lit(lit) => {
|
||||
new_params.push(TyParam::Value(self.eval_lit(lit)?));
|
||||
}
|
||||
_ => {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// FIXME: non-builtin
|
||||
Ok(builtin_poly(Str::rc(other), params.collect()))
|
||||
Ok(builtin_poly(Str::rc(other), new_params))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn instantiate_const_expr(&self, expr: &ast::ConstExpr) -> TyParam {
|
||||
pub(crate) fn instantiate_const_expr(&self, expr: &ast::ConstExpr) -> TyCheckResult<TyParam> {
|
||||
match expr {
|
||||
ast::ConstExpr::Lit(lit) => TyParam::Value(eval_lit(lit)),
|
||||
ast::ConstExpr::Lit(lit) => Ok(TyParam::Value(self.eval_lit(lit)?)),
|
||||
ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => {
|
||||
TyParam::Mono(name.inspect().clone())
|
||||
Ok(TyParam::Mono(name.inspect().clone()))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
|
@ -780,13 +784,13 @@ impl Context {
|
|||
)),
|
||||
TypeSpec::Array(arr) => {
|
||||
let elem_t = self.instantiate_typespec(&arr.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||
let len = self.instantiate_const_expr(&arr.len);
|
||||
Ok(array(elem_t, len))
|
||||
let len = self.instantiate_const_expr(&arr.len)?;
|
||||
Ok(builtin_poly("ArrayType", vec![ty_tp(elem_t), len]))
|
||||
}
|
||||
TypeSpec::Set(set) => {
|
||||
let elem_t = self.instantiate_typespec(&set.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||
let len = self.instantiate_const_expr(&set.len);
|
||||
Ok(erg_type::constructors::set(elem_t, len))
|
||||
let len = self.instantiate_const_expr(&set.len)?;
|
||||
Ok(builtin_poly("SetType", vec![ty_tp(elem_t), len]))
|
||||
}
|
||||
// FIXME: unwrap
|
||||
TypeSpec::Tuple(tys) => Ok(tuple(
|
||||
|
@ -797,18 +801,18 @@ impl Context {
|
|||
})
|
||||
.collect(),
|
||||
)),
|
||||
// TODO: エラー処理(リテラルでない、ダブりがある)はパーサーにやらせる
|
||||
TypeSpec::Enum(set) => Ok(v_enum(
|
||||
set.pos_args()
|
||||
.map(|arg| {
|
||||
if let ast::ConstExpr::Lit(lit) = &arg.expr {
|
||||
eval_lit(lit)
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
})
|
||||
.collect::<Set<_>>(),
|
||||
)),
|
||||
// TODO: エラー処理(リテラルでない)はパーサーにやらせる
|
||||
TypeSpec::Enum(set) => {
|
||||
let mut new_set = set! {};
|
||||
for arg in set.pos_args() {
|
||||
if let ast::ConstExpr::Lit(lit) = &arg.expr {
|
||||
new_set.insert(self.eval_lit(lit)?);
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
Ok(v_enum(new_set))
|
||||
}
|
||||
TypeSpec::Interval { op, lhs, rhs } => {
|
||||
let op = match op.kind {
|
||||
TokenKind::Closed => IntervalOp::Closed,
|
||||
|
@ -817,9 +821,9 @@ impl Context {
|
|||
TokenKind::Open => IntervalOp::Open,
|
||||
_ => assume_unreachable!(),
|
||||
};
|
||||
let l = self.instantiate_const_expr(lhs);
|
||||
let l = self.instantiate_const_expr(lhs)?;
|
||||
let l = self.eval_tp(&l)?;
|
||||
let r = self.instantiate_const_expr(rhs);
|
||||
let r = self.instantiate_const_expr(rhs)?;
|
||||
let r = self.eval_tp(&r)?;
|
||||
if let Some(Greater) = self.try_cmp(&l, &r) {
|
||||
panic!("{l}..{r} is not a valid interval type (should be lhs <= rhs)")
|
||||
|
|
|
@ -281,6 +281,7 @@ pub enum OperationKind {
|
|||
Import,
|
||||
PyImport,
|
||||
Del,
|
||||
AssertCast,
|
||||
}
|
||||
|
||||
impl OperationKind {
|
||||
|
|
|
@ -14,8 +14,9 @@ use ast::{DefId, Identifier, VarName};
|
|||
use erg_parser::ast;
|
||||
|
||||
use erg_type::constructors::{func, func1, proc, ref_, ref_mut, v_enum};
|
||||
use erg_type::free::{Constraint, Cyclicity, FreeKind};
|
||||
use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||
use erg_type::{ParamTy, SubrType, Type};
|
||||
use erg_type::{HasType, ParamTy, SubrType, Type};
|
||||
|
||||
use crate::build_hir::HIRBuilder;
|
||||
use crate::context::{
|
||||
|
@ -1076,4 +1077,75 @@ impl Context {
|
|||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cast(
|
||||
&mut self,
|
||||
type_spec: ast::TypeSpec,
|
||||
call: &mut hir::Call,
|
||||
) -> TyCheckResult<()> {
|
||||
let cast_to =
|
||||
self.instantiate_typespec(&type_spec, None, None, RegistrationMode::Normal)?;
|
||||
let lhs = enum_unwrap!(
|
||||
call.args.get_mut_left_or_key("pred").unwrap(),
|
||||
hir::Expr::BinOp
|
||||
)
|
||||
.lhs
|
||||
.as_mut();
|
||||
match (
|
||||
self.supertype_of(lhs.ref_t(), &cast_to),
|
||||
self.subtype_of(lhs.ref_t(), &cast_to),
|
||||
) {
|
||||
// assert 1 in {1}
|
||||
(true, true) => Ok(()),
|
||||
// assert x in Int (x: Nat)
|
||||
(false, true) => Ok(()), // TODO: warn (needless)
|
||||
// assert x in Nat (x: Int)
|
||||
(true, false) => {
|
||||
if let hir::Expr::Accessor(ref acc) = lhs {
|
||||
self.change_var_type(acc, cast_to.clone())?;
|
||||
}
|
||||
match lhs.ref_t() {
|
||||
Type::FreeVar(fv) if fv.is_linked() => {
|
||||
let constraint = Constraint::new_subtype_of(cast_to, Cyclicity::Not);
|
||||
fv.replace(FreeKind::new_unbound(self.level, constraint));
|
||||
}
|
||||
Type::FreeVar(fv) => {
|
||||
let new_constraint = Constraint::new_subtype_of(cast_to, Cyclicity::Not);
|
||||
fv.update_constraint(new_constraint);
|
||||
}
|
||||
_ => {
|
||||
*lhs.ref_mut_t() = cast_to;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// assert x in Str (x: Int)
|
||||
(false, false) => Err(TyCheckErrors::from(TyCheckError::invalid_type_cast_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
lhs.loc(),
|
||||
self.caused_by(),
|
||||
&lhs.to_string(),
|
||||
&cast_to,
|
||||
None,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn change_var_type(&mut self, acc: &hir::Accessor, t: Type) -> TyCheckResult<()> {
|
||||
#[allow(clippy::single_match)]
|
||||
match acc {
|
||||
hir::Accessor::Ident(ident) => {
|
||||
if let Some(vi) = self.get_mut_current_scope_var(ident.inspect()) {
|
||||
vi.t = t;
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// TODO: support other accessors
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -671,6 +671,13 @@ impl Context {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
hir::Array::WithLength(arr) => {
|
||||
let loc = arr.loc();
|
||||
arr.t = self.deref_tyvar(mem::take(&mut arr.t), Covariant, loc)?;
|
||||
self.resolve_expr_t(&mut arr.elem)?;
|
||||
self.resolve_expr_t(&mut arr.len)?;
|
||||
Ok(())
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
hir::Expr::Tuple(tuple) => match tuple {
|
||||
|
@ -683,12 +690,20 @@ impl Context {
|
|||
},
|
||||
hir::Expr::Set(set) => match set {
|
||||
hir::Set::Normal(st) => {
|
||||
let loc = st.loc();
|
||||
st.t = self.deref_tyvar(mem::take(&mut st.t), Covariant, loc)?;
|
||||
for elem in st.elems.pos_args.iter_mut() {
|
||||
self.resolve_expr_t(&mut elem.expr)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
hir::Set::WithLength(_) => todo!(),
|
||||
hir::Set::WithLength(st) => {
|
||||
let loc = st.loc();
|
||||
st.t = self.deref_tyvar(mem::take(&mut st.t), Covariant, loc)?;
|
||||
self.resolve_expr_t(&mut st.elem)?;
|
||||
self.resolve_expr_t(&mut st.len)?;
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
hir::Expr::Dict(_dict) => {
|
||||
todo!()
|
||||
|
|
|
@ -990,6 +990,30 @@ impl EvalError {
|
|||
caused_by,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn invalid_literal(
|
||||
input: Input,
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
caused_by: AtomicStr,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
ErrorCore::new(
|
||||
errno,
|
||||
SyntaxError,
|
||||
loc,
|
||||
switch_lang!(
|
||||
"japanese" => "リテラルが不正です",
|
||||
"simplified_chinese" => "字面量不合法",
|
||||
"traditional_chinese" => "字面量不合法",
|
||||
"english" => "invalid literal",
|
||||
),
|
||||
None,
|
||||
),
|
||||
input,
|
||||
caused_by,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub type EffectError = TyCheckError;
|
||||
|
@ -1568,6 +1592,34 @@ impl LowerError {
|
|||
caused_by,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn invalid_type_cast_error(
|
||||
input: Input,
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
caused_by: AtomicStr,
|
||||
name: &str,
|
||||
cast_to: &Type,
|
||||
hint: Option<AtomicStr>,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
ErrorCore::new(
|
||||
errno,
|
||||
TypeError,
|
||||
loc,
|
||||
switch_lang!(
|
||||
"japanese" => format!("{YELLOW}{name}{RESET}の型を{RED}{cast_to}{RESET}にキャストすることはできません"),
|
||||
"simplified_chinese" => format!("{YELLOW}{name}{RESET}的类型无法转换为{RED}{cast_to}{RESET}"),
|
||||
"traditional_chinese" => format!("{YELLOW}{name}{RESET}的類型無法轉換為{RED}{cast_to}{RESET}"),
|
||||
"english" => format!("the type of {YELLOW}{name}{RESET} cannot be cast to {RED}{cast_to}{RESET}"),
|
||||
),
|
||||
hint,
|
||||
),
|
||||
input,
|
||||
caused_by,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -47,14 +47,16 @@ impl Locational for Literal {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Token> for Literal {
|
||||
fn from(token: Token) -> Self {
|
||||
let data = ValueObj::from_str(type_from_token_kind(token.kind), token.content.clone());
|
||||
Self {
|
||||
impl TryFrom<Token> for Literal {
|
||||
type Error = ();
|
||||
fn try_from(token: Token) -> Result<Self, ()> {
|
||||
let data =
|
||||
ValueObj::from_str(type_from_token_kind(token.kind), token.content.clone()).ok_or(())?;
|
||||
Ok(Self {
|
||||
t: data.t(),
|
||||
value: data,
|
||||
token,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,6 +284,20 @@ impl Args {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_mut_left_or_key(&mut self, key: &str) -> Option<&mut Expr> {
|
||||
if !self.pos_args.is_empty() {
|
||||
Some(&mut self.pos_args.get_mut(0)?.expr)
|
||||
} else if let Some(pos) = self
|
||||
.kw_args
|
||||
.iter()
|
||||
.position(|arg| &arg.keyword.inspect()[..] == key)
|
||||
{
|
||||
Some(&mut self.kw_args.get_mut(pos)?.expr)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_pos(&mut self, idx: usize, pos: PosArg) {
|
||||
self.pos_args.insert(idx, pos);
|
||||
}
|
||||
|
@ -351,8 +367,8 @@ impl Identifier {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn private(name: Str) -> Self {
|
||||
Self::bare(None, VarName::from_str(name))
|
||||
pub fn private(name: &'static str) -> Self {
|
||||
Self::bare(None, VarName::from_static(name))
|
||||
}
|
||||
|
||||
pub fn private_with_line(name: Str, line: usize) -> Self {
|
||||
|
|
|
@ -59,6 +59,10 @@ impl<'a> Linker<'a> {
|
|||
self.replace_import(&mut elem.expr);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
self.replace_import(&mut arr.elem);
|
||||
self.replace_import(&mut arr.len);
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
|
@ -74,9 +78,11 @@ impl<'a> Linker<'a> {
|
|||
self.replace_import(&mut elem.expr);
|
||||
}
|
||||
}
|
||||
Set::WithLength(_) => todo!(),
|
||||
Set::WithLength(st) => {
|
||||
self.replace_import(&mut st.elem);
|
||||
self.replace_import(&mut st.len);
|
||||
}
|
||||
},
|
||||
|
||||
Expr::Dict(_dict) => {
|
||||
todo!()
|
||||
}
|
||||
|
@ -241,7 +247,7 @@ impl<'a> Linker<'a> {
|
|||
mod_name_lit.ln_begin().unwrap(),
|
||||
mod_name_lit.col_begin().unwrap(),
|
||||
);
|
||||
let mod_name = Expr::Lit(Literal::from(token));
|
||||
let mod_name = Expr::Lit(Literal::try_from(token).unwrap());
|
||||
args.insert_pos(0, PosArg::new(mod_name));
|
||||
let line = expr.ln_begin().unwrap_or(0);
|
||||
for attr in comps {
|
||||
|
|
|
@ -15,6 +15,7 @@ use erg_parser::ast;
|
|||
use erg_parser::ast::AST;
|
||||
use erg_parser::build_ast::ASTBuilder;
|
||||
use erg_parser::token::{Token, TokenKind};
|
||||
use erg_parser::Parser;
|
||||
|
||||
use erg_type::constructors::{
|
||||
array, array_mut, builtin_mono, builtin_poly, free_var, func, mono, proc, quant, set, set_mut,
|
||||
|
@ -182,6 +183,19 @@ impl ASTLowerer {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_literal(&self, lit: ast::Literal) -> LowerResult<hir::Literal> {
|
||||
let loc = lit.loc();
|
||||
let lit = hir::Literal::try_from(lit.token).map_err(|_| {
|
||||
LowerError::invalid_literal(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
loc,
|
||||
self.ctx.caused_by(),
|
||||
)
|
||||
})?;
|
||||
Ok(lit)
|
||||
}
|
||||
|
||||
fn lower_array(&mut self, array: ast::Array) -> LowerResult<hir::Array> {
|
||||
log!(info "entered {}({array})", fn_name!());
|
||||
match array {
|
||||
|
@ -260,6 +274,8 @@ impl ASTLowerer {
|
|||
"ArrayWithMutType!",
|
||||
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
||||
)
|
||||
} else if self.ctx.subtype_of(&elem.t(), &Type::Type) {
|
||||
builtin_poly("ArrayType", vec![TyParam::t(elem.t()), TyParam::Value(v)])
|
||||
} else {
|
||||
array(elem.t(), TyParam::Value(v))
|
||||
}
|
||||
|
@ -429,6 +445,8 @@ impl ASTLowerer {
|
|||
"SetWithMutType!",
|
||||
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
||||
)
|
||||
} else if self.ctx.subtype_of(&elem.t(), &Type::Type) {
|
||||
builtin_poly("SetType", vec![TyParam::t(elem.t()), TyParam::Value(v)])
|
||||
} else {
|
||||
set(elem.t(), TyParam::Value(v))
|
||||
}
|
||||
|
@ -489,7 +507,7 @@ impl ASTLowerer {
|
|||
}
|
||||
ast::Accessor::TupleAttr(t_attr) => {
|
||||
let obj = self.lower_expr(*t_attr.obj)?;
|
||||
let index = hir::Literal::from(t_attr.index.token);
|
||||
let index = self.lower_literal(t_attr.index)?;
|
||||
let n = enum_unwrap!(index.value, ValueObj::Nat);
|
||||
let t = enum_unwrap!(
|
||||
obj.ref_t().typarams().get(n as usize).unwrap().clone(),
|
||||
|
@ -562,9 +580,27 @@ impl ASTLowerer {
|
|||
Ok(hir::UnaryOp::new(unary.op, expr, t))
|
||||
}
|
||||
|
||||
// TODO: single `import`
|
||||
fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
|
||||
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.method_name));
|
||||
let opt_cast_to = if call.is_assert_cast() {
|
||||
if let Some(typ) = call.assert_cast_target_type() {
|
||||
Some(Parser::expr_to_type_spec(typ.clone()).map_err(|e| {
|
||||
let e = LowerError::new(e.into(), self.input().clone(), self.ctx.caused_by());
|
||||
LowerErrors::from(e)
|
||||
})?)
|
||||
} else {
|
||||
return Err(LowerErrors::from(LowerError::syntax_error(
|
||||
self.input().clone(),
|
||||
line!() as usize,
|
||||
call.args.loc(),
|
||||
self.ctx.caused_by(),
|
||||
"invalid assert casting type",
|
||||
None,
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let (pos_args, kw_args, paren) = call.args.deconstruct();
|
||||
let mut hir_args = hir::Args::new(
|
||||
Vec::with_capacity(pos_args.len()),
|
||||
|
@ -597,7 +633,7 @@ impl ASTLowerer {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let call = hir::Call::new(obj, method_name, hir_args, sig_t);
|
||||
let mut call = hir::Call::new(obj, method_name, hir_args, sig_t);
|
||||
match call.additional_operation() {
|
||||
Some(kind @ (OperationKind::Import | OperationKind::PyImport)) => {
|
||||
let mod_name =
|
||||
|
@ -621,7 +657,12 @@ impl ASTLowerer {
|
|||
)))
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
_ => {
|
||||
if let Some(type_spec) = opt_cast_to {
|
||||
log!(err "cast({type_spec}): {call}");
|
||||
self.ctx.cast(type_spec, &mut call)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(call)
|
||||
}
|
||||
|
@ -1241,7 +1282,7 @@ impl ASTLowerer {
|
|||
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
match expr {
|
||||
ast::Expr::Lit(lit) => Ok(hir::Expr::Lit(hir::Literal::from(lit.token))),
|
||||
ast::Expr::Lit(lit) => Ok(hir::Expr::Lit(self.lower_literal(lit)?)),
|
||||
ast::Expr::Array(arr) => Ok(hir::Expr::Array(self.lower_array(arr)?)),
|
||||
ast::Expr::Tuple(tup) => Ok(hir::Expr::Tuple(self.lower_tuple(tup)?)),
|
||||
ast::Expr::Record(rec) => Ok(hir::Expr::Record(self.lower_record(rec)?)),
|
||||
|
|
|
@ -156,6 +156,10 @@ impl OwnershipChecker {
|
|||
self.check_expr(&a.expr, ownership, false);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
self.check_expr(&arr.elem, ownership, false);
|
||||
self.check_expr(&arr.len, ownership, false);
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
|
@ -182,12 +186,15 @@ impl OwnershipChecker {
|
|||
}
|
||||
}
|
||||
Expr::Set(set) => match set {
|
||||
hir::Set::Normal(set) => {
|
||||
for a in set.elems.pos_args.iter() {
|
||||
hir::Set::Normal(st) => {
|
||||
for a in st.elems.pos_args.iter() {
|
||||
self.check_expr(&a.expr, ownership, false);
|
||||
}
|
||||
}
|
||||
hir::Set::WithLength(_) => todo!(),
|
||||
hir::Set::WithLength(st) => {
|
||||
self.check_expr(&st.elem, ownership, false);
|
||||
self.check_expr(&st.len, ownership, false);
|
||||
}
|
||||
},
|
||||
// TODO: capturing
|
||||
Expr::Lambda(lambda) => {
|
||||
|
|
107
compiler/erg_compiler/std/_erg_std_prelude.py
Normal file
107
compiler/erg_compiler/std/_erg_std_prelude.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
from collections.abc import Iterable, Sequence, Iterator, Container
|
||||
|
||||
def in_operator(x, y):
|
||||
if type(y) == type:
|
||||
if isinstance(x, y):
|
||||
return True
|
||||
# TODO: trait check
|
||||
return False
|
||||
elif (type(y) == list or type(y) == set) and type(y[0]) == type:
|
||||
# FIXME:
|
||||
type_check = in_operator(x[0], y[0])
|
||||
len_check = len(x) == len(y)
|
||||
return type_check and len_check
|
||||
elif type(y) == dict and type(y[0]) == type:
|
||||
NotImplemented
|
||||
else:
|
||||
return x in y
|
||||
|
||||
class Range:
|
||||
def __init__(self, start, end):
|
||||
self.start = start
|
||||
self.end = end
|
||||
def __contains__(self, item):
|
||||
pass
|
||||
def __getitem__(self, item):
|
||||
pass
|
||||
def __len__(self):
|
||||
pass
|
||||
def __iter__(self):
|
||||
return RangeIterator(rng=self)
|
||||
|
||||
Sequence.register(Range)
|
||||
Container.register(Range)
|
||||
Iterable.register(Range)
|
||||
|
||||
# represents `start<..end`
|
||||
class LeftOpenRange(Range):
|
||||
def __contains__(self, item):
|
||||
return self.start < item <= self.end
|
||||
def __getitem__(self, item):
|
||||
return NotImplemented
|
||||
def __len__(self):
|
||||
return NotImplemented
|
||||
|
||||
# represents `start..<end`
|
||||
class RightOpenRange(Range):
|
||||
def __contains__(self, item):
|
||||
return self.start <= item < self.end
|
||||
def __getitem__(self, item):
|
||||
return NotImplemented
|
||||
def __len__(self):
|
||||
return NotImplemented
|
||||
|
||||
# represents `start<..<end`
|
||||
class OpenRange(Range):
|
||||
def __contains__(self, item):
|
||||
return self.start < item < self.end
|
||||
def __getitem__(self, item):
|
||||
return NotImplemented
|
||||
def __len__(self):
|
||||
return NotImplemented
|
||||
|
||||
# represents `start..end`
|
||||
class ClosedRange(Range):
|
||||
def __contains__(self, item):
|
||||
return self.start <= item <= self.end
|
||||
def __getitem__(self, item):
|
||||
return NotImplemented
|
||||
def __len__(self):
|
||||
return NotImplemented
|
||||
|
||||
class RangeIterator:
|
||||
def __init__(self, rng):
|
||||
self.rng = rng
|
||||
self.needle = self.rng.start
|
||||
if type(self.rng.start) == int:
|
||||
if not(self.needle in self.rng):
|
||||
self.needle += 1
|
||||
elif type(self.rng.start) == str:
|
||||
if not(self.needle in self.rng):
|
||||
self.needle = chr(ord(self.needle) + 1)
|
||||
else:
|
||||
if not(self.needle in self.rng):
|
||||
self.needle = self.needle.incremented()
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if type(self.rng.start) == int:
|
||||
if self.needle in self.rng:
|
||||
result = self.needle
|
||||
self.needle += 1
|
||||
return result
|
||||
elif type(self.rng.start) == str:
|
||||
if self.needle in self.rng:
|
||||
result = self.needle
|
||||
self.needle = chr(ord(self.needle) + 1)
|
||||
return result
|
||||
else:
|
||||
if self.needle in self.rng:
|
||||
result = self.needle
|
||||
self.needle = self.needle.incremented()
|
||||
return result
|
||||
raise StopIteration
|
||||
|
||||
Iterator.register(RangeIterator)
|
82
compiler/erg_compiler/std/_prelude.er
Normal file
82
compiler/erg_compiler/std/_prelude.er
Normal file
|
@ -0,0 +1,82 @@
|
|||
@Attach NeImpl
|
||||
Eq(R := Self) = Trait {
|
||||
.`==` = (self: Self, R) -> Bool
|
||||
}
|
||||
|
||||
NeImpl R = Patch Eq R
|
||||
NeImpl(R).
|
||||
`!=`(self, other: R): Bool = not(self == other)
|
||||
|
||||
@Attach EqImpl, LeImpl, LtImpl, GeImpl, GtImpl
|
||||
PartialOrd(R := Self) = Trait {
|
||||
.cmp = (self: Self, R) -> Option Ordering
|
||||
}
|
||||
Ord = Subsume PartialOrd()
|
||||
|
||||
EqForOrd R = Patch Ord, Impl := Eq()
|
||||
EqForOrd(R).
|
||||
`==`(self, other: R): Bool = self.cmp(other) == Ordering.Equal
|
||||
|
||||
LeForOrd = Patch Ord
|
||||
LeForOrd.
|
||||
`<=`(self, other: Self): Bool = self.cmp(other) == Ordering.Less or self == other
|
||||
LtForOrd = Patch Ord
|
||||
LtForOrd.
|
||||
`<`(self, other: Self): Bool = self.cmp(other) == Ordering.Less
|
||||
GeForOrd = Patch Ord
|
||||
GeForOrd.
|
||||
`>=`(self, other: Self): Bool = self.cmp(other) == Ordering.Greater or self == other
|
||||
GtForOrd = Patch Ord
|
||||
GtForOrd.
|
||||
`>`(self, other: Self): Bool = self.cmp(other) == Ordering.Greater
|
||||
|
||||
Add(R := Self) = Trait {
|
||||
.Output = Type
|
||||
.`_+_` = (self: Self, R) -> Self.Output
|
||||
}
|
||||
Sub(R := Self) = Trait {
|
||||
.Output = Type
|
||||
.`_-_` = (self: Self, R) -> Self.Output
|
||||
}
|
||||
Mul(R := Self()) = Trait {
|
||||
.Output = Type
|
||||
.`*` = (self: Self, R) -> Self.Output
|
||||
}
|
||||
Div(R := Self) = Trait {
|
||||
.Output = Type
|
||||
.`/` = (self: Self, R) -> Self.Output or Panic
|
||||
}
|
||||
Num: (R := Type) -> Type
|
||||
Num = Add and Sub and Mul
|
||||
|
||||
Seq T = Trait {
|
||||
.__len__ = (self: Ref(Self)) -> Nat
|
||||
.get = (self: Ref(Self), Nat) -> T
|
||||
}
|
||||
|
||||
`_+_`: |R: Type, A <: Add(R)| (A, R) -> A.AddO
|
||||
`_-_`: |R: Type, S <: Add(R)| (S, R) -> S.SubO
|
||||
`*`: |R, O: Type, M <: Add(R)| (M, R) -> M.MulO
|
||||
`/`: |R, O: Type, D <: Add(R)| (D, R) -> D.DivO
|
||||
|
||||
AddForInt = Patch Int, Impl := Add()
|
||||
AddForInt.AddO = Int
|
||||
AddForInt.
|
||||
`_+_`: (self: Self, other: Int) -> Int = magic("Add.`_+_`")
|
||||
|
||||
# TODO: Mul and Div
|
||||
NumForInterval M, N, O, P: Int =
|
||||
Patch M..N, Impl := Add(R := O..P) and Sub(R := O..P)
|
||||
NumForInterval(M, N, O, P).
|
||||
`_+_`: (self: Self, other: O..P) -> M+O..N+P = magic("NumForInterval.`_+_`")
|
||||
`_-_`: (self: Self, other: O..P) -> M-P..N-O = magic("NumForInterval.`_-_`")
|
||||
|
||||
Read = Trait {
|
||||
.read = (self: Ref(Self)) -> Str
|
||||
}
|
||||
Read! = Trait {
|
||||
.read! = (self: Ref!(Self)) => Str
|
||||
}
|
||||
Write! = Trait {
|
||||
.write! = (self: Ref!(Self), Str) => ()
|
||||
}
|
13
compiler/erg_compiler/std/prelude.er
Normal file
13
compiler/erg_compiler/std/prelude.er
Normal file
|
@ -0,0 +1,13 @@
|
|||
discard _x = None
|
||||
|
||||
discard 1
|
||||
|
||||
# if: |T, U|(Bool, T, U) -> T or U
|
||||
cond|T: Type|(c: Bool, then: T, else: T): T =
|
||||
if c:
|
||||
do then
|
||||
do else
|
||||
|
||||
assert cond(False, 1, 2) == 2
|
||||
# assert cond(True, 1, 3) == "a"
|
||||
# assert "a" == cond(True, 1, 3)
|
Loading…
Add table
Add a link
Reference in a new issue