mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-07 13:15:21 +00:00
refactor!: rename Array
-> List
This commit is contained in:
parent
41bf14629b
commit
c6eb78a44d
248 changed files with 1948 additions and 1985 deletions
|
@ -150,10 +150,10 @@
|
|||
2│ l = [1, 2, 3]
|
||||
3│ l.push!(x)
|
||||
^^^^^
|
||||
AttributeError: Array object has no attribute `.push!`
|
||||
AttributeError: List object has no attribute `.push!`
|
||||
hint: to update the internal state of an object, make it mutable by using `!` operator
|
||||
hint: `Array` has `push`, see https://erg-lang.github.io/docs/prelude/Array/##push for more information
|
||||
hint: `Array!` has `push!`, see https://erg-lang.github.io/docs/prelude/Array!/##push! for more information
|
||||
hint: `List` has `push`, see https://erg-lang.github.io/docs/prelude/List/##push for more information
|
||||
hint: `List!` has `push!`, see https://erg-lang.github.io/docs/prelude/List!/##push! for more information
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
|
|
@ -150,10 +150,10 @@
|
|||
2│ l = [1, 2, 3]
|
||||
3│ l.push!(x)
|
||||
^^^^^
|
||||
AttributeError: Arrayオブジェクトは`.push!`という属性を持っていません
|
||||
AttributeError: Listオブジェクトは`.push!`という属性を持っていません
|
||||
ヒント: オブジェクトの内部状態を変更したい場合は、`!`演算子を使って可変化してください
|
||||
ヒント: `Array`は`push`メソッドを持っています、詳しくは https://erg-lang.github.io/docs/prelude/Array/##push を参照してください
|
||||
ヒント: `Array!`は`push!`メソッドを持っています、詳しくは https://erg-lang.github.io/docs/prelude/Array!/##push! を参照してください
|
||||
ヒント: `List`は`push`メソッドを持っています、詳しくは https://erg-lang.github.io/docs/prelude/List/##push を参照してください
|
||||
ヒント: `List!`は`push!`メソッドを持っています、詳しくは https://erg-lang.github.io/docs/prelude/List!/##push! を参照してください
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
|
|
@ -150,10 +150,10 @@
|
|||
2│ l = [1, 2, 3]
|
||||
3│ l.push!(x)
|
||||
^^^^^
|
||||
AttributeError: Array object has no attribute `.push!`
|
||||
AttributeError: List object has no attribute `.push!`
|
||||
hint: to update the internal state of an object, make it mutable by using `!` operator
|
||||
hint: `Array` has `push`, see https://erg-lang.github.io/docs/prelude/Array/##push for more information
|
||||
hint: `Array!` has `push!`, see https://erg-lang.github.io/docs/prelude/Array!/##push! for more information
|
||||
hint: `List` has `push`, see https://erg-lang.github.io/docs/prelude/List/##push for more information
|
||||
hint: `List!` has `push!`, see https://erg-lang.github.io/docs/prelude/List!/##push! for more information
|
||||
```
|
||||
|
||||
## 要求
|
||||
|
|
|
@ -150,10 +150,10 @@
|
|||
2│ l = [1, 2, 3]
|
||||
3│ l.push!(x)
|
||||
^^^^^
|
||||
AttributeError: Array object has no attribute `.push!`
|
||||
AttributeError: List object has no attribute `.push!`
|
||||
hint: to update the internal state of an object, make it mutable by using `!` operator
|
||||
hint: `Array` has `push`, see https://erg-lang.github.io/docs/prelude/Array/##push for more information
|
||||
hint: `Array!` has `push!`, see https://erg-lang.github.io/docs/prelude/Array!/##push! for more information
|
||||
hint: `List` has `push`, see https://erg-lang.github.io/docs/prelude/List/##push for more information
|
||||
hint: `List!` has `push!`, see https://erg-lang.github.io/docs/prelude/List!/##push! for more information
|
||||
```
|
||||
|
||||
## 要求
|
||||
|
|
14
TODO.md
14
TODO.md
|
@ -21,7 +21,7 @@
|
|||
* [ ] Pattern-matching
|
||||
* [x] Variable Pattern
|
||||
* [x] Literal Pattern
|
||||
* [x] Array Pattern
|
||||
* [x] List Pattern
|
||||
* [x] Tuple Pattern
|
||||
* [x] Record Pattern
|
||||
* [x] Data Type Pattern
|
||||
|
@ -30,7 +30,7 @@
|
|||
* [x] Positional arguments
|
||||
* [x] Keyword arguments
|
||||
* [x] Variable length arguments
|
||||
* [x] Array literal
|
||||
* [x] List literal
|
||||
* [x] Record literal
|
||||
* [x] Set literal
|
||||
* [x] Dict literal
|
||||
|
@ -58,11 +58,11 @@
|
|||
* [ ] Patch definition
|
||||
* [ ] Glue Patch definition
|
||||
* [x] Range object
|
||||
* [ ] Decorator
|
||||
* [x] Decorator
|
||||
* [ ] Comprehension
|
||||
* [ ] Array
|
||||
* [ ] Dict
|
||||
* [ ] Set
|
||||
* [x] List
|
||||
* [x] Dict
|
||||
* [x] Set
|
||||
* [ ] Tuple
|
||||
* [x] Pipeline operator
|
||||
* [ ] ? operator
|
||||
|
@ -91,7 +91,7 @@
|
|||
* [x] `sys` (partially)
|
||||
* [x] `time` (partially)
|
||||
* [x] Load User Module
|
||||
* [ ] Recursive module
|
||||
* [x] Recursive module
|
||||
* [x] Visibility check
|
||||
* [x] Patching
|
||||
* [ ] Implement a side-effect checker
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::str::FromStr;
|
|||
use erg_compiler::artifact::BuildRunnable;
|
||||
use erg_compiler::erg_parser::parse::Parsable;
|
||||
|
||||
use erg_compiler::hir::{Accessor, Array, Def, Dict, Expr, KeyValue, Set, Tuple};
|
||||
use erg_compiler::hir::{Accessor, Def, Dict, Expr, KeyValue, List, Set, Tuple};
|
||||
use erg_compiler::varinfo::{AbsLocation, VarInfo};
|
||||
use lsp_types::{
|
||||
CallHierarchyIncomingCall, CallHierarchyIncomingCallsParams, CallHierarchyItem,
|
||||
|
@ -145,8 +145,8 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
calls
|
||||
}
|
||||
Expr::UnaryOp(unop) => self.gen_outgoing_call(&unop.expr),
|
||||
Expr::Array(Array::Normal(arr)) => {
|
||||
for arg in arr.elems.pos_args.iter() {
|
||||
Expr::List(List::Normal(lis)) => {
|
||||
for arg in lis.elems.pos_args.iter() {
|
||||
calls.extend(self.gen_outgoing_call(&arg.expr));
|
||||
}
|
||||
calls
|
||||
|
|
|
@ -142,7 +142,7 @@ impl<'a> HIRVisitor<'a> {
|
|||
| Expr::Accessor(_)
|
||||
| Expr::BinOp(_)
|
||||
| Expr::UnaryOp(_)
|
||||
| Expr::Array(_)
|
||||
| Expr::List(_)
|
||||
| Expr::Dict(_)
|
||||
| Expr::Set(_)
|
||||
| Expr::Tuple(_)
|
||||
|
@ -275,7 +275,7 @@ impl<'a> HIRVisitor<'a> {
|
|||
Expr::Def(def) => self.get_expr_from_def(expr, def, pos),
|
||||
Expr::PatchDef(patch_def) => self.get_expr_from_patch_def(expr, patch_def, pos),
|
||||
Expr::Lambda(lambda) => self.get_expr_from_lambda(expr, lambda, pos),
|
||||
Expr::Array(arr) => self.get_expr_from_array(expr, arr, pos),
|
||||
Expr::List(lis) => self.get_expr_from_list(expr, lis, pos),
|
||||
Expr::Dict(dict) => self.get_expr_from_dict(expr, dict, pos),
|
||||
Expr::Record(record) => self.get_expr_from_record(expr, record, pos),
|
||||
Expr::Set(set) => self.get_expr_from_set(expr, set, pos),
|
||||
|
@ -440,18 +440,18 @@ impl<'a> HIRVisitor<'a> {
|
|||
self.get_expr_from_block(lambda.body.iter(), pos)
|
||||
}
|
||||
|
||||
fn get_expr_from_array<'e>(
|
||||
fn get_expr_from_list<'e>(
|
||||
&'e self,
|
||||
expr: &'e Expr,
|
||||
arr: &'e Array,
|
||||
lis: &'e List,
|
||||
pos: Position,
|
||||
) -> Option<&Expr> {
|
||||
if arr.ln_end() == pos.ln_end() && self.search.matches(expr) {
|
||||
if lis.ln_end() == pos.ln_end() && self.search.matches(expr) {
|
||||
// arr: `[1, 2]`, pos: `]`
|
||||
return Some(expr);
|
||||
}
|
||||
match arr {
|
||||
Array::Normal(arr) => self.get_expr_from_args(&arr.elems, pos),
|
||||
match lis {
|
||||
List::Normal(lis) => self.get_expr_from_args(&lis.elems, pos),
|
||||
_ => None, // todo!(),
|
||||
}
|
||||
}
|
||||
|
@ -587,7 +587,7 @@ impl<'a> HIRVisitor<'a> {
|
|||
Expr::PatchDef(patch_def) => self.get_patch_def_info(patch_def, token),
|
||||
Expr::Def(def) => self.get_def_info(def, token),
|
||||
Expr::Lambda(lambda) => self.get_lambda_info(lambda, token),
|
||||
Expr::Array(arr) => self.get_array_info(arr, token),
|
||||
Expr::List(lis) => self.get_list_info(lis, token),
|
||||
Expr::Dict(dict) => self.get_dict_info(dict, token),
|
||||
Expr::Record(record) => self.get_record_info(record, token),
|
||||
Expr::Set(set) => self.get_set_info(set, token),
|
||||
|
@ -764,9 +764,9 @@ impl<'a> HIRVisitor<'a> {
|
|||
.or_else(|| self.get_block_info(lambda.body.iter(), token))
|
||||
}
|
||||
|
||||
fn get_array_info(&self, arr: &Array, token: &Token) -> Option<VarInfo> {
|
||||
match arr {
|
||||
Array::Normal(arr) => self.get_args_info(&arr.elems, token),
|
||||
fn get_list_info(&self, lis: &List, token: &Token) -> Option<VarInfo> {
|
||||
match lis {
|
||||
List::Normal(lis) => self.get_args_info(&lis.elems, token),
|
||||
_ => None, // todo!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,12 +272,12 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
lsp_log!("failed to get packages: {}", artifact.ast);
|
||||
return cfg;
|
||||
};
|
||||
let Some(ast::Expr::Array(ast::Array::Normal(arr))) = pkgs.body.block.first() else {
|
||||
let Some(ast::Expr::List(ast::List::Normal(lis))) = pkgs.body.block.first() else {
|
||||
lsp_log!("packages must be an array: {pkgs}");
|
||||
return cfg;
|
||||
};
|
||||
let mut packages = vec![];
|
||||
for rec in arr.iter() {
|
||||
for rec in lis.iter() {
|
||||
let ast::Expr::Record(rec) = rec else {
|
||||
lsp_log!("packages must be records: {rec}");
|
||||
break;
|
||||
|
|
|
@ -35,11 +35,11 @@ use erg_parser::token::{Token, TokenKind};
|
|||
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||
use crate::context::ControlKind;
|
||||
use crate::error::CompileError;
|
||||
use crate::hir::ArrayWithLength;
|
||||
use crate::hir::DefaultParamSignature;
|
||||
use crate::hir::ListWithLength;
|
||||
use crate::hir::{
|
||||
Accessor, Args, Array, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, GuardClause,
|
||||
Identifier, Lambda, Literal, NonDefaultParamSignature, Params, PatchDef, PosArg, ReDef, Record,
|
||||
Accessor, Args, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, GuardClause, Identifier,
|
||||
Lambda, List, Literal, NonDefaultParamSignature, Params, PatchDef, PosArg, ReDef, Record,
|
||||
Signature, SubrSignature, Tuple, UnaryOp, VarSignature, HIR,
|
||||
};
|
||||
use crate::ty::codeobj::{CodeObj, CodeObjFlags, MakeFunctionFlags};
|
||||
|
@ -3031,20 +3031,20 @@ impl PyCodeGenerator {
|
|||
}
|
||||
|
||||
// TODO: list comprehension
|
||||
fn emit_array(&mut self, array: Array) {
|
||||
fn emit_list(&mut self, list: List) {
|
||||
let init_stack_len = self.stack_len();
|
||||
if !self.cfg.no_std {
|
||||
self.emit_push_null();
|
||||
if array.is_unsized() {
|
||||
self.emit_load_name_instr(Identifier::static_public("UnsizedArray"));
|
||||
if list.is_unsized() {
|
||||
self.emit_load_name_instr(Identifier::static_public("UnsizedList"));
|
||||
} else {
|
||||
self.emit_load_name_instr(Identifier::static_public("Array"));
|
||||
self.emit_load_name_instr(Identifier::static_public("List"));
|
||||
}
|
||||
}
|
||||
match array {
|
||||
Array::Normal(mut arr) => {
|
||||
let len = arr.elems.len();
|
||||
while let Some(arg) = arr.elems.try_remove_pos(0) {
|
||||
match list {
|
||||
List::Normal(mut lis) => {
|
||||
let len = lis.elems.len();
|
||||
while let Some(arg) = lis.elems.try_remove_pos(0) {
|
||||
self.emit_expr(arg.expr);
|
||||
}
|
||||
self.write_instr(BUILD_LIST);
|
||||
|
@ -3055,7 +3055,7 @@ impl PyCodeGenerator {
|
|||
self.stack_dec_n(len - 1);
|
||||
}
|
||||
}
|
||||
Array::WithLength(ArrayWithLength {
|
||||
List::WithLength(ListWithLength {
|
||||
elem,
|
||||
len: Some(len),
|
||||
..
|
||||
|
@ -3066,10 +3066,10 @@ impl PyCodeGenerator {
|
|||
self.emit_call_instr(1, Name);
|
||||
self.stack_dec();
|
||||
self.emit_expr(*len);
|
||||
self.emit_binop_instr(Token::dummy(TokenKind::Star, "*"), TypePair::ArrayNat);
|
||||
self.emit_binop_instr(Token::dummy(TokenKind::Star, "*"), TypePair::ListNat);
|
||||
return;
|
||||
}
|
||||
Array::WithLength(ArrayWithLength {
|
||||
List::WithLength(ListWithLength {
|
||||
elem, len: None, ..
|
||||
}) => {
|
||||
self.emit_expr(*elem);
|
||||
|
@ -3331,7 +3331,7 @@ impl PyCodeGenerator {
|
|||
Expr::UnaryOp(unary) => self.emit_unaryop(unary),
|
||||
Expr::BinOp(bin) => self.emit_binop(bin),
|
||||
Expr::Call(call) => self.emit_call(call),
|
||||
Expr::Array(arr) => self.emit_array(arr),
|
||||
Expr::List(lis) => self.emit_list(lis),
|
||||
Expr::Tuple(tup) => self.emit_tuple(tup),
|
||||
Expr::Set(set) => self.emit_set(set),
|
||||
Expr::Dict(dict) => self.emit_dict(dict),
|
||||
|
@ -3355,7 +3355,7 @@ impl PyCodeGenerator {
|
|||
self.emit_load_name_instr(Identifier::public(&v.qual_name()));
|
||||
}
|
||||
other => match &other.qual_name()[..] {
|
||||
t @ ("Bytes" | "Array" | "Dict" | "Set") => {
|
||||
t @ ("Bytes" | "List" | "Dict" | "Set") => {
|
||||
self.emit_push_null();
|
||||
self.emit_load_name_instr(Identifier::public(t));
|
||||
}
|
||||
|
@ -3378,7 +3378,7 @@ impl PyCodeGenerator {
|
|||
Expr::UnaryOp(unary) => self.emit_unaryop(unary),
|
||||
Expr::BinOp(bin) => self.emit_binop(bin),
|
||||
Expr::Call(call) => self.emit_call(call),
|
||||
Expr::Array(arr) => self.emit_array(arr),
|
||||
Expr::List(lis) => self.emit_list(lis),
|
||||
Expr::Tuple(tup) => self.emit_tuple(tup),
|
||||
Expr::Set(set) => self.emit_set(set),
|
||||
Expr::Dict(dict) => self.emit_dict(dict),
|
||||
|
|
|
@ -192,7 +192,7 @@ impl Context {
|
|||
..
|
||||
}),
|
||||
) if &n[..] == "GenericProc" => (Absolutely, true),
|
||||
(Mono(l), Poly { name: r, .. }) if &l[..] == "GenericArray" && &r[..] == "Array" => {
|
||||
(Mono(l), Poly { name: r, .. }) if &l[..] == "GenericList" && &r[..] == "List" => {
|
||||
(Absolutely, true)
|
||||
}
|
||||
(Mono(l), Poly { name: r, .. }) if &l[..] == "GenericDict" && &r[..] == "Dict" => {
|
||||
|
@ -494,8 +494,8 @@ impl Context {
|
|||
} else if let Some(lfvt) = lfv.get_type() {
|
||||
// e.g. lfv: ?L(: Int) is unreachable
|
||||
// but
|
||||
// ?L(: Array(Type, 3)) :> Array(Int, 3)
|
||||
// => Array(Type, 3) :> Array(Typeof(Int), 3)
|
||||
// ?L(: List(Type, 3)) :> List(Int, 3)
|
||||
// => List(Type, 3) :> List(Typeof(Int), 3)
|
||||
// => true
|
||||
let rhs_meta = self.meta_type(rhs);
|
||||
self.supertype_of(&lfvt, &rhs_meta)
|
||||
|
@ -568,7 +568,7 @@ impl Context {
|
|||
self.convert_tp_into_value(params[0].clone()).is_ok()
|
||||
}
|
||||
(ty @ (Type | ClassType | TraitType), Poly { name, params })
|
||||
if &name[..] == "Array" || &name[..] == "UnsizedArray" || &name[..] == "Set" =>
|
||||
if &name[..] == "List" || &name[..] == "UnsizedList" || &name[..] == "Set" =>
|
||||
{
|
||||
let Ok(elem_t) = self.convert_tp_into_type(params[0].clone()) else {
|
||||
return false;
|
||||
|
@ -666,8 +666,8 @@ impl Context {
|
|||
// Int :> {I: Str| ...} == false
|
||||
// Bool :> {1} == true
|
||||
// Bool :> {2} == false
|
||||
// [2, 3]: {A: Array(Nat) | A.prod() == 6}
|
||||
// Array({1, 2}, _) :> {[3, 4]} == false
|
||||
// [2, 3]: {A: List(Nat) | A.prod() == 6}
|
||||
// List({1, 2}, _) :> {[3, 4]} == false
|
||||
(l, Refinement(r)) => {
|
||||
// Type / {S: Set(Str) | S == {"a", "b"}}
|
||||
// TODO: GeneralEq
|
||||
|
@ -698,7 +698,7 @@ impl Context {
|
|||
// {N: Nat | ...} :> Int) == false
|
||||
// ({I: Int | I >= 0} :> Int) == false
|
||||
// {U(: Type)} :> { .x = {Int} }(== {{ .x = Int }}) == true
|
||||
// {[1]} == Array({1}, 1) :> Array({1}, _) == true
|
||||
// {[1]} == List({1}, 1) :> List({1}, _) == true
|
||||
(Refinement(l), r) => {
|
||||
if let Some(r) = r.to_singleton() {
|
||||
return self.structural_supertype_of(lhs, &Type::Refinement(r));
|
||||
|
@ -804,7 +804,7 @@ impl Context {
|
|||
return false;
|
||||
}
|
||||
// [Int; 2] :> [Int; 3]
|
||||
if &ln[..] == "Array" || &ln[..] == "Set" {
|
||||
if &ln[..] == "List" || &ln[..] == "Set" {
|
||||
let Ok(lt) = self.convert_tp_into_type(lparams[0].clone()) else {
|
||||
return false;
|
||||
};
|
||||
|
@ -941,7 +941,7 @@ impl Context {
|
|||
self.supertype_of(&self.get_tp_t(sup_p).unwrap_or(Obj), t)
|
||||
}
|
||||
},
|
||||
(TyParam::Array(sup), TyParam::Array(sub))
|
||||
(TyParam::List(sup), TyParam::List(sub))
|
||||
| (TyParam::Tuple(sup), TyParam::Tuple(sub)) => {
|
||||
if sup.len() > sub.len() || (variance.is_invariant() && sup.len() != sub.len()) {
|
||||
return false;
|
||||
|
@ -991,7 +991,7 @@ impl Context {
|
|||
}
|
||||
true
|
||||
}
|
||||
(TyParam::UnsizedArray(sup), TyParam::UnsizedArray(sub)) => {
|
||||
(TyParam::UnsizedList(sup), TyParam::UnsizedList(sub)) => {
|
||||
self.supertype_of_tp(sup, sub, variance)
|
||||
}
|
||||
(TyParam::Type(sup), TyParam::Type(sub)) => match variance {
|
||||
|
@ -1308,8 +1308,8 @@ impl Context {
|
|||
/// union(Nat, Int) == Int
|
||||
/// union(Int, Str) == Int or Str
|
||||
/// union(?T(<: Str), ?U(<: Int)) == ?T or ?U
|
||||
/// union(Array(Int, 2), Array(Str, 2)) == Array(Int or Str, 2)
|
||||
/// union(Array(Int, 2), Array(Str, 3)) == Array(Int, 2) or Array(Int, 3)
|
||||
/// union(List(Int, 2), List(Str, 2)) == List(Int or Str, 2)
|
||||
/// union(List(Int, 2), List(Str, 3)) == List(Int, 2) or List(Int, 3)
|
||||
/// union({ .a = Int }, { .a = Str }) == { .a = Int or Str }
|
||||
/// union({ .a = Int }, { .a = Int; .b = Int }) == { .a = Int } or { .a = Int; .b = Int } # not to lost `b` information
|
||||
/// union((A and B) or C) == (A or C) and (B or C)
|
||||
|
@ -1387,7 +1387,7 @@ impl Context {
|
|||
t
|
||||
}
|
||||
(t, Type::Never) | (Type::Never, t) => t.clone(),
|
||||
// Array({1, 2}, 2), Array({3, 4}, 2) ==> Array({1, 2, 3, 4}, 2)
|
||||
// List({1, 2}, 2), List({3, 4}, 2) ==> List({1, 2, 3, 4}, 2)
|
||||
(
|
||||
Type::Poly {
|
||||
name: ln,
|
||||
|
@ -1430,7 +1430,7 @@ impl Context {
|
|||
Some(TyParam::t(self.union(l, r.typ())))
|
||||
}
|
||||
(TyParam::Type(l), TyParam::Type(r)) => Some(TyParam::t(self.union(l, r))),
|
||||
(TyParam::Array(l), TyParam::Array(r)) => {
|
||||
(TyParam::List(l), TyParam::List(r)) => {
|
||||
let mut tps = vec![];
|
||||
for (l, r) in l.iter().zip(r.iter()) {
|
||||
if let Some(tp) = self.union_tp(l, r) {
|
||||
|
@ -1439,7 +1439,7 @@ impl Context {
|
|||
return None;
|
||||
}
|
||||
}
|
||||
Some(TyParam::Array(tps))
|
||||
Some(TyParam::List(tps))
|
||||
}
|
||||
(fv @ TyParam::FreeVar(f), other) | (other, fv @ TyParam::FreeVar(f))
|
||||
if f.is_unbound() =>
|
||||
|
@ -2195,7 +2195,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
/// {[]} == {A: Array(Never, _) | A == []} => Array(Never, 0)
|
||||
/// {[]} == {A: List(Never, _) | A == []} => List(Never, 0)
|
||||
pub(crate) fn refinement_to_poly(&self, refine: &RefinementType) -> Option<Type> {
|
||||
if refine.t.is_monomorphic() {
|
||||
return None;
|
||||
|
@ -2207,7 +2207,7 @@ impl Context {
|
|||
return None;
|
||||
}
|
||||
match &refine.t.qual_name()[..] {
|
||||
"Array" => self.get_tp_t(rhs).ok().map(|t| t.derefine()),
|
||||
"List" => self.get_tp_t(rhs).ok().map(|t| t.derefine()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ use erg_parser::desugar::Desugarer;
|
|||
use erg_parser::token::{Token, TokenKind};
|
||||
|
||||
use crate::ty::constructors::{
|
||||
array_t, bounded, closed_range, dict_t, func, guard, mono, mono_q, named_free_var, poly, proj,
|
||||
bounded, closed_range, dict_t, func, guard, list_t, mono, mono_q, named_free_var, poly, proj,
|
||||
proj_call, ref_, ref_mut, refinement, set_t, subr_t, subtypeof, tp_enum, try_v_enum, tuple_t,
|
||||
unknown_len_array_t, v_enum,
|
||||
unknown_len_list_t, v_enum,
|
||||
};
|
||||
use crate::ty::free::HasLevel;
|
||||
use crate::ty::typaram::{OpKind, TyParam};
|
||||
|
@ -154,13 +154,13 @@ impl<'c> Substituter<'c> {
|
|||
|
||||
/// e.g.
|
||||
/// ```erg
|
||||
/// qt: Array(T, N), st: Array(Int, 3)
|
||||
/// qt: List(T, N), st: List(Int, 3)
|
||||
/// qt: T or NoneType, st: NoneType or Int (T == Int)
|
||||
/// ```
|
||||
/// invalid (no effect):
|
||||
/// ```erg
|
||||
/// qt: Iterable(T), st: Array(Int, 3)
|
||||
/// qt: Array(T, N), st: Array!(Int, 3) # TODO
|
||||
/// qt: Iterable(T), st: List(Int, 3)
|
||||
/// qt: List(T, N), st: List!(Int, 3) # TODO
|
||||
/// ```
|
||||
pub(crate) fn substitute_typarams(
|
||||
ctx: &'c Context,
|
||||
|
@ -282,9 +282,9 @@ impl<'c> Substituter<'c> {
|
|||
if !qt.is_undoable_linked_var() && qt.is_generalized() && qt.is_free_var() {
|
||||
qt.undoable_link(&st, &self.undoable_linked);
|
||||
} else if qt.is_undoable_linked_var() && qt != st {
|
||||
// e.g. Array(T, N) <: Add(Array(T, M))
|
||||
// Array((Int), (3)) <: Add(Array((Int), (4))): OK
|
||||
// Array((Int), (3)) <: Add(Array((Str), (4))): NG
|
||||
// e.g. List(T, N) <: Add(List(T, M))
|
||||
// List((Int), (3)) <: Add(List((Int), (4))): OK
|
||||
// List((Int), (3)) <: Add(List((Str), (4))): NG
|
||||
if let Some(union) = self.ctx.unify(&qt, &st) {
|
||||
qt.undoable_link(&union, &self.undoable_linked);
|
||||
} else {
|
||||
|
@ -331,7 +331,7 @@ impl<'c> Substituter<'c> {
|
|||
}
|
||||
// NOTE: Rarely, double overwriting occurs.
|
||||
// Whether this could be a problem is under consideration.
|
||||
// e.g. `T` of Array(T, N) <: Add(T, M)
|
||||
// e.g. `T` of List(T, N) <: Add(T, M)
|
||||
TyParam::FreeVar(ref fv) if fv.is_generalized() => {
|
||||
qtp.undoable_link(&stp, &self.undoable_linked);
|
||||
/*if let Err(errs) = self.sub_unify_tp(&stp, &qtp, None, &(), false) {
|
||||
|
@ -785,23 +785,23 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn eval_const_normal_array(&self, arr: &NormalArray) -> EvalResult<ValueObj> {
|
||||
pub(crate) fn eval_const_normal_list(&self, lis: &NormalList) -> EvalResult<ValueObj> {
|
||||
let mut elems = vec![];
|
||||
for elem in arr.elems.pos_args().iter() {
|
||||
for elem in lis.elems.pos_args().iter() {
|
||||
let elem = self.eval_const_expr(&elem.expr)?;
|
||||
elems.push(elem);
|
||||
}
|
||||
Ok(ValueObj::Array(ArcArray::from(elems)))
|
||||
Ok(ValueObj::List(ArcArray::from(elems)))
|
||||
}
|
||||
|
||||
fn eval_const_array(&self, arr: &Array) -> EvalResult<ValueObj> {
|
||||
match arr {
|
||||
Array::Normal(arr) => self.eval_const_normal_array(arr),
|
||||
Array::WithLength(arr) => {
|
||||
let elem = self.eval_const_expr(&arr.elem.expr)?;
|
||||
match arr.len.as_ref() {
|
||||
fn eval_const_list(&self, lis: &List) -> EvalResult<ValueObj> {
|
||||
match lis {
|
||||
List::Normal(lis) => self.eval_const_normal_list(lis),
|
||||
List::WithLength(lis) => {
|
||||
let elem = self.eval_const_expr(&lis.elem.expr)?;
|
||||
match lis.len.as_ref() {
|
||||
Expr::Accessor(Accessor::Ident(ident)) if ident.is_discarded() => {
|
||||
Ok(ValueObj::UnsizedArray(Box::new(elem)))
|
||||
Ok(ValueObj::UnsizedList(Box::new(elem)))
|
||||
}
|
||||
other => {
|
||||
let len = self.eval_const_expr(other)?;
|
||||
|
@ -820,14 +820,14 @@ impl Context {
|
|||
)
|
||||
})?;
|
||||
let arr = vec![elem; len];
|
||||
Ok(ValueObj::Array(ArcArray::from(arr)))
|
||||
Ok(ValueObj::List(ArcArray::from(arr)))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => Err(EvalErrors::from(EvalError::not_const_expr(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
arr.loc(),
|
||||
lis.loc(),
|
||||
self.caused_by(),
|
||||
))),
|
||||
}
|
||||
|
@ -836,8 +836,8 @@ impl Context {
|
|||
fn eval_const_set(&self, set: &AstSet) -> EvalResult<ValueObj> {
|
||||
let mut elems = vec![];
|
||||
match set {
|
||||
AstSet::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args().iter() {
|
||||
AstSet::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args().iter() {
|
||||
let elem = self.eval_const_expr(&elem.expr)?;
|
||||
elems.push(elem);
|
||||
}
|
||||
|
@ -875,8 +875,8 @@ impl Context {
|
|||
fn eval_const_tuple(&self, tuple: &Tuple) -> EvalResult<ValueObj> {
|
||||
let mut elems = vec![];
|
||||
match tuple {
|
||||
Tuple::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args().iter() {
|
||||
Tuple::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args().iter() {
|
||||
let elem = self.eval_const_expr(&elem.expr)?;
|
||||
elems.push(elem);
|
||||
}
|
||||
|
@ -1109,7 +1109,7 @@ impl Context {
|
|||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||
Expr::Call(call) => self.eval_const_call(call),
|
||||
Expr::Array(arr) => self.eval_const_array(arr),
|
||||
Expr::List(lis) => self.eval_const_list(lis),
|
||||
Expr::Set(set) => self.eval_const_set(set),
|
||||
Expr::Dict(dict) => self.eval_const_dict(dict),
|
||||
Expr::Tuple(tuple) => self.eval_const_tuple(tuple),
|
||||
|
@ -1139,7 +1139,7 @@ impl Context {
|
|||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||
Expr::Call(call) => self.eval_const_call(call),
|
||||
Expr::Array(arr) => self.eval_const_array(arr),
|
||||
Expr::List(lis) => self.eval_const_list(lis),
|
||||
Expr::Set(set) => self.eval_const_set(set),
|
||||
Expr::Dict(dict) => self.eval_const_dict(dict),
|
||||
Expr::Tuple(tuple) => self.eval_const_tuple(tuple),
|
||||
|
@ -1412,8 +1412,8 @@ impl Context {
|
|||
(TyParam::Dict(l), TyParam::Dict(r)) if op == OpKind::Add => {
|
||||
Ok(TyParam::Dict(l.concat(r)))
|
||||
}
|
||||
(TyParam::Array(l), TyParam::Array(r)) if op == OpKind::Add => {
|
||||
Ok(TyParam::Array([l, r].concat()))
|
||||
(TyParam::List(l), TyParam::List(r)) if op == OpKind::Add => {
|
||||
Ok(TyParam::List([l, r].concat()))
|
||||
}
|
||||
(TyParam::FreeVar(fv), r) if fv.is_linked() => {
|
||||
let t = fv.crack().clone();
|
||||
|
@ -1563,16 +1563,16 @@ impl Context {
|
|||
TyParam::App { name, args } => self.eval_app(name, args),
|
||||
TyParam::BinOp { op, lhs, rhs } => self.eval_bin_tp(op, *lhs, *rhs),
|
||||
TyParam::UnaryOp { op, val } => self.eval_unary_tp(op, *val),
|
||||
TyParam::Array(tps) => {
|
||||
TyParam::List(tps) => {
|
||||
let mut new_tps = Vec::with_capacity(tps.len());
|
||||
for tp in tps {
|
||||
new_tps.push(self.eval_tp(tp)?);
|
||||
}
|
||||
Ok(TyParam::Array(new_tps))
|
||||
Ok(TyParam::List(new_tps))
|
||||
}
|
||||
TyParam::UnsizedArray(elem) => {
|
||||
TyParam::UnsizedList(elem) => {
|
||||
let elem = self.eval_tp(*elem)?;
|
||||
Ok(TyParam::UnsizedArray(Box::new(elem)))
|
||||
Ok(TyParam::UnsizedList(Box::new(elem)))
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
let mut new_tps = Vec::with_capacity(tps.len());
|
||||
|
@ -2055,17 +2055,17 @@ impl Context {
|
|||
}
|
||||
Ok(tuple_t(ts))
|
||||
}
|
||||
TyParam::Array(tps) => {
|
||||
TyParam::List(tps) => {
|
||||
let mut union = Type::Never;
|
||||
let len = tps.len();
|
||||
for tp in tps {
|
||||
union = self.union(&union, &self.convert_tp_into_type(tp)?);
|
||||
}
|
||||
Ok(array_t(union, TyParam::value(len)))
|
||||
Ok(list_t(union, TyParam::value(len)))
|
||||
}
|
||||
TyParam::UnsizedArray(elem) => {
|
||||
TyParam::UnsizedList(elem) => {
|
||||
let elem = self.convert_tp_into_type(*elem)?;
|
||||
Ok(unknown_len_array_t(elem))
|
||||
Ok(unknown_len_list_t(elem))
|
||||
}
|
||||
TyParam::Set(tps) => {
|
||||
let mut union = Type::Never;
|
||||
|
@ -2095,7 +2095,7 @@ impl Context {
|
|||
let t = fv.crack().clone();
|
||||
self.convert_tp_into_type(t)
|
||||
}
|
||||
// TyParam(Ts: Array(Type)) -> Type(Ts: Array(Type))
|
||||
// TyParam(Ts: List(Type)) -> Type(Ts: List(Type))
|
||||
// TyParam(?S(: Str)) -> Err(...),
|
||||
// TyParam(?D(: GenericDict)) -> Ok(?D(: GenericDict)),
|
||||
// FIXME: GenericDict
|
||||
|
@ -2136,17 +2136,17 @@ impl Context {
|
|||
self.convert_tp_into_value(tp)
|
||||
}
|
||||
TyParam::Value(v) => Ok(v),
|
||||
TyParam::Array(arr) => {
|
||||
TyParam::List(lis) => {
|
||||
let mut new = vec![];
|
||||
for elem in arr {
|
||||
for elem in lis {
|
||||
let elem = self.convert_tp_into_value(elem)?;
|
||||
new.push(elem);
|
||||
}
|
||||
Ok(ValueObj::Array(new.into()))
|
||||
Ok(ValueObj::List(new.into()))
|
||||
}
|
||||
TyParam::UnsizedArray(elem) => {
|
||||
TyParam::UnsizedList(elem) => {
|
||||
let elem = self.convert_tp_into_value(*elem)?;
|
||||
Ok(ValueObj::UnsizedArray(Box::new(elem)))
|
||||
Ok(ValueObj::UnsizedList(Box::new(elem)))
|
||||
}
|
||||
TyParam::Tuple(tys) => {
|
||||
let mut new = vec![];
|
||||
|
@ -2244,17 +2244,17 @@ impl Context {
|
|||
}
|
||||
Ok(tuple_t(new_ts))
|
||||
}
|
||||
ValueObj::Array(arr) => {
|
||||
let len = TyParam::value(arr.len());
|
||||
ValueObj::List(lis) => {
|
||||
let len = TyParam::value(lis.len());
|
||||
let mut union = Type::Never;
|
||||
for v in arr.iter().cloned() {
|
||||
for v in lis.iter().cloned() {
|
||||
union = self.union(&union, &self.convert_value_into_type(v)?);
|
||||
}
|
||||
Ok(array_t(union, len))
|
||||
Ok(list_t(union, len))
|
||||
}
|
||||
ValueObj::UnsizedArray(elem) => {
|
||||
ValueObj::UnsizedList(elem) => {
|
||||
let elem = self.convert_value_into_type(*elem)?;
|
||||
Ok(unknown_len_array_t(elem))
|
||||
Ok(unknown_len_list_t(elem))
|
||||
}
|
||||
ValueObj::Set(set) => try_v_enum(set).map_err(ValueObj::Set),
|
||||
ValueObj::Dict(dic) => {
|
||||
|
@ -2279,23 +2279,23 @@ impl Context {
|
|||
pub(crate) fn convert_value_into_tp(value: ValueObj) -> Result<TyParam, TyParam> {
|
||||
match value {
|
||||
ValueObj::Type(t) => Ok(TyParam::t(t.into_typ())),
|
||||
ValueObj::Array(arr) => {
|
||||
let mut new_arr = vec![];
|
||||
for v in arr.iter().cloned() {
|
||||
ValueObj::List(lis) => {
|
||||
let mut new_lis = vec![];
|
||||
for v in lis.iter().cloned() {
|
||||
let tp = match Self::convert_value_into_tp(v) {
|
||||
Ok(tp) => tp,
|
||||
Err(tp) => tp,
|
||||
};
|
||||
new_arr.push(tp);
|
||||
new_lis.push(tp);
|
||||
}
|
||||
Ok(TyParam::Array(new_arr))
|
||||
Ok(TyParam::List(new_lis))
|
||||
}
|
||||
ValueObj::UnsizedArray(elem) => {
|
||||
ValueObj::UnsizedList(elem) => {
|
||||
let tp = match Self::convert_value_into_tp(*elem) {
|
||||
Ok(tp) => tp,
|
||||
Err(tp) => tp,
|
||||
};
|
||||
Ok(TyParam::UnsizedArray(Box::new(tp)))
|
||||
Ok(TyParam::UnsizedList(Box::new(tp)))
|
||||
}
|
||||
ValueObj::Tuple(vs) => {
|
||||
let mut new_ts = vec![];
|
||||
|
@ -2404,14 +2404,14 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn convert_type_to_array(&self, ty: Type) -> Result<Vec<ValueObj>, Type> {
|
||||
pub(crate) fn convert_type_to_list(&self, ty: Type) -> Result<Vec<ValueObj>, Type> {
|
||||
match ty {
|
||||
Type::FreeVar(fv) if fv.is_linked() => {
|
||||
let t = fv.crack().clone();
|
||||
self.convert_type_to_array(t)
|
||||
self.convert_type_to_list(t)
|
||||
}
|
||||
Type::Refinement(refine) => self.convert_type_to_array(*refine.t),
|
||||
Type::Poly { name, params } if &name[..] == "Array" || &name[..] == "Array!" => {
|
||||
Type::Refinement(refine) => self.convert_type_to_list(*refine.t),
|
||||
Type::Poly { name, params } if &name[..] == "List" || &name[..] == "List!" => {
|
||||
let Ok(t) = self.convert_tp_into_type(params[0].clone()) else {
|
||||
log!(err "cannot convert to type: {}", params[0]);
|
||||
return Err(poly(name, params));
|
||||
|
@ -2429,14 +2429,11 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn convert_value_into_array(
|
||||
&self,
|
||||
val: ValueObj,
|
||||
) -> Result<Vec<ValueObj>, ValueObj> {
|
||||
pub(crate) fn convert_value_into_list(&self, val: ValueObj) -> Result<Vec<ValueObj>, ValueObj> {
|
||||
match val {
|
||||
ValueObj::Array(arr) => Ok(arr.to_vec()),
|
||||
ValueObj::List(lis) => Ok(lis.to_vec()),
|
||||
ValueObj::Type(t) => self
|
||||
.convert_type_to_array(t.into_typ())
|
||||
.convert_type_to_list(t.into_typ())
|
||||
.map_err(ValueObj::builtin_type),
|
||||
_ => Err(val),
|
||||
}
|
||||
|
@ -2972,13 +2969,13 @@ impl Context {
|
|||
line!(),
|
||||
))
|
||||
}),
|
||||
TyParam::Array(tps) => {
|
||||
TyParam::List(tps) => {
|
||||
let tp_t = if let Some(fst) = tps.first() {
|
||||
self.get_tp_t(fst)?
|
||||
} else {
|
||||
Never
|
||||
};
|
||||
let t = array_t(tp_t, TyParam::value(tps.len()));
|
||||
let t = list_t(tp_t, TyParam::value(tps.len()));
|
||||
Ok(t)
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
|
@ -3113,7 +3110,7 @@ impl Context {
|
|||
(TyParam::Type(l), TyParam::Type(r)) => l == r,
|
||||
(TyParam::Value(l), TyParam::Value(r)) => l == r,
|
||||
(TyParam::Erased(l), TyParam::Erased(r)) => l == r,
|
||||
(TyParam::Array(l), TyParam::Array(r)) => l == r,
|
||||
(TyParam::List(l), TyParam::List(r)) => l == r,
|
||||
(TyParam::Tuple(l), TyParam::Tuple(r)) => l == r,
|
||||
(TyParam::Set(l), TyParam::Set(r)) => l == r, // FIXME:
|
||||
(TyParam::Dict(l), TyParam::Dict(r)) => l == r,
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Generalizer {
|
|||
fv.generalize();
|
||||
TyParam::FreeVar(fv)
|
||||
}
|
||||
TyParam::Array(tps) => TyParam::Array(
|
||||
TyParam::List(tps) => TyParam::List(
|
||||
tps.into_iter()
|
||||
.map(|tp| self.generalize_tp(tp, uninit))
|
||||
.collect(),
|
||||
|
@ -496,12 +496,12 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
|
|||
val: Box::new(val),
|
||||
})
|
||||
}
|
||||
TyParam::Array(tps) => {
|
||||
TyParam::List(tps) => {
|
||||
let mut new_tps = vec![];
|
||||
for tp in tps {
|
||||
new_tps.push(self.deref_tp(tp)?);
|
||||
}
|
||||
Ok(TyParam::Array(new_tps))
|
||||
Ok(TyParam::List(new_tps))
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
let mut new_tps = vec![];
|
||||
|
@ -1374,24 +1374,24 @@ impl Context {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
hir::Expr::Array(array) => match array {
|
||||
hir::Array::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args.iter_mut() {
|
||||
hir::Expr::List(list) => match list {
|
||||
hir::List::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args.iter_mut() {
|
||||
self.resolve_expr_t(&mut elem.expr, qnames)?;
|
||||
}
|
||||
let t = mem::take(&mut arr.t);
|
||||
let mut dereferencer = Dereferencer::simple(self, qnames, arr);
|
||||
arr.t = dereferencer.deref_tyvar(t)?;
|
||||
let t = mem::take(&mut lis.t);
|
||||
let mut dereferencer = Dereferencer::simple(self, qnames, lis);
|
||||
lis.t = dereferencer.deref_tyvar(t)?;
|
||||
Ok(())
|
||||
}
|
||||
hir::Array::WithLength(arr) => {
|
||||
self.resolve_expr_t(&mut arr.elem, qnames)?;
|
||||
if let Some(len) = &mut arr.len {
|
||||
hir::List::WithLength(lis) => {
|
||||
self.resolve_expr_t(&mut lis.elem, qnames)?;
|
||||
if let Some(len) = &mut lis.len {
|
||||
self.resolve_expr_t(len, qnames)?;
|
||||
}
|
||||
let t = mem::take(&mut arr.t);
|
||||
let mut dereferencer = Dereferencer::simple(self, qnames, arr);
|
||||
arr.t = dereferencer.deref_tyvar(t)?;
|
||||
let t = mem::take(&mut lis.t);
|
||||
let mut dereferencer = Dereferencer::simple(self, qnames, lis);
|
||||
lis.t = dereferencer.deref_tyvar(t)?;
|
||||
Ok(())
|
||||
}
|
||||
other => feature_error!(
|
||||
|
|
|
@ -44,7 +44,7 @@ impl Context {
|
|||
expected: &Type,
|
||||
found: &Type,
|
||||
) -> Option<String> {
|
||||
if &callee_t.qual_name()[..] == "Array" && attr == Some("__getitem__") && nth == 1 {
|
||||
if &callee_t.qual_name()[..] == "List" && attr == Some("__getitem__") && nth == 1 {
|
||||
let len = &callee_t.typarams().get(1).cloned()?;
|
||||
let (_, _, pred) = found.clone().deconstruct_refinement().ok()?;
|
||||
if let Predicate::Equal { rhs: accessed, .. } = pred {
|
||||
|
@ -58,10 +58,10 @@ impl Context {
|
|||
accessed.clone()
|
||||
};
|
||||
return Some(switch_lang! {
|
||||
"japanese" => format!("配列の長さは{len}ですが、{accessed}番目の要素にアクセスしようとしています"),
|
||||
"japanese" => format!("リストの長さは{len}ですが、{accessed}番目の要素にアクセスしようとしています"),
|
||||
"simplified_chinese" => format!("数组长度为{len}但尝试访问第{accessed}个元素"),
|
||||
"traditional_chinese" => format!("陣列長度為{len}但嘗試訪問第{accessed}個元素"),
|
||||
"english" => format!("Array length is {len} but tried to access the {accessed}th element"),
|
||||
"english" => format!("List length is {len} but tried to access the {accessed}th element"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -489,7 +489,7 @@ impl Context {
|
|||
BYTES,
|
||||
or(
|
||||
mono(BYTES),
|
||||
array_t(Type::from(value(0)..=value(255)), TyParam::erased(Nat)),
|
||||
list_t(Type::from(value(0)..=value(255)), TyParam::erased(Nat)),
|
||||
),
|
||||
)],
|
||||
vec![kw(
|
||||
|
@ -954,7 +954,7 @@ impl Context {
|
|||
None,
|
||||
vec![kw(KW_MAXSPLIT, Nat)],
|
||||
None,
|
||||
unknown_len_array_t(Str),
|
||||
unknown_len_list_t(Str),
|
||||
),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
|
@ -968,7 +968,7 @@ impl Context {
|
|||
None,
|
||||
vec![kw(KW_KEEPENDS, Bool)],
|
||||
None,
|
||||
unknown_len_array_t(Str),
|
||||
unknown_len_list_t(Str),
|
||||
),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
|
@ -1356,14 +1356,14 @@ impl Context {
|
|||
type_.register_superclass(Obj, &obj);
|
||||
type_.register_builtin_erg_impl(
|
||||
FUNC_MRO,
|
||||
fn0_met(Type, array_t(Type, TyParam::erased(Nat))),
|
||||
fn0_met(Type, list_t(Type, TyParam::erased(Nat))),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
// TODO: PolyType
|
||||
type_.register_builtin_erg_impl(
|
||||
FUNDAMENTAL_ARGS,
|
||||
array_t(Type, TyParam::erased(Nat)),
|
||||
list_t(Type, TyParam::erased(Nat)),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
|
@ -1424,31 +1424,31 @@ impl Context {
|
|||
);
|
||||
code.register_builtin_erg_impl(
|
||||
FUNC_CO_VARNAMES,
|
||||
array_t(Str, TyParam::erased(Nat)),
|
||||
list_t(Str, TyParam::erased(Nat)),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
code.register_builtin_erg_impl(
|
||||
FUNC_CO_CONSTS,
|
||||
array_t(Obj, TyParam::erased(Nat)),
|
||||
list_t(Obj, TyParam::erased(Nat)),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
code.register_builtin_erg_impl(
|
||||
FUNC_CO_NAMES,
|
||||
array_t(Str, TyParam::erased(Nat)),
|
||||
list_t(Str, TyParam::erased(Nat)),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
code.register_builtin_erg_impl(
|
||||
FUNC_CO_FREEVARS,
|
||||
array_t(Str, TyParam::erased(Nat)),
|
||||
list_t(Str, TyParam::erased(Nat)),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
code.register_builtin_erg_impl(
|
||||
FUNC_CO_CELLVARS,
|
||||
array_t(Str, TyParam::erased(Nat)),
|
||||
list_t(Str, TyParam::erased(Nat)),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
|
@ -1566,100 +1566,100 @@ impl Context {
|
|||
if ERG_MODE {
|
||||
py_module.register_superclass(g_module_t.clone(), &generic_module);
|
||||
}
|
||||
/* GenericArray */
|
||||
let mut generic_array = Self::builtin_mono_class(GENERIC_ARRAY, 1);
|
||||
generic_array.register_superclass(Obj, &obj);
|
||||
/* GenericList */
|
||||
let mut generic_list = Self::builtin_mono_class(GENERIC_LIST, 1);
|
||||
generic_list.register_superclass(Obj, &obj);
|
||||
let mut arr_eq = Self::builtin_methods(Some(mono(EQ)), 2);
|
||||
arr_eq.register_builtin_erg_impl(
|
||||
OP_EQ,
|
||||
fn1_met(mono(GENERIC_ARRAY), mono(GENERIC_ARRAY), Bool),
|
||||
fn1_met(mono(GENERIC_LIST), mono(GENERIC_LIST), Bool),
|
||||
Const,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
generic_array.register_trait_methods(mono(GENERIC_ARRAY), arr_eq);
|
||||
generic_list.register_trait_methods(mono(GENERIC_LIST), arr_eq);
|
||||
let t_call = func1(
|
||||
poly(ITERABLE, vec![ty_tp(T.clone())]),
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
)
|
||||
.quantify();
|
||||
generic_array.register_builtin_erg_impl(
|
||||
generic_list.register_builtin_erg_impl(
|
||||
FUNDAMENTAL_CALL,
|
||||
t_call,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
let mut array_hash = Self::builtin_methods(Some(mono(HASH)), 1);
|
||||
array_hash.register_builtin_erg_impl(
|
||||
let mut list_hash = Self::builtin_methods(Some(mono(HASH)), 1);
|
||||
list_hash.register_builtin_erg_impl(
|
||||
OP_HASH,
|
||||
fn0_met(mono(GENERIC_ARRAY), Int),
|
||||
fn0_met(mono(GENERIC_LIST), Int),
|
||||
Const,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
generic_array.register_trait_methods(mono(GENERIC_ARRAY), array_hash);
|
||||
let unsized_array_t = poly(UNSIZED_ARRAY, vec![ty_tp(T.clone())]);
|
||||
let mut unsized_array =
|
||||
Self::builtin_poly_class(UNSIZED_ARRAY, vec![ParamSpec::t_nd(TY_T)], 1);
|
||||
unsized_array.register_superclass(Obj, &obj);
|
||||
unsized_array.register_builtin_decl(KW_ELEM, T.clone(), vis.clone(), Some(KW_ELEM));
|
||||
/* Array */
|
||||
let mut array_ =
|
||||
Self::builtin_poly_class(ARRAY, vec![PS::t_nd(TY_T), PS::default(TY_N, Nat)], 10);
|
||||
array_.register_superclass(mono(GENERIC_ARRAY), &generic_array);
|
||||
array_
|
||||
generic_list.register_trait_methods(mono(GENERIC_LIST), list_hash);
|
||||
let unsized_list_t = poly(UNSIZED_LIST, vec![ty_tp(T.clone())]);
|
||||
let mut unsized_list =
|
||||
Self::builtin_poly_class(UNSIZED_LIST, vec![ParamSpec::t_nd(TY_T)], 1);
|
||||
unsized_list.register_superclass(Obj, &obj);
|
||||
unsized_list.register_builtin_decl(KW_ELEM, T.clone(), vis.clone(), Some(KW_ELEM));
|
||||
/* List */
|
||||
let mut list_ =
|
||||
Self::builtin_poly_class(LIST, vec![PS::t_nd(TY_T), PS::default(TY_N, Nat)], 10);
|
||||
list_.register_superclass(mono(GENERIC_LIST), &generic_list);
|
||||
list_
|
||||
.register_trait(self, poly(OUTPUT, vec![ty_tp(T.clone())]))
|
||||
.unwrap();
|
||||
let arr_t = array_t(T.clone(), N.clone());
|
||||
let lis_t = list_t(T.clone(), N.clone());
|
||||
let t = no_var_fn_met(
|
||||
arr_t.clone(),
|
||||
vec![kw(KW_RHS, array_t(T.clone(), M.clone()))],
|
||||
lis_t.clone(),
|
||||
vec![kw(KW_RHS, list_t(T.clone(), M.clone()))],
|
||||
vec![],
|
||||
array_t(T.clone(), N.clone() + M.clone()),
|
||||
list_t(T.clone(), N.clone() + M.clone()),
|
||||
)
|
||||
.quantify();
|
||||
array_.register_py_builtin(FUNC_CONCAT, t.clone(), Some(OP_ADD), 9);
|
||||
list_.register_py_builtin(FUNC_CONCAT, t.clone(), Some(OP_ADD), 9);
|
||||
let t_count =
|
||||
no_var_fn_met(arr_t.clone(), vec![kw(KW_X, T.clone())], vec![], Nat).quantify();
|
||||
array_.register_py_builtin(FUNC_COUNT, t_count, Some(FUNC_COUNT), 17);
|
||||
no_var_fn_met(lis_t.clone(), vec![kw(KW_X, T.clone())], vec![], Nat).quantify();
|
||||
list_.register_py_builtin(FUNC_COUNT, t_count, Some(FUNC_COUNT), 17);
|
||||
let t_get = no_var_fn_met(
|
||||
arr_t.clone(),
|
||||
lis_t.clone(),
|
||||
vec![pos(Nat)],
|
||||
vec![ParamTy::kw_default(KW_DEFAULT.into(), U.clone(), NoneType)],
|
||||
or(T.clone(), U.clone()),
|
||||
)
|
||||
.quantify();
|
||||
array_.register_builtin_erg_impl(FUNC_GET, t_get, Immutable, Visibility::BUILTIN_PUBLIC);
|
||||
// Array(T, N)|<: Add(Array(T, M))|.
|
||||
// Output = Array(T, N + M)
|
||||
// __add__: (self: Array(T, N), other: Array(T, M)) -> Array(T, N + M) = Array.concat
|
||||
let mut array_add = Self::builtin_methods(
|
||||
Some(poly(ADD, vec![ty_tp(array_t(T.clone(), M.clone()))])),
|
||||
list_.register_builtin_erg_impl(FUNC_GET, t_get, Immutable, Visibility::BUILTIN_PUBLIC);
|
||||
// List(T, N)|<: Add(List(T, M))|.
|
||||
// Output = List(T, N + M)
|
||||
// __add__: (self: List(T, N), other: List(T, M)) -> List(T, N + M) = List.concat
|
||||
let mut list_add = Self::builtin_methods(
|
||||
Some(poly(ADD, vec![ty_tp(list_t(T.clone(), M.clone()))])),
|
||||
2,
|
||||
);
|
||||
array_add.register_builtin_erg_impl(OP_ADD, t, Immutable, Visibility::BUILTIN_PUBLIC);
|
||||
let out_t = array_t(T.clone(), N.clone() + M.clone());
|
||||
array_add.register_builtin_const(
|
||||
list_add.register_builtin_erg_impl(OP_ADD, t, Immutable, Visibility::BUILTIN_PUBLIC);
|
||||
let out_t = list_t(T.clone(), N.clone() + M.clone());
|
||||
list_add.register_builtin_const(
|
||||
OUTPUT,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
None,
|
||||
ValueObj::builtin_class(out_t),
|
||||
);
|
||||
array_.register_trait_methods(arr_t.clone(), array_add);
|
||||
list_.register_trait_methods(lis_t.clone(), list_add);
|
||||
let t = no_var_fn_met(
|
||||
arr_t.clone(),
|
||||
lis_t.clone(),
|
||||
vec![kw(KW_ELEM, T.clone())],
|
||||
vec![],
|
||||
array_t(T.clone(), N.clone() + value(1usize)),
|
||||
list_t(T.clone(), N.clone() + value(1usize)),
|
||||
)
|
||||
.quantify();
|
||||
array_.register_builtin_erg_impl(FUNC_PUSH, t, Immutable, Visibility::BUILTIN_PUBLIC);
|
||||
list_.register_builtin_erg_impl(FUNC_PUSH, t, Immutable, Visibility::BUILTIN_PUBLIC);
|
||||
let repeat_t = no_var_fn_met(
|
||||
arr_t.clone(),
|
||||
lis_t.clone(),
|
||||
vec![pos(singleton(Nat, M.clone()))],
|
||||
vec![],
|
||||
array_t(T.clone(), N.clone() * M.clone()),
|
||||
list_t(T.clone(), N.clone() * M.clone()),
|
||||
)
|
||||
.quantify();
|
||||
array_.register_builtin_erg_impl(
|
||||
list_.register_builtin_erg_impl(
|
||||
FUNC_REPEAT,
|
||||
repeat_t,
|
||||
Immutable,
|
||||
|
@ -1667,15 +1667,15 @@ impl Context {
|
|||
);
|
||||
// [T; N].MutType! = [T; !N] (neither [T!; N] nor [T; N]!)
|
||||
let mut_type =
|
||||
ValueObj::builtin_class(poly(MUT_ARRAY, vec![TyParam::t(T.clone()), N.clone()]));
|
||||
let mut array_mutizable = Self::builtin_methods(Some(mono(MUTIZABLE)), 2);
|
||||
array_mutizable.register_builtin_const(
|
||||
ValueObj::builtin_class(poly(MUT_LIST, vec![TyParam::t(T.clone()), N.clone()]));
|
||||
let mut list_mutizable = Self::builtin_methods(Some(mono(MUTIZABLE)), 2);
|
||||
list_mutizable.register_builtin_const(
|
||||
MUTABLE_MUT_TYPE,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
None,
|
||||
mut_type,
|
||||
);
|
||||
array_.register_trait_methods(arr_t.clone(), array_mutizable);
|
||||
list_.register_trait_methods(lis_t.clone(), list_mutizable);
|
||||
let var = FRESH_GEN.fresh_varname();
|
||||
let input = refinement(
|
||||
var.clone(),
|
||||
|
@ -1684,259 +1684,254 @@ impl Context {
|
|||
);
|
||||
// __getitem__: |T, N|(self: [T; N], _: {I: Nat | I <= N}) -> T
|
||||
// and (self: [T; N], _: Range(Int)) -> [T; _]
|
||||
let array_getitem_t = (fn1_kw_met(
|
||||
array_t(T.clone(), N.clone()),
|
||||
anon(input.clone()),
|
||||
T.clone(),
|
||||
) & fn1_kw_met(
|
||||
array_t(T.clone(), N.clone()),
|
||||
anon(poly(RANGE, vec![ty_tp(Int)])),
|
||||
unknown_len_array_t(T.clone()),
|
||||
))
|
||||
.quantify();
|
||||
let list_getitem_t =
|
||||
(fn1_kw_met(list_t(T.clone(), N.clone()), anon(input.clone()), T.clone())
|
||||
& fn1_kw_met(
|
||||
list_t(T.clone(), N.clone()),
|
||||
anon(poly(RANGE, vec![ty_tp(Int)])),
|
||||
unknown_len_list_t(T.clone()),
|
||||
))
|
||||
.quantify();
|
||||
let get_item = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNDAMENTAL_GETITEM,
|
||||
__array_getitem__,
|
||||
array_getitem_t,
|
||||
__list_getitem__,
|
||||
list_getitem_t,
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(
|
||||
list_.register_builtin_const(
|
||||
FUNDAMENTAL_GETITEM,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
None,
|
||||
get_item,
|
||||
);
|
||||
let array_insert_t = no_var_fn_met(
|
||||
array_t(T.clone(), N.clone()),
|
||||
let list_insert_t = no_var_fn_met(
|
||||
list_t(T.clone(), N.clone()),
|
||||
vec![pos(Nat), kw(KW_ELEM, T.clone())],
|
||||
vec![],
|
||||
array_t(T.clone(), N.clone() + value(1usize)),
|
||||
list_t(T.clone(), N.clone() + value(1usize)),
|
||||
)
|
||||
.quantify();
|
||||
let array_insert = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
let list_insert = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_INSERT,
|
||||
array_insert_at,
|
||||
array_insert_t.clone(),
|
||||
list_insert_at,
|
||||
list_insert_t.clone(),
|
||||
None,
|
||||
)));
|
||||
array_._register_builtin_const(
|
||||
list_._register_builtin_const(
|
||||
FUNC_INSERT,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(array_insert_t),
|
||||
array_insert,
|
||||
Some(list_insert_t),
|
||||
list_insert,
|
||||
Some(FUNC_INSERT_AT.into()),
|
||||
);
|
||||
let array_remove_at_t = no_var_fn_met(
|
||||
array_t(T.clone(), N.clone()),
|
||||
let list_remove_at_t = no_var_fn_met(
|
||||
list_t(T.clone(), N.clone()),
|
||||
vec![pos(Nat)],
|
||||
vec![],
|
||||
array_t(T.clone(), N.clone() - value(1usize)),
|
||||
list_t(T.clone(), N.clone() - value(1usize)),
|
||||
)
|
||||
.quantify();
|
||||
let array_remove_at = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
let list_remove_at = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_REMOVE_AT,
|
||||
array_remove_at,
|
||||
array_remove_at_t.clone(),
|
||||
list_remove_at,
|
||||
list_remove_at_t.clone(),
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(
|
||||
list_.register_builtin_const(
|
||||
FUNC_REMOVE_AT,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(array_remove_at_t),
|
||||
array_remove_at,
|
||||
Some(list_remove_at_t),
|
||||
list_remove_at,
|
||||
);
|
||||
let array_remove_all_t = no_var_fn_met(
|
||||
array_t(T.clone(), N.clone()),
|
||||
let list_remove_all_t = no_var_fn_met(
|
||||
list_t(T.clone(), N.clone()),
|
||||
vec![kw(KW_ELEM, T.clone())],
|
||||
vec![],
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
)
|
||||
.quantify();
|
||||
let array_remove_all = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
let list_remove_all = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_REMOVE_ALL,
|
||||
array_remove_all,
|
||||
array_remove_all_t.clone(),
|
||||
list_remove_all,
|
||||
list_remove_all_t.clone(),
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(
|
||||
list_.register_builtin_const(
|
||||
FUNC_REMOVE_ALL,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(array_remove_all_t),
|
||||
array_remove_all,
|
||||
Some(list_remove_all_t),
|
||||
list_remove_all,
|
||||
);
|
||||
array_
|
||||
list_
|
||||
.register_trait(self, poly(INDEXABLE, vec![ty_tp(input), ty_tp(T.clone())]))
|
||||
.unwrap();
|
||||
array_
|
||||
list_
|
||||
.register_trait(
|
||||
self,
|
||||
poly(
|
||||
HAS_SHAPE,
|
||||
vec![ty_tp(arr_t.clone()).proj_call(FUNC_SHAPE.into(), vec![])],
|
||||
vec![ty_tp(lis_t.clone()).proj_call(FUNC_SHAPE.into(), vec![])],
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
array_
|
||||
list_
|
||||
.register_trait(
|
||||
self,
|
||||
poly(
|
||||
HAS_SCALAR_TYPE,
|
||||
vec![ty_tp(arr_t.clone()).proj_call(FUNC_SCALAR_TYPE.into(), vec![])],
|
||||
vec![ty_tp(lis_t.clone()).proj_call(FUNC_SCALAR_TYPE.into(), vec![])],
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
let mut array_sized = Self::builtin_methods(Some(mono(SIZED)), 2);
|
||||
array_sized.register_builtin_erg_impl(
|
||||
let mut list_sized = Self::builtin_methods(Some(mono(SIZED)), 2);
|
||||
list_sized.register_builtin_erg_impl(
|
||||
FUNDAMENTAL_LEN,
|
||||
fn0_met(arr_t.clone(), Nat).quantify(),
|
||||
fn0_met(lis_t.clone(), Nat).quantify(),
|
||||
Const,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
array_.register_trait_methods(arr_t.clone(), array_sized);
|
||||
list_.register_trait_methods(lis_t.clone(), list_sized);
|
||||
// union: (self: [Type; _]) -> Type
|
||||
let array_union_t = fn0_met(array_t(Type, TyParam::erased(Nat)), Type).quantify();
|
||||
let list_union_t = fn0_met(list_t(Type, TyParam::erased(Nat)), Type).quantify();
|
||||
let union = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_UNION,
|
||||
array_union,
|
||||
array_union_t,
|
||||
list_union,
|
||||
list_union_t,
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(FUNC_UNION, Visibility::BUILTIN_PUBLIC, None, union);
|
||||
list_.register_builtin_const(FUNC_UNION, Visibility::BUILTIN_PUBLIC, None, union);
|
||||
// shape: (self: [Type; _]) -> [Nat; _]
|
||||
let array_shape_t = fn0_met(
|
||||
array_t(Type, TyParam::erased(Nat)),
|
||||
unknown_len_array_t(Nat),
|
||||
)
|
||||
.quantify();
|
||||
let list_shape_t =
|
||||
fn0_met(list_t(Type, TyParam::erased(Nat)), unknown_len_list_t(Nat)).quantify();
|
||||
let shape = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_SHAPE,
|
||||
array_shape,
|
||||
array_shape_t,
|
||||
list_shape,
|
||||
list_shape_t,
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(FUNC_SHAPE, Visibility::BUILTIN_PUBLIC, None, shape);
|
||||
let array_scalar_type_t = fn0_met(Type, Type).quantify();
|
||||
let array_scalar_type = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
list_.register_builtin_const(FUNC_SHAPE, Visibility::BUILTIN_PUBLIC, None, shape);
|
||||
let list_scalar_type_t = fn0_met(Type, Type).quantify();
|
||||
let list_scalar_type = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_SCALAR_TYPE,
|
||||
array_scalar_type,
|
||||
array_scalar_type_t,
|
||||
list_scalar_type,
|
||||
list_scalar_type_t,
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(
|
||||
list_.register_builtin_const(
|
||||
FUNC_SCALAR_TYPE,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
None,
|
||||
array_scalar_type,
|
||||
list_scalar_type,
|
||||
);
|
||||
let mut array_eq = Self::builtin_methods(Some(mono(EQ)), 2);
|
||||
array_eq.register_builtin_erg_impl(
|
||||
let mut list_eq = Self::builtin_methods(Some(mono(EQ)), 2);
|
||||
list_eq.register_builtin_erg_impl(
|
||||
OP_EQ,
|
||||
fn1_met(arr_t.clone(), arr_t.clone(), Bool).quantify(),
|
||||
fn1_met(lis_t.clone(), lis_t.clone(), Bool).quantify(),
|
||||
Const,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
array_.register_trait_methods(arr_t.clone(), array_eq);
|
||||
array_
|
||||
list_.register_trait_methods(lis_t.clone(), list_eq);
|
||||
list_
|
||||
.register_trait(self, poly(SEQUENCE, vec![ty_tp(T.clone())]))
|
||||
.unwrap();
|
||||
array_.unregister_trait(&poly(INDEXABLE, vec![ty_tp(Nat), ty_tp(T.clone())]));
|
||||
let mut array_show = Self::builtin_methods(Some(mono(SHOW)), 1);
|
||||
array_show.register_builtin_py_impl(
|
||||
list_.unregister_trait(&poly(INDEXABLE, vec![ty_tp(Nat), ty_tp(T.clone())]));
|
||||
let mut list_show = Self::builtin_methods(Some(mono(SHOW)), 1);
|
||||
list_show.register_builtin_py_impl(
|
||||
FUNDAMENTAL_STR,
|
||||
fn0_met(arr_t.clone(), Str).quantify(),
|
||||
fn0_met(lis_t.clone(), Str).quantify(),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNDAMENTAL_STR),
|
||||
);
|
||||
array_.register_trait_methods(arr_t.clone(), array_show);
|
||||
let mut array_iterable =
|
||||
list_.register_trait_methods(lis_t.clone(), list_show);
|
||||
let mut list_iterable =
|
||||
Self::builtin_methods(Some(poly(ITERABLE, vec![ty_tp(T.clone())])), 2);
|
||||
let array_iter = poly(ARRAY_ITERATOR, vec![ty_tp(T.clone())]);
|
||||
let t = fn0_met(array_t(T.clone(), TyParam::erased(Nat)), array_iter.clone()).quantify();
|
||||
array_iterable.register_builtin_py_impl(
|
||||
let list_iter = poly(LIST_ITERATOR, vec![ty_tp(T.clone())]);
|
||||
let t = fn0_met(list_t(T.clone(), TyParam::erased(Nat)), list_iter.clone()).quantify();
|
||||
list_iterable.register_builtin_py_impl(
|
||||
FUNC_ITER,
|
||||
t,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNDAMENTAL_ITER),
|
||||
);
|
||||
array_iterable.register_builtin_const(
|
||||
list_iterable.register_builtin_const(
|
||||
ITERATOR,
|
||||
vis.clone(),
|
||||
None,
|
||||
ValueObj::builtin_class(array_iter),
|
||||
ValueObj::builtin_class(list_iter),
|
||||
);
|
||||
array_.register_trait_methods(arr_t.clone(), array_iterable);
|
||||
let mut array_collection =
|
||||
list_.register_trait_methods(lis_t.clone(), list_iterable);
|
||||
let mut list_collection =
|
||||
Self::builtin_methods(Some(poly(COLLECTION, vec![ty_tp(T.clone())])), 4);
|
||||
array_collection.register_builtin_erg_impl(
|
||||
list_collection.register_builtin_erg_impl(
|
||||
FUNDAMENTAL_CONTAINS,
|
||||
fn1_met(arr_t.clone(), T.clone(), Bool).quantify(),
|
||||
fn1_met(lis_t.clone(), T.clone(), Bool).quantify(),
|
||||
Const,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
array_.register_trait_methods(arr_t.clone(), array_collection);
|
||||
array_
|
||||
list_.register_trait_methods(lis_t.clone(), list_collection);
|
||||
list_
|
||||
.register_trait(self, poly(COLLECTION, vec![ty_tp(T.clone())]))
|
||||
.unwrap();
|
||||
let t = fn1_met(
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
func1(T.clone(), Bool),
|
||||
tuple_t(vec![
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
]),
|
||||
);
|
||||
array_.register_py_builtin(FUNC_PARTITION, t.quantify(), Some(FUNC_PARTITION), 37);
|
||||
list_.register_py_builtin(FUNC_PARTITION, t.quantify(), Some(FUNC_PARTITION), 37);
|
||||
let t = no_var_fn_met(
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
vec![],
|
||||
vec![kw(
|
||||
KW_SAME_BUCKET,
|
||||
or(func2(T.clone(), T.clone(), Bool), NoneType),
|
||||
)],
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
);
|
||||
array_.register_py_builtin(FUNC_DEDUP, t.quantify(), Some(FUNC_DEDUP), 28);
|
||||
list_.register_py_builtin(FUNC_DEDUP, t.quantify(), Some(FUNC_DEDUP), 28);
|
||||
let sum_t = no_var_fn_met(
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
vec![],
|
||||
vec![kw(KW_START, T.clone())],
|
||||
T.clone(),
|
||||
);
|
||||
let sum = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_SUM,
|
||||
array_sum,
|
||||
list_sum,
|
||||
sum_t.quantify(),
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(FUNC_SUM, Visibility::BUILTIN_PUBLIC, None, sum);
|
||||
list_.register_builtin_const(FUNC_SUM, Visibility::BUILTIN_PUBLIC, None, sum);
|
||||
let prod_t = no_var_fn_met(
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
vec![],
|
||||
vec![kw(KW_START, T.clone())],
|
||||
T.clone(),
|
||||
);
|
||||
let prod = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_PROD,
|
||||
array_prod,
|
||||
list_prod,
|
||||
prod_t.quantify(),
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(FUNC_PROD, Visibility::BUILTIN_PUBLIC, None, prod);
|
||||
list_.register_builtin_const(FUNC_PROD, Visibility::BUILTIN_PUBLIC, None, prod);
|
||||
let reversed_t = no_var_fn_met(
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
vec![],
|
||||
vec![],
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
);
|
||||
let reversed = ValueObj::Subr(ConstSubr::Builtin(BuiltinConstSubr::new(
|
||||
FUNC_REVERSED,
|
||||
array_reversed,
|
||||
list_reversed,
|
||||
reversed_t.quantify(),
|
||||
None,
|
||||
)));
|
||||
array_.register_builtin_const(FUNC_REVERSED, Visibility::BUILTIN_PUBLIC, None, reversed);
|
||||
list_.register_builtin_const(FUNC_REVERSED, Visibility::BUILTIN_PUBLIC, None, reversed);
|
||||
/* Slice */
|
||||
let mut slice = Self::builtin_mono_class(SLICE, 3);
|
||||
slice.register_superclass(Obj, &obj);
|
||||
|
@ -2284,7 +2279,7 @@ impl Context {
|
|||
/* GenericTuple */
|
||||
let mut generic_tuple = Self::builtin_mono_class(GENERIC_TUPLE, 1);
|
||||
generic_tuple.register_superclass(Obj, &obj);
|
||||
// tuple doesn't have a constructor, use `Array` instead
|
||||
// tuple doesn't have a constructor, use `List` instead
|
||||
let mut tuple_eq = Self::builtin_methods(Some(mono(EQ)), 2);
|
||||
tuple_eq.register_builtin_erg_impl(
|
||||
OP_EQ,
|
||||
|
@ -2302,14 +2297,11 @@ impl Context {
|
|||
);
|
||||
generic_tuple.register_trait_methods(mono(GENERIC_TUPLE), tuple_hash);
|
||||
generic_tuple.register_trait(self, mono(EQ_HASH)).unwrap();
|
||||
let Ts = mono_q_tp(TY_TS, instanceof(array_t(Type, N.clone())));
|
||||
// Ts <: GenericArray
|
||||
let Ts = mono_q_tp(TY_TS, instanceof(list_t(Type, N.clone())));
|
||||
// Ts <: GenericList
|
||||
let _tuple_t = poly(TUPLE, vec![Ts.clone()]);
|
||||
let mut tuple_ = Self::builtin_poly_class(
|
||||
TUPLE,
|
||||
vec![PS::named_nd(TY_TS, array_t(Type, N.clone()))],
|
||||
2,
|
||||
);
|
||||
let mut tuple_ =
|
||||
Self::builtin_poly_class(TUPLE, vec![PS::named_nd(TY_TS, list_t(Type, N.clone()))], 2);
|
||||
tuple_.register_superclass(mono(GENERIC_TUPLE), &generic_tuple);
|
||||
tuple_
|
||||
.register_trait(self, poly(OUTPUT, vec![Ts.clone()]))
|
||||
|
@ -2498,12 +2490,12 @@ impl Context {
|
|||
str_iterator
|
||||
.register_trait(self, poly(OUTPUT, vec![ty_tp(Str)]))
|
||||
.unwrap();
|
||||
let mut array_iterator = Self::builtin_poly_class(ARRAY_ITERATOR, vec![PS::t_nd(TY_T)], 1);
|
||||
array_iterator.register_superclass(Obj, &obj);
|
||||
array_iterator
|
||||
let mut list_iterator = Self::builtin_poly_class(LIST_ITERATOR, vec![PS::t_nd(TY_T)], 1);
|
||||
list_iterator.register_superclass(Obj, &obj);
|
||||
list_iterator
|
||||
.register_trait(self, poly(ITERABLE, vec![ty_tp(T.clone())]))
|
||||
.unwrap();
|
||||
array_iterator
|
||||
list_iterator
|
||||
.register_trait(self, poly(OUTPUT, vec![ty_tp(T.clone())]))
|
||||
.unwrap();
|
||||
let mut set_iterator = Self::builtin_poly_class(SET_ITERATOR, vec![PS::t_nd(TY_T)], 1);
|
||||
|
@ -3004,16 +2996,16 @@ impl Context {
|
|||
file_mut
|
||||
.register_trait(self, mono(CONTEXT_MANAGER))
|
||||
.unwrap();
|
||||
/* Array! */
|
||||
let array_mut_t = poly(MUT_ARRAY, vec![ty_tp(T.clone()), N.clone()]);
|
||||
let mut array_mut_ =
|
||||
Self::builtin_poly_class(MUT_ARRAY, vec![PS::t_nd(TY_T), PS::default(TY_N, Nat)], 2);
|
||||
array_mut_.register_superclass(arr_t.clone(), &array_);
|
||||
/* List! */
|
||||
let list_mut_t = poly(MUT_LIST, vec![ty_tp(T.clone()), N.clone()]);
|
||||
let mut list_mut_ =
|
||||
Self::builtin_poly_class(MUT_LIST, vec![PS::t_nd(TY_T), PS::default(TY_N, Nat)], 2);
|
||||
list_mut_.register_superclass(lis_t.clone(), &list_);
|
||||
let t = pr_met(
|
||||
ref_mut(
|
||||
array_mut_t.clone(),
|
||||
list_mut_t.clone(),
|
||||
Some(poly(
|
||||
MUT_ARRAY,
|
||||
MUT_LIST,
|
||||
vec![ty_tp(T.clone()), N.clone() + value(1usize)],
|
||||
)),
|
||||
),
|
||||
|
@ -3023,18 +3015,15 @@ impl Context {
|
|||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_PUSH, t, Some(FUNC_APPEND), 15);
|
||||
let t_copy = fn0_met(ref_(array_mut_t.clone()), array_mut_t.clone()).quantify();
|
||||
let mut array_mut_copy = Self::builtin_methods(Some(mono(COPY)), 2);
|
||||
array_mut_copy.register_py_builtin(FUNC_COPY, t_copy, Some(FUNC_COPY), 116);
|
||||
array_mut_.register_trait_methods(array_mut_t.clone(), array_mut_copy);
|
||||
list_mut_.register_py_builtin(PROC_PUSH, t, Some(FUNC_APPEND), 15);
|
||||
let t_copy = fn0_met(ref_(list_mut_t.clone()), list_mut_t.clone()).quantify();
|
||||
let mut list_mut_copy = Self::builtin_methods(Some(mono(COPY)), 2);
|
||||
list_mut_copy.register_py_builtin(FUNC_COPY, t_copy, Some(FUNC_COPY), 116);
|
||||
list_mut_.register_trait_methods(list_mut_t.clone(), list_mut_copy);
|
||||
let t_extend = pr_met(
|
||||
ref_mut(
|
||||
array_mut_t.clone(),
|
||||
Some(poly(
|
||||
MUT_ARRAY,
|
||||
vec![ty_tp(T.clone()), TyParam::erased(Nat)],
|
||||
)),
|
||||
list_mut_t.clone(),
|
||||
Some(poly(MUT_LIST, vec![ty_tp(T.clone()), TyParam::erased(Nat)])),
|
||||
),
|
||||
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
|
||||
None,
|
||||
|
@ -3042,12 +3031,12 @@ impl Context {
|
|||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_EXTEND, t_extend, Some(FUNC_EXTEND), 24);
|
||||
list_mut_.register_py_builtin(PROC_EXTEND, t_extend, Some(FUNC_EXTEND), 24);
|
||||
let t_insert = pr_met(
|
||||
ref_mut(
|
||||
array_mut_t.clone(),
|
||||
list_mut_t.clone(),
|
||||
Some(poly(
|
||||
MUT_ARRAY,
|
||||
MUT_LIST,
|
||||
vec![ty_tp(T.clone()), N.clone() + value(1usize)],
|
||||
)),
|
||||
),
|
||||
|
@ -3057,12 +3046,12 @@ impl Context {
|
|||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_INSERT, t_insert, Some(FUNC_INSERT), 33);
|
||||
list_mut_.register_py_builtin(PROC_INSERT, t_insert, Some(FUNC_INSERT), 33);
|
||||
let t_remove = pr_met(
|
||||
ref_mut(
|
||||
array_mut_t.clone(),
|
||||
list_mut_t.clone(),
|
||||
Some(poly(
|
||||
MUT_ARRAY,
|
||||
MUT_LIST,
|
||||
vec![ty_tp(T.clone()), N.clone() - value(1usize)],
|
||||
)),
|
||||
),
|
||||
|
@ -3072,12 +3061,12 @@ impl Context {
|
|||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_REMOVE, t_remove, Some(FUNC_REMOVE), 42);
|
||||
list_mut_.register_py_builtin(PROC_REMOVE, t_remove, Some(FUNC_REMOVE), 42);
|
||||
let t_pop = pr_met(
|
||||
ref_mut(
|
||||
array_mut_t.clone(),
|
||||
list_mut_t.clone(),
|
||||
Some(poly(
|
||||
MUT_ARRAY,
|
||||
MUT_LIST,
|
||||
vec![ty_tp(T.clone()), N.clone() - value(1usize)],
|
||||
)),
|
||||
),
|
||||
|
@ -3087,18 +3076,18 @@ impl Context {
|
|||
T.clone(),
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_POP, t_pop, Some(FUNC_POP), 52);
|
||||
list_mut_.register_py_builtin(PROC_POP, t_pop, Some(FUNC_POP), 52);
|
||||
let t_clear = pr0_met(
|
||||
ref_mut(
|
||||
array_mut_t.clone(),
|
||||
Some(poly(MUT_ARRAY, vec![ty_tp(T.clone()), value(0usize)])),
|
||||
list_mut_t.clone(),
|
||||
Some(poly(MUT_LIST, vec![ty_tp(T.clone()), value(0usize)])),
|
||||
),
|
||||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_CLEAR, t_clear, Some(FUNC_CLEAR), 61);
|
||||
list_mut_.register_py_builtin(PROC_CLEAR, t_clear, Some(FUNC_CLEAR), 61);
|
||||
let t_sort = pr_met(
|
||||
ref_mut(array_mut_t.clone(), None),
|
||||
ref_mut(list_mut_t.clone(), None),
|
||||
vec![],
|
||||
None,
|
||||
vec![kw(
|
||||
|
@ -3108,77 +3097,77 @@ impl Context {
|
|||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_SORT, t_sort, Some(FUNC_SORT), 78);
|
||||
let t_reverse = pr0_met(ref_mut(array_mut_t.clone(), None), NoneType).quantify();
|
||||
array_mut_.register_py_builtin(PROC_REVERSE, t_reverse, Some(FUNC_REVERSE), 87);
|
||||
list_mut_.register_py_builtin(PROC_SORT, t_sort, Some(FUNC_SORT), 78);
|
||||
let t_reverse = pr0_met(ref_mut(list_mut_t.clone(), None), NoneType).quantify();
|
||||
list_mut_.register_py_builtin(PROC_REVERSE, t_reverse, Some(FUNC_REVERSE), 87);
|
||||
let t = pr_met(
|
||||
array_mut_t.clone(),
|
||||
list_mut_t.clone(),
|
||||
vec![kw(KW_FUNC, nd_func(vec![anon(T.clone())], None, T.clone()))],
|
||||
None,
|
||||
vec![],
|
||||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_STRICT_MAP, t, None, 96);
|
||||
list_mut_.register_py_builtin(PROC_STRICT_MAP, t, None, 96);
|
||||
let t_update_nth = pr_met(
|
||||
ref_mut(array_mut_t.clone(), None),
|
||||
ref_mut(list_mut_t.clone(), None),
|
||||
vec![kw(KW_IDX, Nat), kw(KW_FUNC, func1(T.clone(), T.clone()))],
|
||||
None,
|
||||
vec![],
|
||||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
array_mut_.register_py_builtin(PROC_UPDATE_NTH, t_update_nth, Some(FUNC_UPDATE_NTH), 105);
|
||||
list_mut_.register_py_builtin(PROC_UPDATE_NTH, t_update_nth, Some(FUNC_UPDATE_NTH), 105);
|
||||
let f_t = kw(
|
||||
KW_FUNC,
|
||||
no_var_func(vec![kw(KW_OLD, arr_t.clone())], vec![], arr_t.clone()),
|
||||
no_var_func(vec![kw(KW_OLD, lis_t.clone())], vec![], lis_t.clone()),
|
||||
);
|
||||
let t = pr_met(
|
||||
ref_mut(array_mut_t.clone(), None),
|
||||
ref_mut(list_mut_t.clone(), None),
|
||||
vec![f_t],
|
||||
None,
|
||||
vec![],
|
||||
NoneType,
|
||||
)
|
||||
.quantify();
|
||||
let mut array_mut_mutable = Self::builtin_methods(Some(mono(MUTABLE)), 2);
|
||||
array_mut_mutable.register_builtin_py_impl(
|
||||
let mut list_mut_mutable = Self::builtin_methods(Some(mono(MUTABLE)), 2);
|
||||
list_mut_mutable.register_builtin_py_impl(
|
||||
PROC_UPDATE,
|
||||
t,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNC_UPDATE),
|
||||
);
|
||||
array_mut_.register_trait_methods(array_mut_t.clone(), array_mut_mutable);
|
||||
list_mut_.register_trait_methods(list_mut_t.clone(), list_mut_mutable);
|
||||
/* ByteArray! */
|
||||
let bytearray_mut_t = mono(BYTEARRAY);
|
||||
let mut bytearray_mut = Self::builtin_mono_class(BYTEARRAY, 2);
|
||||
let bytelist_mut_t = mono(BYTEARRAY);
|
||||
let mut bytelist_mut = Self::builtin_mono_class(BYTEARRAY, 2);
|
||||
let t_append = pr_met(
|
||||
ref_mut(bytearray_mut_t.clone(), None),
|
||||
ref_mut(bytelist_mut_t.clone(), None),
|
||||
vec![kw(KW_ELEM, int_interval(IntervalOp::Closed, 0, 255))],
|
||||
None,
|
||||
vec![],
|
||||
NoneType,
|
||||
);
|
||||
bytearray_mut.register_builtin_py_impl(
|
||||
bytelist_mut.register_builtin_py_impl(
|
||||
PROC_PUSH,
|
||||
t_append,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNC_APPEND),
|
||||
);
|
||||
let t_copy = fn0_met(ref_(bytearray_mut_t.clone()), bytearray_mut_t.clone());
|
||||
let mut bytearray_mut_copy = Self::builtin_methods(Some(mono(COPY)), 2);
|
||||
bytearray_mut_copy.register_builtin_py_impl(
|
||||
let t_copy = fn0_met(ref_(bytelist_mut_t.clone()), bytelist_mut_t.clone());
|
||||
let mut bytelist_mut_copy = Self::builtin_methods(Some(mono(COPY)), 2);
|
||||
bytelist_mut_copy.register_builtin_py_impl(
|
||||
FUNC_COPY,
|
||||
t_copy,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNC_COPY),
|
||||
);
|
||||
bytearray_mut.register_trait_methods(bytearray_mut_t.clone(), bytearray_mut_copy);
|
||||
bytelist_mut.register_trait_methods(bytelist_mut_t.clone(), bytelist_mut_copy);
|
||||
let t_extend = pr_met(
|
||||
ref_mut(bytearray_mut_t.clone(), None),
|
||||
ref_mut(bytelist_mut_t.clone(), None),
|
||||
vec![kw(
|
||||
KW_ITERABLE,
|
||||
poly(
|
||||
|
@ -3190,7 +3179,7 @@ impl Context {
|
|||
vec![],
|
||||
NoneType,
|
||||
);
|
||||
bytearray_mut.register_builtin_py_impl(
|
||||
bytelist_mut.register_builtin_py_impl(
|
||||
PROC_EXTEND,
|
||||
t_extend,
|
||||
Immutable,
|
||||
|
@ -3198,7 +3187,7 @@ impl Context {
|
|||
Some(FUNC_EXTEND),
|
||||
);
|
||||
let t_insert = pr_met(
|
||||
ref_mut(bytearray_mut_t.clone(), None),
|
||||
ref_mut(bytelist_mut_t.clone(), None),
|
||||
vec![
|
||||
kw(KW_INDEX, Nat),
|
||||
kw(KW_ELEM, int_interval(IntervalOp::Closed, 0, 255)),
|
||||
|
@ -3207,7 +3196,7 @@ impl Context {
|
|||
vec![],
|
||||
NoneType,
|
||||
);
|
||||
bytearray_mut.register_builtin_py_impl(
|
||||
bytelist_mut.register_builtin_py_impl(
|
||||
PROC_INSERT,
|
||||
t_insert,
|
||||
Immutable,
|
||||
|
@ -3215,18 +3204,18 @@ impl Context {
|
|||
Some(FUNC_INSERT),
|
||||
);
|
||||
let t_pop = pr0_met(
|
||||
ref_mut(bytearray_mut_t.clone(), None),
|
||||
ref_mut(bytelist_mut_t.clone(), None),
|
||||
int_interval(IntervalOp::Closed, 0, 255),
|
||||
);
|
||||
bytearray_mut.register_builtin_py_impl(
|
||||
bytelist_mut.register_builtin_py_impl(
|
||||
PROC_POP,
|
||||
t_pop,
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNC_POP),
|
||||
);
|
||||
let t_reverse = pr0_met(ref_mut(bytearray_mut_t.clone(), None), NoneType);
|
||||
bytearray_mut.register_builtin_py_impl(
|
||||
let t_reverse = pr0_met(ref_mut(bytelist_mut_t.clone(), None), NoneType);
|
||||
bytelist_mut.register_builtin_py_impl(
|
||||
PROC_REVERSE,
|
||||
t_reverse,
|
||||
Immutable,
|
||||
|
@ -3445,7 +3434,7 @@ impl Context {
|
|||
base_exception.register_superclass(Obj, &obj);
|
||||
base_exception.register_builtin_erg_impl(
|
||||
ATTR_ARGS,
|
||||
unknown_len_array_t(Str),
|
||||
unknown_len_list_t(Str),
|
||||
Immutable,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
|
@ -3695,20 +3684,20 @@ impl Context {
|
|||
Some(MODULE_TYPE),
|
||||
);
|
||||
self.register_builtin_type(
|
||||
mono(GENERIC_ARRAY),
|
||||
generic_array,
|
||||
mono(GENERIC_LIST),
|
||||
generic_list,
|
||||
vis.clone(),
|
||||
Const,
|
||||
Some(ARRAY),
|
||||
Some(LIST),
|
||||
);
|
||||
self.register_builtin_type(
|
||||
unsized_array_t,
|
||||
unsized_array,
|
||||
unsized_list_t,
|
||||
unsized_list,
|
||||
vis.clone(),
|
||||
Const,
|
||||
Some(UNSIZED_ARRAY),
|
||||
Some(UNSIZED_LIST),
|
||||
);
|
||||
self.register_builtin_type(arr_t, array_, vis.clone(), Const, Some(ARRAY));
|
||||
self.register_builtin_type(lis_t, list_, vis.clone(), Const, Some(LIST));
|
||||
self.register_builtin_type(mono(SLICE), slice, vis.clone(), Const, Some(FUNC_SLICE));
|
||||
self.register_builtin_type(
|
||||
mono(GENERIC_SET),
|
||||
|
@ -3753,11 +3742,11 @@ impl Context {
|
|||
Some(FUNC_STR_ITERATOR),
|
||||
);
|
||||
self.register_builtin_type(
|
||||
poly(ARRAY_ITERATOR, vec![ty_tp(T.clone())]),
|
||||
array_iterator,
|
||||
poly(LIST_ITERATOR, vec![ty_tp(T.clone())]),
|
||||
list_iterator,
|
||||
Visibility::BUILTIN_PRIVATE,
|
||||
Const,
|
||||
Some(FUNC_ARRAY_ITERATOR),
|
||||
Some(FUNC_LIST_ITERATOR),
|
||||
);
|
||||
self.register_builtin_type(
|
||||
poly(SET_ITERATOR, vec![ty_tp(T.clone())]),
|
||||
|
@ -3851,10 +3840,10 @@ impl Context {
|
|||
Some(MEMORYVIEW),
|
||||
);
|
||||
self.register_builtin_type(mono(MUT_FILE), file_mut, vis.clone(), Const, Some(FILE));
|
||||
self.register_builtin_type(array_mut_t, array_mut_, vis.clone(), Const, Some(ARRAY));
|
||||
self.register_builtin_type(list_mut_t, list_mut_, vis.clone(), Const, Some(LIST));
|
||||
self.register_builtin_type(
|
||||
bytearray_mut_t,
|
||||
bytearray_mut,
|
||||
bytelist_mut_t,
|
||||
bytelist_mut,
|
||||
vis.clone(),
|
||||
Const,
|
||||
Some(BYTEARRAY),
|
||||
|
|
|
@ -186,14 +186,14 @@ pub(crate) fn structural_func(mut args: ValueArgs, ctx: &Context) -> EvalValueRe
|
|||
Ok(ValueObj::gen_t(GenTypeObj::structural(t, base)).into())
|
||||
}
|
||||
|
||||
pub(crate) fn __array_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
pub(crate) fn __list_getitem__(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let slf = match ctx.convert_value_into_array(slf) {
|
||||
let slf = match ctx.convert_value_into_list(slf) {
|
||||
Ok(slf) => slf,
|
||||
Err(val) => {
|
||||
return Err(type_mismatch("Array", val, "Self"));
|
||||
return Err(type_mismatch("List", val, "Self"));
|
||||
}
|
||||
};
|
||||
let index = args
|
||||
|
@ -369,7 +369,7 @@ pub(crate) fn dict_keys(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<T
|
|||
// let keys = poly(DICT_KEYS, vec![ty_tp(union)]);
|
||||
Ok(ValueObj::builtin_type(union).into())
|
||||
} else {
|
||||
Ok(ValueObj::Array(slf.into_keys().collect::<Vec<_>>().into()).into())
|
||||
Ok(ValueObj::List(slf.into_keys().collect::<Vec<_>>().into()).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ pub(crate) fn dict_values(mut args: ValueArgs, ctx: &Context) -> EvalValueResult
|
|||
// let values = poly(DICT_VALUES, vec![ty_tp(union)]);
|
||||
Ok(ValueObj::builtin_type(union).into())
|
||||
} else {
|
||||
Ok(ValueObj::Array(slf.into_values().collect::<Vec<_>>().into()).into())
|
||||
Ok(ValueObj::List(slf.into_values().collect::<Vec<_>>().into()).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,7 +423,7 @@ pub(crate) fn dict_items(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<
|
|||
// let items = poly(DICT_ITEMS, vec![ty_tp(union)]);
|
||||
Ok(ValueObj::builtin_type(union).into())
|
||||
} else {
|
||||
Ok(ValueObj::Array(
|
||||
Ok(ValueObj::List(
|
||||
slf.into_iter()
|
||||
.map(|(k, v)| ValueObj::Tuple(vec![k, v].into()))
|
||||
.collect::<Vec<_>>()
|
||||
|
@ -468,12 +468,12 @@ pub(crate) fn dict_diff(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<
|
|||
}
|
||||
|
||||
/// `[Int, Str].union() == Int or Str`
|
||||
pub(crate) fn array_union(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
pub(crate) fn list_union(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let ValueObj::Array(slf) = slf else {
|
||||
return Err(type_mismatch("Array", slf, "Self"));
|
||||
let ValueObj::List(slf) = slf else {
|
||||
return Err(type_mismatch("List", slf, "Self"));
|
||||
};
|
||||
let slf = slf
|
||||
.iter()
|
||||
|
@ -485,15 +485,15 @@ pub(crate) fn array_union(mut args: ValueArgs, ctx: &Context) -> EvalValueResult
|
|||
Ok(ValueObj::builtin_type(union).into())
|
||||
}
|
||||
|
||||
fn _arr_shape(arr: ValueObj, ctx: &Context) -> Result<Vec<TyParam>, String> {
|
||||
fn _lis_shape(arr: ValueObj, ctx: &Context) -> Result<Vec<TyParam>, String> {
|
||||
let mut shape = vec![];
|
||||
let mut arr = arr;
|
||||
loop {
|
||||
match arr {
|
||||
ValueObj::Array(a) => {
|
||||
ValueObj::List(a) => {
|
||||
shape.push(ValueObj::from(a.len()).into());
|
||||
match a.first() {
|
||||
Some(arr_ @ (ValueObj::Array(_) | ValueObj::Type(_))) => {
|
||||
Some(arr_ @ (ValueObj::List(_) | ValueObj::Type(_))) => {
|
||||
arr = arr_.clone();
|
||||
}
|
||||
_ => {
|
||||
|
@ -501,7 +501,7 @@ fn _arr_shape(arr: ValueObj, ctx: &Context) -> Result<Vec<TyParam>, String> {
|
|||
}
|
||||
}
|
||||
}
|
||||
ValueObj::Type(ref t) if &t.typ().qual_name()[..] == "Array" => {
|
||||
ValueObj::Type(ref t) if &t.typ().qual_name()[..] == "List" => {
|
||||
let mut tps = t.typ().typarams();
|
||||
let elem = match ctx.convert_tp_into_type(tps.remove(0)) {
|
||||
Ok(elem) => elem,
|
||||
|
@ -522,23 +522,23 @@ fn _arr_shape(arr: ValueObj, ctx: &Context) -> Result<Vec<TyParam>, String> {
|
|||
}
|
||||
|
||||
/// ```erg
|
||||
/// Array(Int, 2).shape() == [2,]
|
||||
/// Array(Array(Int, 2), N).shape() == [N, 2]
|
||||
/// List(Int, 2).shape() == [2,]
|
||||
/// List(List(Int, 2), N).shape() == [N, 2]
|
||||
/// [1, 2].shape() == [2,]
|
||||
/// [[1, 2], [3, 4], [5, 6]].shape() == [3, 2]
|
||||
/// ```
|
||||
pub(crate) fn array_shape(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
pub(crate) fn list_shape(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let res = _arr_shape(arr, ctx).unwrap();
|
||||
let arr = TyParam::Array(res);
|
||||
Ok(arr)
|
||||
let res = _lis_shape(val, ctx).unwrap();
|
||||
let lis = TyParam::List(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
fn _array_scalar_type(mut typ: Type, ctx: &Context) -> Result<Type, String> {
|
||||
fn _list_scalar_type(mut typ: Type, ctx: &Context) -> Result<Type, String> {
|
||||
loop {
|
||||
if matches!(&typ.qual_name()[..], "Array" | "Array!" | "UnsizedArray") {
|
||||
if matches!(&typ.qual_name()[..], "List" | "List!" | "UnsizedList") {
|
||||
let tp = typ.typarams().remove(0);
|
||||
match ctx.convert_tp_into_type(tp) {
|
||||
Ok(typ_) => {
|
||||
|
@ -554,21 +554,21 @@ fn _array_scalar_type(mut typ: Type, ctx: &Context) -> Result<Type, String> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn array_scalar_type(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
pub(crate) fn list_scalar_type(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let slf = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let Ok(slf) = ctx.convert_value_into_type(slf.clone()) else {
|
||||
return Err(type_mismatch("Type", slf, "Self"));
|
||||
};
|
||||
let res = _array_scalar_type(slf, ctx).unwrap();
|
||||
let res = _list_scalar_type(slf, ctx).unwrap();
|
||||
Ok(TyParam::t(res))
|
||||
}
|
||||
|
||||
fn _scalar_type(mut value: ValueObj, _ctx: &Context) -> Result<Type, String> {
|
||||
loop {
|
||||
match value {
|
||||
ValueObj::Array(a) => match a.first() {
|
||||
ValueObj::List(a) => match a.first() {
|
||||
Some(elem) => {
|
||||
value = elem.clone();
|
||||
}
|
||||
|
@ -592,7 +592,7 @@ fn _scalar_type(mut value: ValueObj, _ctx: &Context) -> Result<Type, String> {
|
|||
return Ok(Type::Never);
|
||||
}
|
||||
},
|
||||
ValueObj::UnsizedArray(a) => {
|
||||
ValueObj::UnsizedList(a) => {
|
||||
value = *a.clone();
|
||||
}
|
||||
other => {
|
||||
|
@ -608,17 +608,17 @@ fn _scalar_type(mut value: ValueObj, _ctx: &Context) -> Result<Type, String> {
|
|||
/// ```
|
||||
#[allow(unused)]
|
||||
pub(crate) fn scalar_type(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
let val = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let res = _scalar_type(arr, ctx).unwrap();
|
||||
let arr = TyParam::t(res);
|
||||
Ok(arr)
|
||||
let res = _scalar_type(val, ctx).unwrap();
|
||||
let lis = TyParam::t(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
fn _array_sum(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
fn _list_sum(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match arr {
|
||||
ValueObj::Array(a) => {
|
||||
ValueObj::List(a) => {
|
||||
let mut sum = 0f64;
|
||||
for v in a.iter() {
|
||||
match v {
|
||||
|
@ -657,18 +657,18 @@ fn _array_sum(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
|||
/// ```erg
|
||||
/// [1, 2].sum() == [3,]
|
||||
/// ```
|
||||
pub(crate) fn array_sum(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
pub(crate) fn list_sum(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let res = _array_sum(arr, ctx).unwrap();
|
||||
let arr = TyParam::Value(res);
|
||||
Ok(arr)
|
||||
let res = _list_sum(val, ctx).unwrap();
|
||||
let lis = TyParam::Value(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
fn _array_prod(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match arr {
|
||||
ValueObj::Array(a) => {
|
||||
fn _list_prod(lis: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match lis {
|
||||
ValueObj::List(a) => {
|
||||
let mut prod = 1f64;
|
||||
for v in a.iter() {
|
||||
match v {
|
||||
|
@ -700,63 +700,63 @@ fn _array_prod(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
|||
Ok(ValueObj::Float(prod))
|
||||
}
|
||||
}
|
||||
_ => Err(format!("Cannot prod {arr}")),
|
||||
_ => Err(format!("Cannot prod {lis}")),
|
||||
}
|
||||
}
|
||||
|
||||
/// ```erg
|
||||
/// [1, 2].prod() == [2,]
|
||||
/// ```
|
||||
pub(crate) fn array_prod(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
pub(crate) fn list_prod(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let res = _array_prod(arr, ctx).unwrap();
|
||||
let arr = TyParam::Value(res);
|
||||
Ok(arr)
|
||||
let res = _list_prod(val, ctx).unwrap();
|
||||
let lis = TyParam::Value(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
fn _array_reversed(arr: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match arr {
|
||||
ValueObj::Array(a) => {
|
||||
fn _list_reversed(lis: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match lis {
|
||||
ValueObj::List(a) => {
|
||||
let mut vec = a.to_vec();
|
||||
vec.reverse();
|
||||
Ok(ValueObj::Array(vec.into()))
|
||||
Ok(ValueObj::List(vec.into()))
|
||||
}
|
||||
_ => Err(format!("Cannot reverse {arr}")),
|
||||
_ => Err(format!("Cannot reverse {lis}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn array_reversed(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
pub(crate) fn list_reversed(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let res = _array_reversed(arr, ctx).unwrap();
|
||||
let arr = TyParam::Value(res);
|
||||
Ok(arr)
|
||||
let res = _list_reversed(val, ctx).unwrap();
|
||||
let lis = TyParam::Value(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
fn _array_insert_at(
|
||||
arr: ValueObj,
|
||||
fn _list_insert_at(
|
||||
lis: ValueObj,
|
||||
index: usize,
|
||||
value: ValueObj,
|
||||
_ctx: &Context,
|
||||
) -> Result<ValueObj, String> {
|
||||
match arr {
|
||||
ValueObj::Array(a) => {
|
||||
match lis {
|
||||
ValueObj::List(a) => {
|
||||
let mut a = a.to_vec();
|
||||
if index > a.len() {
|
||||
return Err(format!("Index out of range: {index}"));
|
||||
}
|
||||
a.insert(index, value);
|
||||
Ok(ValueObj::Array(a.into()))
|
||||
Ok(ValueObj::List(a.into()))
|
||||
}
|
||||
_ => Err(format!("Cannot insert into {arr}")),
|
||||
_ => Err(format!("Cannot insert into {lis}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn array_insert_at(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
pub(crate) fn list_insert_at(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let lis = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let index = args
|
||||
|
@ -768,27 +768,27 @@ pub(crate) fn array_insert_at(mut args: ValueArgs, ctx: &Context) -> EvalValueRe
|
|||
let Ok(index) = usize::try_from(&index) else {
|
||||
return Err(type_mismatch("Nat", index, "Index"));
|
||||
};
|
||||
let res = _array_insert_at(arr, index, value, ctx).unwrap();
|
||||
let arr = TyParam::Value(res);
|
||||
Ok(arr)
|
||||
let res = _list_insert_at(lis, index, value, ctx).unwrap();
|
||||
let lis = TyParam::Value(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
fn _array_remove_at(arr: ValueObj, index: usize, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match arr {
|
||||
ValueObj::Array(a) => {
|
||||
fn _list_remove_at(lis: ValueObj, index: usize, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match lis {
|
||||
ValueObj::List(a) => {
|
||||
let mut a = a.to_vec();
|
||||
if index >= a.len() {
|
||||
return Err(format!("Index out of range: {index}"));
|
||||
}
|
||||
a.remove(index);
|
||||
Ok(ValueObj::Array(a.into()))
|
||||
Ok(ValueObj::List(a.into()))
|
||||
}
|
||||
_ => Err(format!("Cannot remove from {arr}")),
|
||||
_ => Err(format!("Cannot remove from {lis}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn array_remove_at(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
pub(crate) fn list_remove_at(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let index = args
|
||||
|
@ -797,32 +797,32 @@ pub(crate) fn array_remove_at(mut args: ValueArgs, ctx: &Context) -> EvalValueRe
|
|||
let Ok(index) = usize::try_from(&index) else {
|
||||
return Err(type_mismatch("Nat", index, "Index"));
|
||||
};
|
||||
let res = _array_remove_at(arr, index, ctx).unwrap();
|
||||
let arr = TyParam::Value(res);
|
||||
Ok(arr)
|
||||
let res = _list_remove_at(val, index, ctx).unwrap();
|
||||
let lis = TyParam::Value(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
fn _array_remove_all(arr: ValueObj, value: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match arr {
|
||||
ValueObj::Array(a) => {
|
||||
fn _list_remove_all(lis: ValueObj, value: ValueObj, _ctx: &Context) -> Result<ValueObj, String> {
|
||||
match lis {
|
||||
ValueObj::List(a) => {
|
||||
let mut a = a.to_vec();
|
||||
a.retain(|v| v != &value);
|
||||
Ok(ValueObj::Array(a.into()))
|
||||
Ok(ValueObj::List(a.into()))
|
||||
}
|
||||
_ => Err(format!("Cannot remove from {arr}")),
|
||||
_ => Err(format!("Cannot remove from {lis}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn array_remove_all(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let arr = args
|
||||
pub(crate) fn list_remove_all(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
let val = args
|
||||
.remove_left_or_key("Self")
|
||||
.ok_or_else(|| not_passed("Self"))?;
|
||||
let value = args
|
||||
.remove_left_or_key("Value")
|
||||
.ok_or_else(|| not_passed("Value"))?;
|
||||
let res = _array_remove_all(arr, value, ctx).unwrap();
|
||||
let arr = TyParam::Value(res);
|
||||
Ok(arr)
|
||||
let res = _list_remove_all(val, value, ctx).unwrap();
|
||||
let lis = TyParam::Value(res);
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
pub(crate) fn __range_getitem__(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
|
@ -1058,7 +1058,7 @@ pub(crate) fn str_join(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
return Err(type_mismatch("Str", slf, "self"));
|
||||
};
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
ValueObj::Dict(d) => d.into_keys().collect(),
|
||||
|
@ -1136,7 +1136,7 @@ pub(crate) fn all_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1162,7 +1162,7 @@ pub(crate) fn any_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1191,7 +1191,7 @@ pub(crate) fn filter_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1223,7 +1223,7 @@ pub(crate) fn filter_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok(TyParam::Value(ValueObj::Array(filtered.into())))
|
||||
Ok(TyParam::Value(ValueObj::List(filtered.into())))
|
||||
}
|
||||
|
||||
pub(crate) fn len_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
|
@ -1231,7 +1231,7 @@ pub(crate) fn len_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let len = match container {
|
||||
ValueObj::Array(a) => a.len(),
|
||||
ValueObj::List(a) => a.len(),
|
||||
ValueObj::Tuple(t) => t.len(),
|
||||
ValueObj::Set(s) => s.len(),
|
||||
ValueObj::Dict(d) => d.len(),
|
||||
|
@ -1252,7 +1252,7 @@ pub(crate) fn map_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Ty
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1277,7 +1277,7 @@ pub(crate) fn map_func(mut args: ValueArgs, ctx: &Context) -> EvalValueResult<Ty
|
|||
}
|
||||
}
|
||||
}
|
||||
Ok(TyParam::Array(mapped))
|
||||
Ok(TyParam::List(mapped))
|
||||
}
|
||||
|
||||
pub(crate) fn max_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
|
@ -1285,7 +1285,7 @@ pub(crate) fn max_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1320,7 +1320,7 @@ pub(crate) fn min_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1365,7 +1365,7 @@ pub(crate) fn reversed_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueRes
|
|||
.remove_left_or_key("reversible")
|
||||
.ok_or_else(|| not_passed("reversible"))?;
|
||||
let arr = match reversible {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
_ => {
|
||||
return Err(type_mismatch("Reversible", reversible, "reversible"));
|
||||
|
@ -1375,7 +1375,7 @@ pub(crate) fn reversed_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueRes
|
|||
for v in arr.into_iter().rev() {
|
||||
reversed.push(v);
|
||||
}
|
||||
Ok(TyParam::Value(ValueObj::Array(reversed.into())))
|
||||
Ok(TyParam::Value(ValueObj::List(reversed.into())))
|
||||
}
|
||||
|
||||
pub(crate) fn str_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<TyParam> {
|
||||
|
@ -1390,7 +1390,7 @@ pub(crate) fn sum_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
.remove_left_or_key("iterable")
|
||||
.ok_or_else(|| not_passed("iterable"))?;
|
||||
let arr = match iterable {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
ValueObj::Dict(d) => d.into_keys().collect(),
|
||||
|
@ -1502,7 +1502,7 @@ pub(crate) fn zip_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
.remove_left_or_key("iterable2")
|
||||
.ok_or_else(|| not_passed("iterable2"))?;
|
||||
let iterable1 = match iterable1 {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1510,7 +1510,7 @@ pub(crate) fn zip_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
}
|
||||
};
|
||||
let iterable2 = match iterable2 {
|
||||
ValueObj::Array(a) => a.to_vec(),
|
||||
ValueObj::List(a) => a.to_vec(),
|
||||
ValueObj::Tuple(t) => t.to_vec(),
|
||||
ValueObj::Set(s) => s.into_iter().collect(),
|
||||
_ => {
|
||||
|
@ -1521,7 +1521,7 @@ pub(crate) fn zip_func(mut args: ValueArgs, _ctx: &Context) -> EvalValueResult<T
|
|||
for (v1, v2) in iterable1.into_iter().zip(iterable2.into_iter()) {
|
||||
zipped.push(ValueObj::Tuple(vec![v1, v2].into()));
|
||||
}
|
||||
Ok(TyParam::Value(ValueObj::Array(zipped.into())))
|
||||
Ok(TyParam::Value(ValueObj::List(zipped.into())))
|
||||
}
|
||||
|
||||
/// ```erg
|
||||
|
|
|
@ -53,12 +53,6 @@ impl Context {
|
|||
None,
|
||||
)));
|
||||
let t_ascii = nd_func(vec![kw(KW_OBJECT, Obj)], None, Str);
|
||||
let t_array = no_var_func(
|
||||
vec![],
|
||||
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
)
|
||||
.quantify();
|
||||
let t_assert = no_var_func(vec![kw(KW_TEST, Bool)], vec![kw(KW_MSG, Str)], NoneType);
|
||||
let t_bin = nd_func(vec![kw(KW_N, Int)], None, Str);
|
||||
let t_bytes = func0(mono(BYTES))
|
||||
|
@ -182,7 +176,7 @@ impl Context {
|
|||
let t_isinstance = nd_func(
|
||||
vec![
|
||||
kw(KW_OBJECT, Obj),
|
||||
kw(KW_CLASSINFO, ClassType | unknown_len_array_t(ClassType)), // TODO: => ClassInfo
|
||||
kw(KW_CLASSINFO, ClassType | unknown_len_list_t(ClassType)), // TODO: => ClassInfo
|
||||
],
|
||||
None,
|
||||
Bool,
|
||||
|
@ -190,7 +184,7 @@ impl Context {
|
|||
let t_issubclass = nd_func(
|
||||
vec![
|
||||
kw(KW_SUBCLASS, ClassType),
|
||||
kw(KW_CLASSINFO, ClassType | unknown_len_array_t(ClassType)), // TODO: => ClassInfo
|
||||
kw(KW_CLASSINFO, ClassType | unknown_len_list_t(ClassType)), // TODO: => ClassInfo
|
||||
],
|
||||
None,
|
||||
Bool,
|
||||
|
@ -216,6 +210,12 @@ impl Context {
|
|||
t_len.clone(),
|
||||
None,
|
||||
)));
|
||||
let t_list = no_var_func(
|
||||
vec![],
|
||||
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
)
|
||||
.quantify();
|
||||
let t_log = func(
|
||||
vec![],
|
||||
Some(kw(KW_OBJECTS, ref_(Obj))),
|
||||
|
@ -341,7 +341,7 @@ impl Context {
|
|||
let t_sorted = nd_func(
|
||||
vec![kw(KW_ITERABLE, poly(ITERABLE, vec![ty_tp(T.clone())]))],
|
||||
None,
|
||||
array_t(T.clone(), TyParam::erased(Nat)),
|
||||
list_t(T.clone(), TyParam::erased(Nat)),
|
||||
)
|
||||
.quantify();
|
||||
let t_staticmethod = nd_func(vec![kw(KW_FUNC, F.clone())], None, F.clone()).quantify();
|
||||
|
@ -411,7 +411,7 @@ impl Context {
|
|||
Some(FUNC_ANY),
|
||||
Some(33),
|
||||
);
|
||||
self.register_py_builtin(FUNC_ARRAY, t_array, Some(FUNC_LIST), 215);
|
||||
self.register_py_builtin(FUNC_LIST, t_list, Some(FUNC_LIST), 215);
|
||||
self.register_py_builtin(FUNC_ASCII, t_ascii, Some(FUNC_ASCII), 53);
|
||||
// Leave as `Const`, as it may negatively affect assert casting.
|
||||
let name = if PYTHON_MODE { FUNC_ASSERT } else { "assert__" };
|
||||
|
|
|
@ -258,10 +258,10 @@ const GENERIC_MODULE: &str = "GenericModule";
|
|||
const PATH: &str = "Path";
|
||||
const MODULE: &str = "Module";
|
||||
const PY_MODULE: &str = "PyModule";
|
||||
const GENERIC_ARRAY: &str = "GenericArray";
|
||||
const UNSIZED_ARRAY: &str = "UnsizedArray";
|
||||
const ARRAY: &str = "Array";
|
||||
const MUT_ARRAY: &str = "Array!";
|
||||
const GENERIC_LIST: &str = "GenericList";
|
||||
const UNSIZED_LIST: &str = "UnsizedList";
|
||||
const LIST: &str = "List";
|
||||
const MUT_LIST: &str = "List!";
|
||||
const FUNC_UPDATE_NTH: &str = "update_nth";
|
||||
const PROC_UPDATE_NTH: &str = "update_nth!";
|
||||
const FUNC_PARTITION: &str = "partition";
|
||||
|
@ -273,7 +273,7 @@ const FUNC_REPEAT: &str = "repeat";
|
|||
const PROC_PUSH: &str = "push!";
|
||||
const FUNC_MERGE: &str = "merge";
|
||||
const PROC_MERGE: &str = "merge!";
|
||||
const ARRAY_ITERATOR: &str = "ArrayIterator";
|
||||
const LIST_ITERATOR: &str = "ListIterator";
|
||||
const GENERIC_SET: &str = "GenericSet";
|
||||
const SET: &str = "Set";
|
||||
const MUT_SET: &str = "Set!";
|
||||
|
@ -375,7 +375,7 @@ const FUNC_DICT: &str = "dict";
|
|||
const FUNC_TUPLE: &str = "tuple";
|
||||
const UNION: &str = "Union";
|
||||
const FUNC_STR_ITERATOR: &str = "str_iterator";
|
||||
const FUNC_ARRAY_ITERATOR: &str = "array_iterator";
|
||||
const FUNC_LIST_ITERATOR: &str = "list_iterator";
|
||||
const FUNC_SET_ITERATOR: &str = "set_iterator";
|
||||
const FUNC_TUPLE_ITERATOR: &str = "tuple_iterator";
|
||||
const FUNC_ENUMERATE: &str = "enumerate";
|
||||
|
@ -391,7 +391,7 @@ const FUNC_NTH: &str = "nth";
|
|||
const FUNC_SKIP: &str = "skip";
|
||||
const FUNC_POSITION: &str = "position";
|
||||
const FUNC_CHAIN: &str = "chain";
|
||||
const FUNC_INTO_ARRAY: &str = "into_array";
|
||||
const FUNC_TO_LIST: &str = "to_list";
|
||||
const FILE: &str = "File";
|
||||
const CALLABLE: &str = "Callable";
|
||||
const GENERATOR: &str = "Generator";
|
||||
|
@ -478,7 +478,6 @@ const USER_WARNING: &str = "UserWarning";
|
|||
const FUNC_RANGE: &str = "range";
|
||||
const FUNC_ALL: &str = "all";
|
||||
const FUNC_ANY: &str = "any";
|
||||
const FUNC_ARRAY: &str = "array";
|
||||
const FUNC_ASCII: &str = "ascii";
|
||||
const FUNC_ASSERT: &str = "assert";
|
||||
const FUNC_BIN: &str = "bin";
|
||||
|
@ -1071,7 +1070,7 @@ impl Context {
|
|||
};
|
||||
let qual_name = t.qual_name();
|
||||
let name = VarName::from_str(t.local_name());
|
||||
// e.g Array!: |T, N|(_: {T}, _:= {N}) -> {Array!(T, N)}
|
||||
// e.g. List!: |T, N|(_: {T}, _:= {N}) -> {List!(T, N)}
|
||||
let nd_params = ctx
|
||||
.params_spec
|
||||
.iter()
|
||||
|
|
|
@ -30,7 +30,7 @@ impl Context {
|
|||
let t_dir = no_var_proc(
|
||||
vec![],
|
||||
vec![kw("object", ref_(Obj))],
|
||||
array_t(Str, TyParam::erased(Nat)),
|
||||
list_t(Str, TyParam::erased(Nat)),
|
||||
);
|
||||
let t_print = proc(
|
||||
vec![],
|
||||
|
|
|
@ -80,7 +80,7 @@ impl Context {
|
|||
);
|
||||
readable.register_builtin_decl(
|
||||
PROC_READLINES,
|
||||
pr0_met(ref_mut(Slf, None), unknown_len_array_t(Str)),
|
||||
pr0_met(ref_mut(Slf, None), unknown_len_list_t(Str)),
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some(FUNC_READLINES),
|
||||
);
|
||||
|
@ -263,7 +263,7 @@ impl Context {
|
|||
);
|
||||
let ret_t = poly(
|
||||
TUPLE,
|
||||
vec![TyParam::Array(vec![ty_tp(Nat), ty_tp(T.clone())])],
|
||||
vec![TyParam::List(vec![ty_tp(Nat), ty_tp(T.clone())])],
|
||||
);
|
||||
let t_enumerate = fn0_met(Slf.clone(), poly(ITERATOR, vec![ty_tp(ret_t)])).quantify();
|
||||
iterable.register_builtin_decl(
|
||||
|
@ -362,10 +362,10 @@ impl Context {
|
|||
Visibility::BUILTIN_PUBLIC,
|
||||
Some("Function::iterable_chain"),
|
||||
);
|
||||
let t_into_array = fn0_met(Slf.clone(), unknown_len_array_t(T.clone())).quantify();
|
||||
let t_to_list = fn0_met(Slf.clone(), unknown_len_list_t(T.clone())).quantify();
|
||||
iterable.register_builtin_decl(
|
||||
FUNC_INTO_ARRAY,
|
||||
t_into_array,
|
||||
FUNC_TO_LIST,
|
||||
t_to_list,
|
||||
Visibility::BUILTIN_PUBLIC,
|
||||
Some("Function::list"),
|
||||
);
|
||||
|
@ -514,8 +514,8 @@ impl Context {
|
|||
Visibility::BUILTIN_PUBLIC,
|
||||
);
|
||||
/* HasShape */
|
||||
let S = mono_q_tp(TY_S, instanceof(unknown_len_array_t(Nat)));
|
||||
let params = vec![PS::named_nd("S", unknown_len_array_t(Nat))];
|
||||
let S = mono_q_tp(TY_S, instanceof(unknown_len_list_t(Nat)));
|
||||
let params = vec![PS::named_nd("S", unknown_len_list_t(Nat))];
|
||||
let has_shape = Self::builtin_poly_trait(HAS_SHAPE, params.clone(), 2);
|
||||
/* HasScalarType */
|
||||
let Ty = mono_q_tp(TY_T, instanceof(Type));
|
||||
|
|
|
@ -3690,7 +3690,7 @@ impl Context {
|
|||
/// ```
|
||||
pub fn meta_type(&self, typ: &Type) -> Type {
|
||||
match typ {
|
||||
Type::Poly { name, params } if &name[..] == "Array" || &name[..] == "Set" => poly(
|
||||
Type::Poly { name, params } if &name[..] == "List" || &name[..] == "Set" => poly(
|
||||
name.clone(),
|
||||
params
|
||||
.iter()
|
||||
|
@ -3743,7 +3743,7 @@ impl Context {
|
|||
|
||||
/// ```erg
|
||||
/// recover_typarams(Int, Nat) == Nat
|
||||
/// recover_typarams(Array!(Int, _), Array(Nat, 2)) == Array!(Nat, 2)
|
||||
/// recover_typarams(List!(Int, _), List(Nat, 2)) == List!(Nat, 2)
|
||||
/// recover_typarams(Str or NoneType, {"a", "b"}) == {"a", "b"}
|
||||
/// ```
|
||||
/// ```erg
|
||||
|
@ -3773,7 +3773,7 @@ impl Context {
|
|||
)));
|
||||
}
|
||||
}
|
||||
// Array(Nat, 2) !<: Array!(Int, _)
|
||||
// List(Nat, 2) !<: List!(Int, _)
|
||||
let base_def_t = self
|
||||
.get_nominal_type_ctx(base)
|
||||
.map(|ctx| &ctx.typ)
|
||||
|
@ -3783,7 +3783,7 @@ impl Context {
|
|||
.map(|ctx| &ctx.typ)
|
||||
.unwrap_or(&Type::Obj);
|
||||
if self.related(base_def_t, assert_def_t) {
|
||||
// FIXME: Vec(_), Array(Int, 2) -> Vec(2)
|
||||
// FIXME: Vec(_), List(Int, 2) -> Vec(2)
|
||||
let casted = poly(base.qual_name(), guard.to.typarams());
|
||||
Ok(casted)
|
||||
} else {
|
||||
|
|
|
@ -30,7 +30,7 @@ use crate::hir;
|
|||
/// For example, cloning each type variable of quantified type `?T -> ?T` would result in `?1 -> ?2`.
|
||||
/// To avoid this, an environment to store type variables is needed, which is `TyVarCache`.
|
||||
/// 量化型をインスタンス化するための文脈
|
||||
/// e.g. Array -> [("T": ?T(: Type)), ("N": ?N(: Nat))]
|
||||
/// e.g. List -> [("T": ?T(: Type)), ("N": ?N(: Nat))]
|
||||
/// FIXME: current implementation is wrong
|
||||
/// It will not work unless the type variable is used with the same name as the definition.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -468,16 +468,16 @@ impl Context {
|
|||
.collect::<TyCheckResult<_>>()?;
|
||||
Ok(TyParam::Dict(dict))
|
||||
}
|
||||
TyParam::Array(arr) => {
|
||||
let arr = arr
|
||||
TyParam::List(lis) => {
|
||||
let lis = lis
|
||||
.into_iter()
|
||||
.map(|v| self.instantiate_tp(v, tmp_tv_cache, loc))
|
||||
.collect::<TyCheckResult<_>>()?;
|
||||
Ok(TyParam::Array(arr))
|
||||
Ok(TyParam::List(lis))
|
||||
}
|
||||
TyParam::UnsizedArray(elem) => {
|
||||
TyParam::UnsizedList(elem) => {
|
||||
let elem = self.instantiate_tp(*elem, tmp_tv_cache, loc)?;
|
||||
Ok(TyParam::UnsizedArray(Box::new(elem)))
|
||||
Ok(TyParam::UnsizedList(Box::new(elem)))
|
||||
}
|
||||
TyParam::Set(set) => {
|
||||
let set = set
|
||||
|
@ -706,12 +706,12 @@ impl Context {
|
|||
Ok(ValueObj::Subr(ConstSubr::User(user)))
|
||||
}
|
||||
},
|
||||
ValueObj::Array(arr) => {
|
||||
ValueObj::List(lis) => {
|
||||
let mut new = vec![];
|
||||
for v in arr.iter().cloned() {
|
||||
for v in lis.iter().cloned() {
|
||||
new.push(self.instantiate_value(v, tmp_tv_cache, loc)?);
|
||||
}
|
||||
Ok(ValueObj::Array(new.into()))
|
||||
Ok(ValueObj::List(new.into()))
|
||||
}
|
||||
ValueObj::Tuple(tup) => {
|
||||
let mut new = vec![];
|
||||
|
|
|
@ -10,7 +10,7 @@ use ast::{
|
|||
NonDefaultParamSignature, ParamTySpec, PreDeclTypeSpec, TypeBoundSpec, TypeBoundSpecs, TypeSpec,
|
||||
};
|
||||
use erg_parser::ast::{
|
||||
self, ConstApp, ConstArgs, ConstArray, ConstExpr, ConstSet, Identifier, VarName,
|
||||
self, ConstApp, ConstArgs, ConstExpr, ConstList, ConstSet, Identifier, VarName,
|
||||
VisModifierSpec, VisRestriction,
|
||||
};
|
||||
use erg_parser::token::TokenKind;
|
||||
|
@ -443,13 +443,13 @@ impl Context {
|
|||
ast::ParamPattern::Ref(_) => ref_(gen_free_t()),
|
||||
ast::ParamPattern::RefMut(_) => ref_mut(gen_free_t(), None),
|
||||
// ast::ParamPattern::VarName(name) if &name.inspect()[..] == "_" => Type::Obj,
|
||||
// TODO: Array<Lit>
|
||||
// TODO: List<Lit>
|
||||
_ => gen_free_t(),
|
||||
}
|
||||
};
|
||||
if let Some(decl_pt) = opt_decl_t {
|
||||
if kind.is_var_params() {
|
||||
let spec_t = unknown_len_array_t(spec_t.clone());
|
||||
let spec_t = unknown_len_list_t(spec_t.clone());
|
||||
self.sub_unify(
|
||||
decl_pt.typ(),
|
||||
&spec_t,
|
||||
|
@ -710,9 +710,9 @@ impl Context {
|
|||
not_found_is_qvar: bool,
|
||||
) -> Failable<Type> {
|
||||
match name.inspect().trim_start_matches([':', '.']) {
|
||||
"Array" => {
|
||||
"List" => {
|
||||
let ctx = &self
|
||||
.get_nominal_type_ctx(&array_t(Type::Obj, TyParam::Failure))
|
||||
.get_nominal_type_ctx(&list_t(Type::Obj, TyParam::Failure))
|
||||
.unwrap()
|
||||
.ctx;
|
||||
// TODO: kw
|
||||
|
@ -737,9 +737,9 @@ impl Context {
|
|||
} else {
|
||||
TyParam::erased(Nat)
|
||||
};
|
||||
Ok(array_t(t, len))
|
||||
Ok(list_t(t, len))
|
||||
} else {
|
||||
Ok(mono("GenericArray"))
|
||||
Ok(mono("GenericList"))
|
||||
}
|
||||
}
|
||||
"Ref" => {
|
||||
|
@ -1250,7 +1250,7 @@ impl Context {
|
|||
}
|
||||
|
||||
/// erased_index:
|
||||
/// e.g. `instantiate_const_expr(Array(Str, _), Some((self, 1))) => Array(Str, _: Nat)`
|
||||
/// e.g. `instantiate_const_expr(List(Str, _), Some((self, 1))) => List(Str, _: Nat)`
|
||||
pub(crate) fn instantiate_const_expr(
|
||||
&self,
|
||||
expr: &ast::ConstExpr,
|
||||
|
@ -1269,40 +1269,40 @@ impl Context {
|
|||
ast::ConstExpr::App(app) => {
|
||||
self.instantiate_app(app, erased_idx, tmp_tv_cache, not_found_is_qvar)
|
||||
}
|
||||
ast::ConstExpr::Array(ConstArray::Normal(array)) => {
|
||||
let mut tp_arr = vec![];
|
||||
for (i, elem) in array.elems.pos_args().enumerate() {
|
||||
ast::ConstExpr::List(ConstList::Normal(list)) => {
|
||||
let mut tp_lis = vec![];
|
||||
for (i, elem) in list.elems.pos_args().enumerate() {
|
||||
let el = self.instantiate_const_expr(
|
||||
&elem.expr,
|
||||
Some((self, i)),
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?;
|
||||
tp_arr.push(el);
|
||||
tp_lis.push(el);
|
||||
}
|
||||
Ok(TyParam::Array(tp_arr))
|
||||
Ok(TyParam::List(tp_lis))
|
||||
}
|
||||
ast::ConstExpr::Array(ConstArray::WithLength(arr)) => {
|
||||
ast::ConstExpr::List(ConstList::WithLength(lis)) => {
|
||||
let elem = self.instantiate_const_expr(
|
||||
&arr.elem,
|
||||
&lis.elem,
|
||||
erased_idx,
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?;
|
||||
let length = self.instantiate_const_expr(
|
||||
&arr.length,
|
||||
&lis.length,
|
||||
erased_idx,
|
||||
tmp_tv_cache,
|
||||
not_found_is_qvar,
|
||||
)?;
|
||||
if length.is_erased() {
|
||||
if let Ok(elem_t) = self.instantiate_tp_as_type(elem, arr) {
|
||||
return Ok(TyParam::t(unknown_len_array_t(elem_t)));
|
||||
if let Ok(elem_t) = self.instantiate_tp_as_type(elem, lis) {
|
||||
return Ok(TyParam::t(unknown_len_list_t(elem_t)));
|
||||
}
|
||||
}
|
||||
type_feature_error!(
|
||||
self,
|
||||
arr.loc(),
|
||||
lis.loc(),
|
||||
&format!("instantiating const expression {expr}")
|
||||
)
|
||||
}
|
||||
|
@ -1636,14 +1636,14 @@ impl Context {
|
|||
TyParam::Value(value) => self.convert_value_into_type(value).or_else(|value| {
|
||||
type_feature_error!(self, loc.loc(), &format!("instantiate `{value}` as type"))
|
||||
}),
|
||||
TyParam::Array(arr) => {
|
||||
let len = TyParam::value(arr.len());
|
||||
TyParam::List(lis) => {
|
||||
let len = TyParam::value(lis.len());
|
||||
let mut union = Type::Never;
|
||||
for tp in arr {
|
||||
for tp in lis {
|
||||
let t = self.instantiate_tp_as_type(tp, loc)?;
|
||||
union = self.union(&union, &t);
|
||||
}
|
||||
Ok(array_t(union, len))
|
||||
Ok(list_t(union, len))
|
||||
}
|
||||
TyParam::Set(set) => {
|
||||
let t = set
|
||||
|
@ -1962,20 +1962,20 @@ impl Context {
|
|||
mode,
|
||||
not_found_is_qvar,
|
||||
)?)),
|
||||
TypeSpec::Array(arr) => {
|
||||
TypeSpec::List(lis) => {
|
||||
let elem_t = self.instantiate_typespec_full(
|
||||
&arr.ty,
|
||||
&lis.ty,
|
||||
opt_decl_t,
|
||||
tmp_tv_cache,
|
||||
mode,
|
||||
not_found_is_qvar,
|
||||
)?;
|
||||
let mut len =
|
||||
self.instantiate_const_expr(&arr.len, None, tmp_tv_cache, not_found_is_qvar)?;
|
||||
self.instantiate_const_expr(&lis.len, None, tmp_tv_cache, not_found_is_qvar)?;
|
||||
if let TyParam::Erased(t) = &mut len {
|
||||
*t.as_mut() = Type::Nat;
|
||||
}
|
||||
Ok(array_t(elem_t, len))
|
||||
Ok(list_t(elem_t, len))
|
||||
}
|
||||
TypeSpec::SetWithLen(set) => {
|
||||
let elem_t = self.instantiate_typespec_full(
|
||||
|
|
|
@ -645,7 +645,7 @@ pub struct Context {
|
|||
pub(crate) mono_types: Dict<VarName, TypeContext>,
|
||||
// Implementation Contexts for Polymorphic Types
|
||||
// Vec<TyParam> are specialization parameters
|
||||
// e.g. {"Array": [(Array(Nat), ctx), (Array(Int), ctx), (Array(Str), ctx), (Array(Obj), ctx), (Array('T), ctx)], ...}
|
||||
// e.g. {"List": [(List(Nat), ctx), (List(Int), ctx), (List(Str), ctx), (List(Obj), ctx), (List('T), ctx)], ...}
|
||||
pub(crate) poly_types: Dict<VarName, TypeContext>,
|
||||
// patches can be accessed like normal records
|
||||
// but when used as a fallback to a type, values are traversed instead of accessing by keys
|
||||
|
|
|
@ -21,7 +21,7 @@ use erg_parser::ast::{self, ClassAttr, RecordAttrOrIdent, TypeSpecWithOp};
|
|||
|
||||
use crate::ty::constructors::{
|
||||
free_var, func, func0, func1, module, proc, py_module, ref_, ref_mut, str_dict_t, tp_enum,
|
||||
unknown_len_array_t, v_enum,
|
||||
unknown_len_list_t, v_enum,
|
||||
};
|
||||
use crate::ty::free::{Constraint, HasLevel};
|
||||
use crate::ty::typaram::TyParam;
|
||||
|
@ -397,7 +397,7 @@ impl Context {
|
|||
Err((ty, errs)) => (ty, errs),
|
||||
};
|
||||
let spec_t = match kind {
|
||||
ParamKind::VarParams => unknown_len_array_t(spec_t),
|
||||
ParamKind::VarParams => unknown_len_list_t(spec_t),
|
||||
ParamKind::KwVarParams => str_dict_t(spec_t),
|
||||
_ => spec_t,
|
||||
};
|
||||
|
@ -577,7 +577,7 @@ impl Context {
|
|||
}
|
||||
if let Some(var_params) = &mut params.var_params {
|
||||
if let Some(pt) = &subr_t.var_params {
|
||||
let pt = pt.clone().map_type(unknown_len_array_t);
|
||||
let pt = pt.clone().map_type(unknown_len_list_t);
|
||||
if let Err(es) =
|
||||
self.assign_param(var_params, Some(&pt), tmp_tv_cache, ParamKind::VarParams)
|
||||
{
|
||||
|
@ -2764,9 +2764,9 @@ impl Context {
|
|||
}
|
||||
res
|
||||
}
|
||||
ast::Expr::Array(ast::Array::Normal(arr)) => {
|
||||
ast::Expr::List(ast::List::Normal(lis)) => {
|
||||
let mut res = false;
|
||||
for val in arr.elems.pos_args().iter() {
|
||||
for val in lis.elems.pos_args().iter() {
|
||||
if self.inc_ref_expr(&val.expr, namespace, tmp_tv_cache) {
|
||||
res = true;
|
||||
}
|
||||
|
|
|
@ -525,7 +525,7 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
|
|||
self.sub_unify(sub, &r)?;
|
||||
Ok(())
|
||||
}
|
||||
(TyParam::Array(sub), TyParam::Array(sup))
|
||||
(TyParam::List(sub), TyParam::List(sup))
|
||||
| (TyParam::Tuple(sub), TyParam::Tuple(sup)) => {
|
||||
for (l, r) in sub.iter().zip(sup.iter()) {
|
||||
self.sub_unify_tp(l, r, _variance, allow_divergence)?;
|
||||
|
@ -1208,8 +1208,8 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
|
|||
};
|
||||
self.sub_unify(&sub, &new_sup)?;
|
||||
// ?T(:> Int, <: Int) ==> ?T == Int
|
||||
// ?T(:> Array(Int, 3), <: Array(?T, ?N)) ==> ?T == Array(Int, 3)
|
||||
// ?T(:> Array(Int, 3), <: Indexable(?K, ?V)) ==> ?T(:> Array(Int, 3), <: Indexable(0..2, Int))
|
||||
// ?T(:> List(Int, 3), <: List(?T, ?N)) ==> ?T == List(Int, 3)
|
||||
// ?T(:> List(Int, 3), <: Indexable(?K, ?V)) ==> ?T(:> List(Int, 3), <: Indexable(0..2, Int))
|
||||
if !sub.is_refinement()
|
||||
&& new_sup.qual_name() == sub.qual_name()
|
||||
&& !new_sup.is_unbound_var()
|
||||
|
@ -1384,7 +1384,7 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
|
|||
},
|
||||
) => {
|
||||
// e.g. Set(?T) <: Eq(Set(?T))
|
||||
// Array(Str) <: Iterable(Str)
|
||||
// List(Str) <: Iterable(Str)
|
||||
// Zip(T, U) <: Iterable(Tuple([T, U]))
|
||||
if ln != rn {
|
||||
self.nominal_sub_unify(maybe_sub, maybe_sup, rps)?;
|
||||
|
@ -1542,7 +1542,7 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
|
|||
(Subr(_) | Record(_), Type) => {}
|
||||
(Guard(_), Bool) | (Bool, Guard(_)) => {}
|
||||
// REVIEW: correct?
|
||||
(Poly { name, .. }, Type) if &name[..] == "Array" || &name[..] == "Tuple" => {}
|
||||
(Poly { name, .. }, Type) if &name[..] == "List" || &name[..] == "Tuple" => {}
|
||||
(Poly { .. }, _) => {
|
||||
if maybe_sub.has_no_qvar() && maybe_sup.has_no_qvar() {
|
||||
return Ok(());
|
||||
|
|
|
@ -12,7 +12,7 @@ use erg_parser::desugar::Desugarer;
|
|||
use crate::context::instantiate::TyVarCache;
|
||||
use crate::context::{ClassDefType, Context, MethodContext, MethodPair, TraitImpl};
|
||||
use crate::lower::GenericASTLowerer;
|
||||
use crate::ty::constructors::{array_t, mono, mono_q, mono_q_tp, poly, v_enum};
|
||||
use crate::ty::constructors::{list_t, mono, mono_q, mono_q_tp, poly, v_enum};
|
||||
use crate::ty::free::{Constraint, HasLevel};
|
||||
use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
|
||||
use crate::ty::{HasType, TyParam, Type, Visibility};
|
||||
|
@ -288,30 +288,30 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
Ok(hir::UnaryOp::new(unaryop.op, expr, VarInfo::default()))
|
||||
}
|
||||
|
||||
fn fake_lower_array(&self, arr: ast::Array) -> LowerResult<hir::Array> {
|
||||
fn fake_lower_list(&self, arr: ast::List) -> LowerResult<hir::List> {
|
||||
match arr {
|
||||
ast::Array::WithLength(arr) => {
|
||||
let len = self.fake_lower_expr(*arr.len)?;
|
||||
let elem = self.fake_lower_expr(arr.elem.expr)?;
|
||||
Ok(hir::Array::WithLength(hir::ArrayWithLength::new(
|
||||
arr.l_sqbr,
|
||||
arr.r_sqbr,
|
||||
ast::List::WithLength(lis) => {
|
||||
let len = self.fake_lower_expr(*lis.len)?;
|
||||
let elem = self.fake_lower_expr(lis.elem.expr)?;
|
||||
Ok(hir::List::WithLength(hir::ListWithLength::new(
|
||||
lis.l_sqbr,
|
||||
lis.r_sqbr,
|
||||
Type::Failure,
|
||||
elem,
|
||||
Some(len),
|
||||
)))
|
||||
}
|
||||
ast::Array::Normal(arr) => {
|
||||
ast::List::Normal(lis) => {
|
||||
let mut elems = Vec::new();
|
||||
let (elems_, ..) = arr.elems.deconstruct();
|
||||
let (elems_, ..) = lis.elems.deconstruct();
|
||||
for elem in elems_.into_iter() {
|
||||
let elem = self.fake_lower_expr(elem.expr)?;
|
||||
elems.push(hir::PosArg::new(elem));
|
||||
}
|
||||
let elems = hir::Args::new(elems, None, vec![], None, None);
|
||||
let t = array_t(Type::Failure, TyParam::value(elems.len()));
|
||||
Ok(hir::Array::Normal(hir::NormalArray::new(
|
||||
arr.l_sqbr, arr.r_sqbr, t, elems,
|
||||
let t = list_t(Type::Failure, TyParam::value(elems.len()));
|
||||
Ok(hir::List::Normal(hir::NormalList::new(
|
||||
lis.l_sqbr, lis.r_sqbr, t, elems,
|
||||
)))
|
||||
}
|
||||
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||
|
@ -612,7 +612,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
ast::Expr::Literal(lit) => Ok(hir::Expr::Literal(self.fake_lower_literal(lit)?)),
|
||||
ast::Expr::BinOp(binop) => Ok(hir::Expr::BinOp(self.fake_lower_binop(binop)?)),
|
||||
ast::Expr::UnaryOp(unop) => Ok(hir::Expr::UnaryOp(self.fake_lower_unaryop(unop)?)),
|
||||
ast::Expr::Array(arr) => Ok(hir::Expr::Array(self.fake_lower_array(arr)?)),
|
||||
ast::Expr::List(lis) => Ok(hir::Expr::List(self.fake_lower_list(lis)?)),
|
||||
ast::Expr::Tuple(tup) => Ok(hir::Expr::Tuple(self.fake_lower_tuple(tup)?)),
|
||||
ast::Expr::Record(rec) => Ok(hir::Expr::Record(self.fake_lower_record(rec)?)),
|
||||
ast::Expr::Set(set) => Ok(hir::Expr::Set(self.fake_lower_set(set)?)),
|
||||
|
|
|
@ -10,7 +10,7 @@ use erg_parser::token::TokenKind;
|
|||
|
||||
use crate::context::Context;
|
||||
use crate::error::{EffectError, EffectErrors};
|
||||
use crate::hir::{Array, Call, Def, Dict, Expr, Params, Set, Signature, Tuple, HIR};
|
||||
use crate::hir::{Call, Def, Dict, Expr, List, Params, Set, Signature, Tuple, HIR};
|
||||
use crate::ty::{HasType, Visibility};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -134,21 +134,21 @@ impl<'c> SideEffectChecker<'c> {
|
|||
self.check_expr(&unary.expr);
|
||||
}
|
||||
Expr::Accessor(_) | Expr::Literal(_) => {}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args.iter() {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args.iter() {
|
||||
self.check_expr(&elem.expr);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
self.check_expr(&arr.elem);
|
||||
if let Some(len) = &arr.len {
|
||||
List::WithLength(lis) => {
|
||||
self.check_expr(&lis.elem);
|
||||
if let Some(len) = &lis.len {
|
||||
self.check_expr(len);
|
||||
}
|
||||
}
|
||||
Array::Comprehension(arr) => {
|
||||
self.check_expr(&arr.elem);
|
||||
self.check_expr(&arr.guard);
|
||||
List::Comprehension(lis) => {
|
||||
self.check_expr(&lis.elem);
|
||||
self.check_expr(&lis.guard);
|
||||
}
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
|
@ -350,21 +350,21 @@ impl<'c> SideEffectChecker<'c> {
|
|||
self.check_expr(def);
|
||||
}
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args.iter() {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args.iter() {
|
||||
self.check_expr(&elem.expr);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
self.check_expr(&arr.elem);
|
||||
if let Some(len) = &arr.len {
|
||||
List::WithLength(lis) => {
|
||||
self.check_expr(&lis.elem);
|
||||
if let Some(len) = &lis.len {
|
||||
self.check_expr(len);
|
||||
}
|
||||
}
|
||||
Array::Comprehension(arr) => {
|
||||
self.check_expr(&arr.elem);
|
||||
self.check_expr(&arr.guard);
|
||||
List::Comprehension(lis) => {
|
||||
self.check_expr(&lis.elem);
|
||||
self.check_expr(&lis.guard);
|
||||
}
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
|
@ -538,15 +538,15 @@ impl<'c> SideEffectChecker<'c> {
|
|||
}
|
||||
Expr::BinOp(bin) => Self::is_impure(&bin.lhs) || Self::is_impure(&bin.rhs),
|
||||
Expr::UnaryOp(unary) => Self::is_impure(&unary.expr),
|
||||
Expr::Array(arr) => match arr {
|
||||
Array::Normal(arr) => arr
|
||||
Expr::List(lis) => match lis {
|
||||
List::Normal(lis) => lis
|
||||
.elems
|
||||
.pos_args
|
||||
.iter()
|
||||
.any(|elem| Self::is_impure(&elem.expr)),
|
||||
Array::WithLength(arr) => {
|
||||
Self::is_impure(&arr.elem)
|
||||
|| arr.len.as_ref().map_or(false, |len| Self::is_impure(len))
|
||||
List::WithLength(lis) => {
|
||||
Self::is_impure(&lis.elem)
|
||||
|| lis.len.as_ref().map_or(false, |len| Self::is_impure(len))
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
|
|
|
@ -744,7 +744,7 @@ impl Accessor {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ArrayWithLength {
|
||||
pub struct ListWithLength {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub t: Type,
|
||||
|
@ -752,7 +752,7 @@ pub struct ArrayWithLength {
|
|||
pub len: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ArrayWithLength {
|
||||
impl NestedDisplay for ListWithLength {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -764,7 +764,7 @@ impl NestedDisplay for ArrayWithLength {
|
|||
}
|
||||
}
|
||||
|
||||
impl NoTypeDisplay for ArrayWithLength {
|
||||
impl NoTypeDisplay for ListWithLength {
|
||||
fn to_string_notype(&self) -> String {
|
||||
format!(
|
||||
"[{}; {}]",
|
||||
|
@ -774,11 +774,11 @@ impl NoTypeDisplay for ArrayWithLength {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ArrayWithLength);
|
||||
impl_locational!(ArrayWithLength, l_sqbr, elem, r_sqbr);
|
||||
impl_t!(ArrayWithLength);
|
||||
impl_display_from_nested!(ListWithLength);
|
||||
impl_locational!(ListWithLength, l_sqbr, elem, r_sqbr);
|
||||
impl_t!(ListWithLength);
|
||||
|
||||
impl ArrayWithLength {
|
||||
impl ListWithLength {
|
||||
pub fn new(l_sqbr: Token, r_sqbr: Token, t: Type, elem: Expr, len: Option<Expr>) -> Self {
|
||||
Self {
|
||||
l_sqbr,
|
||||
|
@ -796,7 +796,7 @@ impl ArrayWithLength {
|
|||
|
||||
// TODO: generators
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ArrayComprehension {
|
||||
pub struct ListComprehension {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub t: Type,
|
||||
|
@ -804,13 +804,13 @@ pub struct ArrayComprehension {
|
|||
pub guard: Box<Expr>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ArrayComprehension {
|
||||
impl NestedDisplay for ListComprehension {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "[{} | {}](: {})", self.elem, self.guard, self.t)
|
||||
}
|
||||
}
|
||||
|
||||
impl NoTypeDisplay for ArrayComprehension {
|
||||
impl NoTypeDisplay for ListComprehension {
|
||||
fn to_string_notype(&self) -> String {
|
||||
format!(
|
||||
"[{} | {}]",
|
||||
|
@ -820,19 +820,19 @@ impl NoTypeDisplay for ArrayComprehension {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ArrayComprehension);
|
||||
impl_locational!(ArrayComprehension, l_sqbr, elem, r_sqbr);
|
||||
impl_t!(ArrayComprehension);
|
||||
impl_display_from_nested!(ListComprehension);
|
||||
impl_locational!(ListComprehension, l_sqbr, elem, r_sqbr);
|
||||
impl_t!(ListComprehension);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct NormalArray {
|
||||
pub struct NormalList {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub t: Type,
|
||||
pub elems: Args,
|
||||
}
|
||||
|
||||
impl NestedDisplay for NormalArray {
|
||||
impl NestedDisplay for NormalList {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
writeln!(f, "[")?;
|
||||
self.elems.fmt_nest(f, level + 1)?;
|
||||
|
@ -840,7 +840,7 @@ impl NestedDisplay for NormalArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl NoTypeDisplay for NormalArray {
|
||||
impl NoTypeDisplay for NormalList {
|
||||
fn to_string_notype(&self) -> String {
|
||||
format!(
|
||||
"[{}]",
|
||||
|
@ -854,11 +854,11 @@ impl NoTypeDisplay for NormalArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(NormalArray);
|
||||
impl_locational!(NormalArray, l_sqbr, elems, r_sqbr);
|
||||
impl_t!(NormalArray);
|
||||
impl_display_from_nested!(NormalList);
|
||||
impl_locational!(NormalList, l_sqbr, elems, r_sqbr);
|
||||
impl_t!(NormalList);
|
||||
|
||||
impl NormalArray {
|
||||
impl NormalList {
|
||||
pub fn new(l_sqbr: Token, r_sqbr: Token, t: Type, elems: Args) -> Self {
|
||||
Self {
|
||||
l_sqbr,
|
||||
|
@ -874,21 +874,21 @@ impl NormalArray {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Array {
|
||||
Normal(NormalArray),
|
||||
Comprehension(ArrayComprehension),
|
||||
WithLength(ArrayWithLength),
|
||||
pub enum List {
|
||||
Normal(NormalList),
|
||||
Comprehension(ListComprehension),
|
||||
WithLength(ListWithLength),
|
||||
}
|
||||
|
||||
impl_nested_display_for_enum!(Array; Normal, Comprehension, WithLength);
|
||||
impl_no_type_display_for_enum!(Array; Normal, Comprehension, WithLength);
|
||||
impl_display_for_enum!(Array; Normal, Comprehension, WithLength);
|
||||
impl_locational_for_enum!(Array; Normal, Comprehension, WithLength);
|
||||
impl_t_for_enum!(Array; Normal, Comprehension, WithLength);
|
||||
impl_nested_display_for_enum!(List; Normal, Comprehension, WithLength);
|
||||
impl_no_type_display_for_enum!(List; Normal, Comprehension, WithLength);
|
||||
impl_display_for_enum!(List; Normal, Comprehension, WithLength);
|
||||
impl_locational_for_enum!(List; Normal, Comprehension, WithLength);
|
||||
impl_t_for_enum!(List; Normal, Comprehension, WithLength);
|
||||
|
||||
impl Array {
|
||||
impl List {
|
||||
pub const fn is_unsized(&self) -> bool {
|
||||
matches!(self, Self::WithLength(arr) if arr.is_unsized())
|
||||
matches!(self, Self::WithLength(lis) if lis.is_unsized())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2733,7 +2733,7 @@ impl TypeAscription {
|
|||
pub enum Expr {
|
||||
Literal(Literal),
|
||||
Accessor(Accessor),
|
||||
Array(Array),
|
||||
List(List),
|
||||
Tuple(Tuple),
|
||||
Set(Set),
|
||||
Dict(Dict),
|
||||
|
@ -2753,13 +2753,13 @@ pub enum Expr {
|
|||
Dummy(Dummy), // for mapping to Python AST
|
||||
}
|
||||
|
||||
impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_no_type_display_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_no_type_display_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_display_from_nested!(Expr);
|
||||
impl_locational_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_t_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_from_trait_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Set, Dummy);
|
||||
impl_try_from_trait_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Set, Dummy);
|
||||
impl_locational_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_t_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Code, Compound, TypeAsc, Set, Import, Dummy);
|
||||
impl_from_trait_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Set, Dummy);
|
||||
impl_try_from_trait_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Record, BinOp, UnaryOp, Call, Lambda, Def, ClassDef, PatchDef, ReDef, Set, Dummy);
|
||||
|
||||
impl Default for Expr {
|
||||
fn default() -> Self {
|
||||
|
@ -2849,7 +2849,7 @@ impl Expr {
|
|||
match self {
|
||||
Self::Literal(_) => "literal",
|
||||
Self::Accessor(_) => "accessor",
|
||||
Self::Array(_) => "array",
|
||||
Self::List(_) => "array",
|
||||
Self::Tuple(_) => "tuple",
|
||||
Self::Dict(_) => "dict",
|
||||
Self::Set(_) => "set",
|
||||
|
@ -2945,9 +2945,9 @@ impl Expr {
|
|||
}
|
||||
sum
|
||||
}
|
||||
Self::Array(Array::Normal(arr)) => {
|
||||
Self::List(List::Normal(lis)) => {
|
||||
let mut sum = 0;
|
||||
for elem in arr.elems.pos_args.iter() {
|
||||
for elem in lis.elems.pos_args.iter() {
|
||||
sum += elem.expr.complexity();
|
||||
}
|
||||
sum
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# TODO: transition specifications
|
||||
array = pyimport "Array"
|
||||
array = pyimport "List"
|
||||
|
||||
.Array!: ClassType
|
||||
.Array! <: array.Array
|
||||
.Array!.
|
||||
.List!: ClassType
|
||||
.List! <: array.List
|
||||
.List!.
|
||||
'''
|
||||
Append object to the end of the list.
|
||||
'''
|
||||
|
@ -12,7 +12,7 @@ array = pyimport "Array"
|
|||
arr.push! 3
|
||||
assert arr == [1, 2, 3]
|
||||
'''
|
||||
push!: |T, N: Nat|(self: Array!(T, N), elem: T) => NoneType
|
||||
push!: |T, N: Nat|(self: List!(T, N), elem: T) => NoneType
|
||||
'''
|
||||
Extend the list by appending all the items from `iterable`.
|
||||
'''
|
||||
|
@ -21,7 +21,7 @@ array = pyimport "Array"
|
|||
arr.extend! [3, 4]
|
||||
assert arr == [1, 2, 3, 4]
|
||||
'''
|
||||
extend!: |T, N: Nat|(self: Array!(T, N), iterable: Iterable(T)) => NoneType
|
||||
extend!: |T, N: Nat|(self: List!(T, N), iterable: Iterable(T)) => NoneType
|
||||
'''
|
||||
Insert `elem` before `index`.
|
||||
'''
|
||||
|
@ -30,7 +30,7 @@ array = pyimport "Array"
|
|||
arr.insert! 0, 3
|
||||
assert arr == [3, 1, 2]
|
||||
'''
|
||||
insert!: |T, N: Nat|(self: Array!(T, N), index: Nat, elem: T) => NoneType
|
||||
insert!: |T, N: Nat|(self: List!(T, N), index: Nat, elem: T) => NoneType
|
||||
'''
|
||||
Remove the first item from the list whose value is `value`.
|
||||
'''
|
||||
|
@ -39,7 +39,7 @@ array = pyimport "Array"
|
|||
arr.remove! 1
|
||||
assert arr == [2]
|
||||
'''
|
||||
remove!: |T, N: Nat|(self: Array!(T, N), value: T) => NoneType
|
||||
remove!: |T, N: Nat|(self: List!(T, N), value: T) => NoneType
|
||||
'''
|
||||
Remove the item at the given position in the list, and return it.
|
||||
'''
|
||||
|
@ -49,7 +49,7 @@ array = pyimport "Array"
|
|||
assert arr == [1]
|
||||
assert i == 2
|
||||
'''
|
||||
pop!: |T, N: Nat|(self: Array!(T, N), index := Nat or {-1}) => T
|
||||
pop!: |T, N: Nat|(self: List!(T, N), index := Nat or {-1}) => T
|
||||
'''
|
||||
Remove all items from the list.
|
||||
'''
|
||||
|
@ -58,7 +58,7 @@ array = pyimport "Array"
|
|||
arr.clear!()
|
||||
assert arr == []
|
||||
'''
|
||||
clear!: |T, N: Nat|(self: Array!(T, N)) => NoneType
|
||||
clear!: |T, N: Nat|(self: List!(T, N)) => NoneType
|
||||
'''
|
||||
Sort the list in ascending order and return `None`.
|
||||
|
||||
|
@ -75,7 +75,7 @@ array = pyimport "Array"
|
|||
arr.sort!()
|
||||
assert arr == [1, 2, 3]
|
||||
'''
|
||||
sort!: |T, N: Nat|(self: Array!(T, N)) => NoneType
|
||||
sort!: |T, N: Nat|(self: List!(T, N)) => NoneType
|
||||
'''
|
||||
Reverse the elements of the list in-place and return `None`.
|
||||
'''
|
||||
|
@ -84,7 +84,7 @@ array = pyimport "Array"
|
|||
arr.reverse!()
|
||||
assert arr == [2, 1, 3]
|
||||
'''
|
||||
reverse!: |T, N: Nat|(self: Array!(T, N)) => NoneType
|
||||
reverse!: |T, N: Nat|(self: List!(T, N)) => NoneType
|
||||
'''
|
||||
Update each element of the array according to the passed function `f`.
|
||||
'''
|
||||
|
@ -93,7 +93,7 @@ array = pyimport "Array"
|
|||
arr.strict_map! x -> x + 1
|
||||
assert arr == [3, 4]
|
||||
'''
|
||||
strict_map!: |T, N: Nat|(self: Array!(T, N), f: T -> T) => NoneType
|
||||
strict_map!: |T, N: Nat|(self: List!(T, N), f: T -> T) => NoneType
|
||||
'''
|
||||
Update `index`-th element of the array according to the passed function `f`.
|
||||
'''
|
||||
|
@ -102,7 +102,7 @@ array = pyimport "Array"
|
|||
arr.udpate_nth! 0, x -> x + 1
|
||||
assert arr == [2, 2]
|
||||
'''
|
||||
update_nth!: |T, N: Nat|(self: Array!(T, N), index: Nat, f: T -> T) => NoneType
|
||||
update_nth!: |T, N: Nat|(self: List!(T, N), index: Nat, f: T -> T) => NoneType
|
||||
'''
|
||||
Return a (deep) copy of the array.
|
||||
'''
|
||||
|
@ -113,4 +113,4 @@ array = pyimport "Array"
|
|||
assert arr_copy == [1, 2, 3]
|
||||
assert arr == [1, 2]
|
||||
'''
|
||||
copy: |T, N: Nat|(self: Ref(Array!(T, N))) => Array!(T, N)
|
||||
copy: |T, N: Nat|(self: Ref(List!(T, N))) => List!(T, N)
|
|
@ -1,12 +1,12 @@
|
|||
.Array: ClassType
|
||||
.Array.
|
||||
.List: ClassType
|
||||
.List.
|
||||
'''
|
||||
Concatenates two arrays. Same as `self + other`.
|
||||
'''
|
||||
'''erg
|
||||
assert [1, 2].concat([3, 4]) == [1, 2, 3, 4]
|
||||
'''
|
||||
concat: |T: Type, M: Nat, N: Nat|(self: Array(T, M), other: Array(T, N)) -> Array(T, M + N)
|
||||
concat: |T: Type, M: Nat, N: Nat|(self: List(T, M), other: List(T, N)) -> List(T, M + N)
|
||||
'''
|
||||
Returns the number of elements in the array.
|
||||
'''
|
||||
|
@ -14,7 +14,7 @@
|
|||
assert [1, 2, 3, 1, 2].count(1) == 2
|
||||
assert ["a", "b", "c"].count("a") == 1
|
||||
'''
|
||||
count: |T: Type, N: Nat|(self: Array(T, N), x: T) -> Nat
|
||||
count: |T: Type, N: Nat|(self: List(T, N), x: T) -> Nat
|
||||
'''
|
||||
Remove array duplicates.
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
|||
assert [1, 1, 2].dedup() == [1, 2]
|
||||
assert [0.0, 0.1, 10.0, 20.0, 20.1].dedup((lhs, rhs) -> abs(lhs - rhs) < 1.0) == [0.1, 10.0, 20.1]
|
||||
'''
|
||||
dedup: |T: Type|(self: Array(T, _), same_bucket := (T, T) -> Bool) -> Array(T, _)
|
||||
dedup: |T: Type|(self: List(T, _), same_bucket := (T, T) -> Bool) -> List(T, _)
|
||||
'''
|
||||
Create two arrays according to the `predicate` function.
|
||||
|
||||
|
@ -34,25 +34,25 @@
|
|||
'''erg
|
||||
assert [-2, -1, 0, 1, 2].partition(x -> x >= 0) == ([0, 1, 2], [-2, -1])
|
||||
'''
|
||||
partition: |T: Type|(self: Array(T, _), predicate: T -> Bool) -> (Array(T, _), Array(T, _))
|
||||
partition: |T: Type|(self: List(T, _), predicate: T -> Bool) -> (List(T, _), List(T, _))
|
||||
'''
|
||||
Returns the summation of all elements in the array.
|
||||
'''
|
||||
'''erg
|
||||
assert [1, 2, 3].sum() == 6
|
||||
'''
|
||||
sum: |T: Type|(self: Array(T, _), start := T) -> T
|
||||
sum: |T: Type|(self: List(T, _), start := T) -> T
|
||||
'''
|
||||
Returns the product of all elements in the array.
|
||||
'''
|
||||
'''erg
|
||||
assert [1, 2, 3].product() == 6
|
||||
'''
|
||||
prod: |T: Type|(self: Array(T, _), start := T) -> T
|
||||
prod: |T: Type|(self: List(T, _), start := T) -> T
|
||||
'''
|
||||
Returns the reversed array.
|
||||
'''
|
||||
'''erg
|
||||
assert [1, 2, 3].reversed() == [3, 2, 1]
|
||||
'''
|
||||
reversed: |T: Type, N: Nat|(self: Array(T, N)) -> Array(T, N)
|
||||
reversed: |T: Type, N: Nat|(self: List(T, N)) -> List(T, N)
|
|
@ -60,9 +60,9 @@ def contains_operator(y, elem) -> bool:
|
|||
len_check = True # It can be True even if either elem or y has the larger number of elems
|
||||
return type_check and len_check
|
||||
elif _isinstance(elem, list):
|
||||
from _erg_array import Array
|
||||
from _erg_list import List
|
||||
|
||||
return contains_operator(y, Array(elem))
|
||||
return contains_operator(y, List(elem))
|
||||
elif callable(elem):
|
||||
# TODO:
|
||||
return callable(y)
|
||||
|
|
|
@ -8,21 +8,21 @@ from _erg_result import is_ok
|
|||
from _erg_type import UnionType
|
||||
|
||||
|
||||
class Array(list):
|
||||
class List(list):
|
||||
@staticmethod
|
||||
def try_new(arr): # -> Result[Array]
|
||||
if isinstance(arr, list):
|
||||
return Array(arr)
|
||||
def try_new(lis): # -> Result[List]
|
||||
if isinstance(lis, list):
|
||||
return List(lis)
|
||||
else:
|
||||
return Error("not a list")
|
||||
|
||||
def generic_try_new(arr, cls=None): # -> Result[Array]
|
||||
def generic_try_new(lis, cls=None): # -> Result[List]
|
||||
if cls is None:
|
||||
return Array.try_new(arr)
|
||||
return List.try_new(lis)
|
||||
else:
|
||||
elem_t = cls.__args__[0]
|
||||
elems = []
|
||||
for elem in arr:
|
||||
for elem in lis:
|
||||
if not hasattr(elem_t, "try_new"):
|
||||
return Error("not a " + str(elem_t))
|
||||
# TODO: nested check
|
||||
|
@ -31,11 +31,11 @@ class Array(list):
|
|||
elems.append(elem)
|
||||
else:
|
||||
return Error("not a " + str(elem_t))
|
||||
return Array(elems)
|
||||
return List(elems)
|
||||
|
||||
def dedup(self, same_bucket=None):
|
||||
if same_bucket is None:
|
||||
return Array(list(set(self)))
|
||||
return List(list(set(self)))
|
||||
else:
|
||||
removes = []
|
||||
for lhs, rhs in zip(self, self[1:]):
|
||||
|
@ -56,20 +56,20 @@ class Array(list):
|
|||
return self
|
||||
|
||||
def partition(self, f):
|
||||
return Array(list(filter(f, self))), Array(
|
||||
return List(list(filter(f, self))), List(
|
||||
list(filter(lambda x: not f(x), self))
|
||||
)
|
||||
|
||||
def __mul__(self, n):
|
||||
return then__(list.__mul__(self, n), Array)
|
||||
return then__(list.__mul__(self, n), List)
|
||||
|
||||
def __getitem__(self, index_or_slice):
|
||||
if isinstance(index_or_slice, slice):
|
||||
return Array(list.__getitem__(self, index_or_slice))
|
||||
return List(list.__getitem__(self, index_or_slice))
|
||||
elif isinstance(index_or_slice, NatMut) or isinstance(index_or_slice, IntMut):
|
||||
return list.__getitem__(self, int(index_or_slice))
|
||||
elif isinstance(index_or_slice, Range):
|
||||
return Array(list.__getitem__(self, index_or_slice.into_slice()))
|
||||
return List(list.__getitem__(self, index_or_slice.into_slice()))
|
||||
else:
|
||||
return list.__getitem__(self, index_or_slice)
|
||||
|
||||
|
@ -77,7 +77,7 @@ class Array(list):
|
|||
return hash(tuple(self))
|
||||
|
||||
def update(self, f):
|
||||
self = Array(f(self))
|
||||
self = List(f(self))
|
||||
|
||||
def type_check(self, t: type) -> bool:
|
||||
if isinstance(t, list):
|
||||
|
@ -114,7 +114,7 @@ class Array(list):
|
|||
return reduce(lambda x, y: x * y, self, start)
|
||||
|
||||
def reversed(self):
|
||||
return Array(list.__reversed__(self))
|
||||
return List(list.__reversed__(self))
|
||||
|
||||
def insert_at(self, index, value):
|
||||
self.insert(index, value)
|
||||
|
@ -135,10 +135,10 @@ class Array(list):
|
|||
new = []
|
||||
for _ in range(n):
|
||||
new.extend(deepcopy(self))
|
||||
return Array(new)
|
||||
return List(new)
|
||||
|
||||
|
||||
class UnsizedArray:
|
||||
class UnsizedList:
|
||||
elem: object
|
||||
|
||||
def __init__(self, elem):
|
|
@ -1,5 +1,5 @@
|
|||
# HACK: import MutType to suppress segfault in CPython 3.10 (cause unknown)
|
||||
from _erg_array import Array, UnsizedArray
|
||||
from _erg_list import List, UnsizedList
|
||||
from _erg_bool import Bool
|
||||
from _erg_bytes import Bytes
|
||||
from _erg_contains_operator import contains_operator
|
||||
|
|
|
@ -206,13 +206,13 @@ opened in a binary mode.
|
|||
) => File!
|
||||
|
||||
'''
|
||||
Convert `iterable` into an array.
|
||||
Convert `iterable` into a list.
|
||||
'''
|
||||
'''erg
|
||||
assert array() == []
|
||||
assert array((1, 2)) == [1, 2]
|
||||
assert list() == []
|
||||
assert list((1, 2)) == [1, 2]
|
||||
'''
|
||||
.array: |T| (iterable := Iterable(T)) -> [T; _]
|
||||
.list: |T| (iterable := Iterable(T)) -> [T; _]
|
||||
|
||||
'''
|
||||
Convert `iterable` into a dict.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.heappush!: |T: Type|(heap: Iterable(T), item: T) => NoneType # TODO: Push!
|
||||
.heappop!: |T: Type|(heap: Iterable(T)) => T # TODO: Pop!
|
||||
.heappushpop!: |T: Type|(heap: Iterable(T), item: T) => T # TODO: Push! and Pop!
|
||||
.heapify!: (heap: Array(Obj, _)) => NoneType
|
||||
.heapify!: (heap: List(Obj, _)) => NoneType
|
||||
|
|
|
@ -56,7 +56,7 @@ io = pyimport "io"
|
|||
.seed_bits = Nat;
|
||||
.cutoff = Int;
|
||||
}
|
||||
.path: Array!(Str, _)
|
||||
.path: List!(Str, _)
|
||||
'''
|
||||
* AIX -> 'aix'
|
||||
* FreeBSD -> 'freebsd'
|
||||
|
|
|
@ -121,15 +121,15 @@ impl<'a> HIRLinker<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args.iter_mut() {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args.iter_mut() {
|
||||
Self::resolve_pymod_path(&mut elem.expr);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
Self::resolve_pymod_path(&mut arr.elem);
|
||||
if let Some(len) = arr.len.as_deref_mut() {
|
||||
List::WithLength(lis) => {
|
||||
Self::resolve_pymod_path(&mut lis.elem);
|
||||
if let Some(len) = lis.len.as_deref_mut() {
|
||||
Self::resolve_pymod_path(len);
|
||||
}
|
||||
}
|
||||
|
@ -245,15 +245,15 @@ impl<'a> HIRLinker<'a> {
|
|||
},
|
||||
}
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args.iter_mut() {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args.iter_mut() {
|
||||
self.replace_import(&mut elem.expr);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
self.replace_import(&mut arr.elem);
|
||||
if let Some(len) = arr.len.as_deref_mut() {
|
||||
List::WithLength(lis) => {
|
||||
self.replace_import(&mut lis.elem);
|
||||
if let Some(len) = lis.len.as_deref_mut() {
|
||||
self.replace_import(len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ use crate::artifact::{BuildRunnable, Buildable, CompleteArtifact, IncompleteArti
|
|||
use crate::build_package::CheckStatus;
|
||||
use crate::module::SharedCompilerResource;
|
||||
use crate::ty::constructors::{
|
||||
array_t, free_var, func, guard, mono, poly, proc, refinement, set_t, singleton, ty_tp,
|
||||
unsized_array_t, v_enum,
|
||||
free_var, func, guard, list_t, mono, poly, proc, refinement, set_t, singleton, ty_tp,
|
||||
unsized_list_t, v_enum,
|
||||
};
|
||||
use crate::ty::free::Constraint;
|
||||
use crate::ty::typaram::TyParam;
|
||||
|
@ -335,21 +335,19 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
Ok(lit)
|
||||
}
|
||||
|
||||
fn lower_array(&mut self, array: ast::Array, expect: Option<&Type>) -> LowerResult<hir::Array> {
|
||||
log!(info "entered {}({array})", fn_name!());
|
||||
match array {
|
||||
ast::Array::Normal(arr) => {
|
||||
Ok(hir::Array::Normal(self.lower_normal_array(arr, expect)?))
|
||||
}
|
||||
ast::Array::WithLength(arr) => Ok(hir::Array::WithLength(
|
||||
self.lower_array_with_length(arr, expect)?,
|
||||
fn lower_list(&mut self, list: ast::List, expect: Option<&Type>) -> LowerResult<hir::List> {
|
||||
log!(info "entered {}({list})", fn_name!());
|
||||
match list {
|
||||
ast::List::Normal(lis) => Ok(hir::List::Normal(self.lower_normal_list(lis, expect)?)),
|
||||
ast::List::WithLength(lis) => Ok(hir::List::WithLength(
|
||||
self.lower_list_with_length(lis, expect)?,
|
||||
)),
|
||||
other => feature_error!(
|
||||
LowerErrors,
|
||||
LowerError,
|
||||
self.module.context,
|
||||
other.loc(),
|
||||
"array comprehension"
|
||||
"list comprehension"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -364,10 +362,10 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
elem.loc(),
|
||||
String::from(&self.module.context.name[..]),
|
||||
switch_lang!(
|
||||
"japanese" => "配列の要素は全て同じ型である必要があります",
|
||||
"japanese" => "リストの要素は全て同じ型である必要があります",
|
||||
"simplified_chinese" => "数组元素必须全部是相同类型",
|
||||
"traditional_chinese" => "數組元素必須全部是相同類型",
|
||||
"english" => "all elements of an array must be of the same type",
|
||||
"english" => "all elements of a list must be of the same type",
|
||||
)
|
||||
.to_owned(),
|
||||
Some(switch_lang!(
|
||||
|
@ -379,18 +377,18 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
))
|
||||
}
|
||||
|
||||
fn lower_normal_array(
|
||||
fn lower_normal_list(
|
||||
&mut self,
|
||||
array: ast::NormalArray,
|
||||
list: ast::NormalList,
|
||||
expect: Option<&Type>,
|
||||
) -> LowerResult<hir::NormalArray> {
|
||||
log!(info "entered {}({array})", fn_name!());
|
||||
let mut new_array = vec![];
|
||||
let eval_result = self.module.context.eval_const_normal_array(&array);
|
||||
let (elems, ..) = array.elems.deconstruct();
|
||||
) -> LowerResult<hir::NormalList> {
|
||||
log!(info "entered {}({list})", fn_name!());
|
||||
let mut new_list = vec![];
|
||||
let eval_result = self.module.context.eval_const_normal_list(&list);
|
||||
let (elems, ..) = list.elems.deconstruct();
|
||||
let expect_elem = expect.and_then(|t| {
|
||||
// REVIEW: are these all?
|
||||
if !(t.is_array() || t.is_array_mut() || t.is_iterable()) {
|
||||
if !(t.is_list() || t.is_list_mut() || t.is_iterable()) {
|
||||
return None;
|
||||
}
|
||||
self.module
|
||||
|
@ -404,7 +402,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
let union_ = self.module.context.union(&union, elem.ref_t());
|
||||
self.homogeneity_check(expect_elem.as_ref(), &union_, &union, &elem)?;
|
||||
union = union_;
|
||||
new_array.push(elem);
|
||||
new_list.push(elem);
|
||||
}
|
||||
let elem_t = if union == Type::Never {
|
||||
free_var(
|
||||
|
@ -414,14 +412,14 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
} else {
|
||||
union
|
||||
};
|
||||
let elems = hir::Args::values(new_array, None);
|
||||
let t = array_t(elem_t, TyParam::value(elems.len()));
|
||||
let elems = hir::Args::values(new_list, None);
|
||||
let t = list_t(elem_t, TyParam::value(elems.len()));
|
||||
let t = if let Ok(value) = eval_result {
|
||||
singleton(t, TyParam::Value(value))
|
||||
} else {
|
||||
t
|
||||
};
|
||||
Ok(hir::NormalArray::new(array.l_sqbr, array.r_sqbr, t, elems))
|
||||
Ok(hir::NormalList::new(list.l_sqbr, list.r_sqbr, t, elems))
|
||||
}
|
||||
|
||||
fn homogeneity_check(
|
||||
|
@ -466,14 +464,14 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn lower_array_with_length(
|
||||
fn lower_list_with_length(
|
||||
&mut self,
|
||||
array: ast::ArrayWithLength,
|
||||
list: ast::ListWithLength,
|
||||
expect: Option<&Type>,
|
||||
) -> LowerResult<hir::ArrayWithLength> {
|
||||
log!(info "entered {}({array})", fn_name!());
|
||||
) -> LowerResult<hir::ListWithLength> {
|
||||
log!(info "entered {}({list})", fn_name!());
|
||||
let expect_elem = expect.and_then(|t| {
|
||||
if !(t.is_array() || t.is_array_mut() || t.is_iterable()) {
|
||||
if !(t.is_list() || t.is_list_mut() || t.is_iterable()) {
|
||||
return None;
|
||||
}
|
||||
self.module
|
||||
|
@ -481,26 +479,26 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
.convert_tp_into_type(t.typarams().first()?.clone())
|
||||
.ok()
|
||||
});
|
||||
let elem = self.lower_expr(array.elem.expr, expect_elem.as_ref())?;
|
||||
let array_t = self.gen_array_with_length_type(&elem, &array.len);
|
||||
let len = match *array.len {
|
||||
let elem = self.lower_expr(list.elem.expr, expect_elem.as_ref())?;
|
||||
let list_t = self.gen_list_with_length_type(&elem, &list.len);
|
||||
let len = match *list.len {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) if ident.is_discarded() => None,
|
||||
len => Some(self.lower_expr(len, Some(&Type::Nat))?),
|
||||
};
|
||||
let hir_array = hir::ArrayWithLength::new(array.l_sqbr, array.r_sqbr, array_t, elem, len);
|
||||
Ok(hir_array)
|
||||
let hir_list = hir::ListWithLength::new(list.l_sqbr, list.r_sqbr, list_t, elem, len);
|
||||
Ok(hir_list)
|
||||
}
|
||||
|
||||
fn gen_array_with_length_type(&self, elem: &hir::Expr, len: &ast::Expr) -> Type {
|
||||
fn gen_list_with_length_type(&self, elem: &hir::Expr, len: &ast::Expr) -> Type {
|
||||
match len {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) if ident.is_discarded() => {
|
||||
return unsized_array_t(elem.t());
|
||||
return unsized_list_t(elem.t());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let maybe_len = self.module.context.eval_const_expr(len);
|
||||
match maybe_len {
|
||||
Ok(v @ ValueObj::Nat(_)) => array_t(elem.t(), TyParam::Value(v)),
|
||||
Ok(v @ ValueObj::Nat(_)) => list_t(elem.t(), TyParam::Value(v)),
|
||||
Ok(other) => todo!("{other} is not a Nat object"),
|
||||
Err(err) => todo!("{err}"),
|
||||
}
|
||||
|
@ -2947,7 +2945,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
|
|||
let casted = self.module.context.get_casted_type(&expr);
|
||||
let mut expr = match expr {
|
||||
ast::Expr::Literal(lit) => hir::Expr::Literal(self.lower_literal(lit, expect)?),
|
||||
ast::Expr::Array(arr) => hir::Expr::Array(self.lower_array(arr, expect)?),
|
||||
ast::Expr::List(lis) => hir::Expr::List(self.lower_list(lis, expect)?),
|
||||
ast::Expr::Tuple(tup) => hir::Expr::Tuple(self.lower_tuple(tup, expect)?),
|
||||
ast::Expr::Record(rec) => hir::Expr::Record(self.lower_record(rec, expect)?),
|
||||
ast::Expr::Set(set) => hir::Expr::Set(self.lower_set(set, expect)?),
|
||||
|
|
|
@ -13,7 +13,7 @@ use erg_parser::ast::{ParamPattern, VarName};
|
|||
use crate::ty::{HasType, Ownership, Visibility};
|
||||
|
||||
use crate::error::{OwnershipError, OwnershipErrors};
|
||||
use crate::hir::{self, Accessor, Array, Block, Def, Expr, Identifier, Signature, Tuple, HIR};
|
||||
use crate::hir::{self, Accessor, Block, Def, Expr, Identifier, List, Signature, Tuple, HIR};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum WrapperKind {
|
||||
|
@ -222,23 +222,23 @@ impl OwnershipChecker {
|
|||
Expr::UnaryOp(unary) => {
|
||||
self.check_expr(&unary.expr, ownership, false);
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
for a in arr.elems.pos_args.iter() {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
for a in lis.elems.pos_args.iter() {
|
||||
self.check_expr(&a.expr, ownership, false);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
self.check_expr(&arr.elem, ownership, false);
|
||||
if let Some(len) = &arr.len {
|
||||
List::WithLength(lis) => {
|
||||
self.check_expr(&lis.elem, ownership, false);
|
||||
if let Some(len) = &lis.len {
|
||||
self.check_expr(len, ownership, false);
|
||||
}
|
||||
}
|
||||
_ => todo!(),
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
Tuple::Normal(arr) => {
|
||||
for a in arr.elems.pos_args.iter() {
|
||||
Tuple::Normal(lis) => {
|
||||
for a in lis.elems.pos_args.iter() {
|
||||
self.check_expr(&a.expr, ownership, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,4 +40,4 @@ val!() =
|
|||
val = val!()
|
||||
|
||||
xs as [Nat or Str; _] = [1, 2, "aa"]
|
||||
ys = array filter x -> x in Int, xs
|
||||
ys = list filter x -> x in Int, xs
|
||||
|
|
|
@ -12,8 +12,8 @@ use erg_compiler::error::CompileErrors;
|
|||
use erg_compiler::lower::ASTLowerer;
|
||||
|
||||
use erg_compiler::ty::constructors::{
|
||||
array_t, func0, func1, func2, kw, mono, nd_func, nd_proc, or, poly, proc1, subtype_q, ty_tp,
|
||||
type_q, unknown_len_array_mut, unknown_len_array_t, v_enum,
|
||||
func0, func1, func2, kw, list_t, mono, nd_func, nd_proc, or, poly, proc1, subtype_q, ty_tp,
|
||||
type_q, unknown_len_list_mut, unknown_len_list_t, v_enum,
|
||||
};
|
||||
use erg_compiler::ty::Type::*;
|
||||
|
||||
|
@ -71,15 +71,15 @@ fn _test_infer_types() -> Result<(), ()> {
|
|||
module.context.assert_var_type("abs2", &abs_t)?;
|
||||
let norm_t = func1(mono("<module>::Norm"), Nat);
|
||||
module.context.assert_var_type("norm", &norm_t)?;
|
||||
let a_t = array_t(
|
||||
let a_t = list_t(
|
||||
v_enum(set! {1.into(), 2.into(), 3.into(), 4.into()}),
|
||||
4.into(),
|
||||
);
|
||||
module.context.assert_var_type("a", &a_t)?;
|
||||
let abc_t = unknown_len_array_t(v_enum(set! {"a".into(), "b".into(), "c".into()}));
|
||||
let abc_t = unknown_len_list_t(v_enum(set! {"a".into(), "b".into(), "c".into()}));
|
||||
module.context.assert_var_type("abc", &abc_t)?;
|
||||
let t = type_q("T");
|
||||
let f_t = proc1(t.clone(), unknown_len_array_mut(t)).quantify();
|
||||
let f_t = proc1(t.clone(), unknown_len_list_mut(t)).quantify();
|
||||
module.context.assert_var_type("f!", &f_t)?;
|
||||
let r = type_q("R");
|
||||
let add_r = poly("Add", vec![ty_tp(r.clone())]);
|
||||
|
@ -92,7 +92,7 @@ fn _test_infer_types() -> Result<(), ()> {
|
|||
.assert_var_type("val", &v_enum(set! { "b".into(), "d".into() }))?;
|
||||
module
|
||||
.context
|
||||
.assert_var_type("ys", &unknown_len_array_t(Nat))?;
|
||||
.assert_var_type("ys", &unknown_len_list_t(Nat))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::context::{Context, ContextProvider, ModuleContext};
|
|||
use crate::desugar_hir::HIRDesugarer;
|
||||
use crate::error::{CompileError, CompileErrors, CompileResult};
|
||||
use crate::hir::{
|
||||
Accessor, Args, Array, BinOp, Block, Call, ClassDef, Def, Dict, Expr, Identifier, Lambda,
|
||||
Accessor, Args, BinOp, Block, Call, ClassDef, Def, Dict, Expr, Identifier, Lambda, List,
|
||||
Literal, Params, PatchDef, ReDef, Record, Set, Signature, Tuple, UnaryOp, HIR,
|
||||
};
|
||||
use crate::link_hir::HIRLinker;
|
||||
|
@ -476,7 +476,7 @@ impl PyScriptGenerator {
|
|||
.replace("from _erg_str import Str", "")
|
||||
.replace("from _erg_float import FloatMut", "")
|
||||
.replace("from _erg_float import Float", "")
|
||||
.replace("from _erg_array import Array", "")
|
||||
.replace("from _erg_list import List", "")
|
||||
.replace("from _erg_range import Range", "")
|
||||
.replace("from _erg_result import Error", "")
|
||||
.replace("from _erg_result import is_ok", "")
|
||||
|
@ -531,7 +531,7 @@ impl PyScriptGenerator {
|
|||
self.load_contains_op_if_not();
|
||||
if self.range_ops_loaded {
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_float.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_array.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_list.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_dict.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_set.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_bytes.py"));
|
||||
|
@ -541,7 +541,7 @@ impl PyScriptGenerator {
|
|||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_bool.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_str.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_float.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_array.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_list.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_dict.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_set.py"));
|
||||
self.prelude += &Self::replace_import(include_str!("lib/core/_erg_bytes.py"));
|
||||
|
@ -578,11 +578,11 @@ impl PyScriptGenerator {
|
|||
Expr::Call(call) => self.transpile_call(call),
|
||||
Expr::BinOp(bin) => self.transpile_binop(bin),
|
||||
Expr::UnaryOp(unary) => self.transpile_unaryop(unary),
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
self.load_builtin_types_if_not();
|
||||
let mut code = "Array([".to_string();
|
||||
for elem in arr.elems.pos_args {
|
||||
let mut code = "List([".to_string();
|
||||
for elem in lis.elems.pos_args {
|
||||
code += &format!("{},", self.transpile_expr(elem.expr));
|
||||
}
|
||||
code += "])";
|
||||
|
@ -762,7 +762,7 @@ impl PyScriptGenerator {
|
|||
prefix.push('(');
|
||||
}
|
||||
other => {
|
||||
if let t @ ("Bytes" | "Array" | "Dict" | "Set") = &other.qual_name()[..] {
|
||||
if let t @ ("Bytes" | "List" | "Dict" | "Set") = &other.qual_name()[..] {
|
||||
self.load_builtin_types_if_not();
|
||||
prefix.push_str(t);
|
||||
prefix.push('(');
|
||||
|
@ -773,9 +773,9 @@ impl PyScriptGenerator {
|
|||
match acc {
|
||||
Accessor::Ident(ident) => {
|
||||
match &ident.inspect()[..] {
|
||||
"Str" | "Bytes" | "Bool" | "Nat" | "Int" | "Float" | "Array" | "Dict"
|
||||
"Str" | "Bytes" | "Bool" | "Nat" | "Int" | "Float" | "List" | "Dict"
|
||||
| "Set" | "Str!" | "Bytes!" | "Bool!" | "Nat!" | "Int!" | "Float!"
|
||||
| "Array!" => {
|
||||
| "List!" => {
|
||||
self.load_builtin_types_if_not();
|
||||
}
|
||||
"if" | "if!" | "for!" | "while" | "discard" => {
|
||||
|
@ -1288,24 +1288,24 @@ impl JsonGenerator {
|
|||
|
||||
fn expr_into_value(&self, expr: Expr) -> Option<ValueObj> {
|
||||
match expr {
|
||||
Expr::Array(Array::Normal(arr)) => {
|
||||
Expr::List(List::Normal(lis)) => {
|
||||
let mut vals = vec![];
|
||||
for elem in arr.elems.pos_args {
|
||||
for elem in lis.elems.pos_args {
|
||||
if let Some(val) = self.expr_into_value(elem.expr) {
|
||||
vals.push(val);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(ValueObj::Array(vals.into()))
|
||||
Some(ValueObj::List(vals.into()))
|
||||
}
|
||||
Expr::Array(Array::WithLength(arr)) => {
|
||||
let len = arr
|
||||
Expr::List(List::WithLength(lis)) => {
|
||||
let len = lis
|
||||
.len
|
||||
.and_then(|len| self.expr_into_value(*len))
|
||||
.and_then(|v| usize::try_from(&v).ok())?;
|
||||
let vals = vec![self.expr_into_value(*arr.elem)?; len];
|
||||
Some(ValueObj::Array(vals.into()))
|
||||
let vals = vec![self.expr_into_value(*lis.elem)?; len];
|
||||
Some(ValueObj::List(vals.into()))
|
||||
}
|
||||
Expr::Tuple(Tuple::Normal(tup)) => {
|
||||
let mut vals = vec![];
|
||||
|
@ -1379,10 +1379,10 @@ impl JsonGenerator {
|
|||
replace_non_symbolic(&acc.to_string())
|
||||
}
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
let mut code = "[".to_string();
|
||||
for (i, elem) in arr.elems.pos_args.into_iter().enumerate() {
|
||||
for (i, elem) in lis.elems.pos_args.into_iter().enumerate() {
|
||||
if i > 0 {
|
||||
code += ", ";
|
||||
}
|
||||
|
|
|
@ -44,36 +44,36 @@ pub fn named_uninit_var(name: Str) -> Type {
|
|||
Type::FreeVar(Free::new_named_unbound(name, 1, Constraint::Uninited))
|
||||
}
|
||||
|
||||
pub fn array_t(elem_t: Type, len: TyParam) -> Type {
|
||||
poly("Array", vec![TyParam::t(elem_t), len])
|
||||
pub fn list_t(elem_t: Type, len: TyParam) -> Type {
|
||||
poly("List", vec![TyParam::t(elem_t), len])
|
||||
}
|
||||
|
||||
pub fn array_mut(elem_t: Type, len: TyParam) -> Type {
|
||||
poly("Array!", vec![TyParam::t(elem_t), len])
|
||||
pub fn list_mut(elem_t: Type, len: TyParam) -> Type {
|
||||
poly("List!", vec![TyParam::t(elem_t), len])
|
||||
}
|
||||
|
||||
pub fn unknown_len_array_t(elem_t: Type) -> Type {
|
||||
array_t(elem_t, TyParam::erased(Type::Nat))
|
||||
pub fn unknown_len_list_t(elem_t: Type) -> Type {
|
||||
list_t(elem_t, TyParam::erased(Type::Nat))
|
||||
}
|
||||
|
||||
pub fn unknown_len_array_mut(elem_t: Type) -> Type {
|
||||
array_mut(elem_t, TyParam::erased(Type::Nat))
|
||||
pub fn unknown_len_list_mut(elem_t: Type) -> Type {
|
||||
list_mut(elem_t, TyParam::erased(Type::Nat))
|
||||
}
|
||||
|
||||
pub fn str_dict_t(value: Type) -> Type {
|
||||
dict! { Type::Str => value }.into()
|
||||
}
|
||||
|
||||
/// `UnsizedArray` is a type of `[x; _]` (unsized array literal).
|
||||
/// `UnsizedArray(T) != Array(T, _)`
|
||||
pub fn unsized_array_t(elem_t: Type) -> Type {
|
||||
poly("UnsizedArray", vec![TyParam::t(elem_t)])
|
||||
/// `UnsizedList` is a type of `[x; _]` (unsized list literal).
|
||||
/// `UnsizedList(T) != List(T, _)`
|
||||
pub fn unsized_list_t(elem_t: Type) -> Type {
|
||||
poly("UnsizedList", vec![TyParam::t(elem_t)])
|
||||
}
|
||||
|
||||
pub fn tuple_t(args: Vec<Type>) -> Type {
|
||||
poly(
|
||||
"Tuple",
|
||||
vec![TyParam::Array(args.into_iter().map(TyParam::t).collect())],
|
||||
vec![TyParam::List(args.into_iter().map(TyParam::t).collect())],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use erg_common::{fn_name, switch_lang};
|
|||
use erg_common::{ArcArray, Str};
|
||||
|
||||
use super::codeobj::{CodeObj, FastKind};
|
||||
use super::constructors::array_t;
|
||||
use super::constructors::list_t;
|
||||
use super::typaram::TyParam;
|
||||
use super::value::ValueObj;
|
||||
use super::{HasType, Type};
|
||||
|
@ -140,7 +140,7 @@ impl Deserializer {
|
|||
}
|
||||
|
||||
fn get_cached_arr(&mut self, arr: &[ValueObj]) -> ValueObj {
|
||||
ValueObj::Array(self.arr_cache.get(arr))
|
||||
ValueObj::List(self.arr_cache.get(arr))
|
||||
}
|
||||
|
||||
pub fn vec_to_bytes<const LEN: usize>(vector: Vec<u8>) -> [u8; LEN] {
|
||||
|
@ -226,7 +226,7 @@ impl Deserializer {
|
|||
field: Option<&str>,
|
||||
) -> DeserializeResult<Vec<ValueObj>> {
|
||||
match self.deserialize_const(v, python_ver)? {
|
||||
ValueObj::Array(arr) => Ok(arr.to_vec()),
|
||||
ValueObj::List(lis) => Ok(lis.to_vec()),
|
||||
other => Err(DeserializeError::type_error(
|
||||
field,
|
||||
&Type::Str,
|
||||
|
@ -242,7 +242,7 @@ impl Deserializer {
|
|||
field: Option<&str>,
|
||||
) -> DeserializeResult<ArcArray<ValueObj>> {
|
||||
match self.deserialize_const(v, python_ver)? {
|
||||
ValueObj::Array(arr) => Ok(arr),
|
||||
ValueObj::List(lis) => Ok(lis),
|
||||
other => Err(DeserializeError::type_error(
|
||||
field,
|
||||
&Type::Str,
|
||||
|
@ -273,16 +273,16 @@ impl Deserializer {
|
|||
field: Option<&str>,
|
||||
) -> DeserializeResult<Vec<Str>> {
|
||||
match self.deserialize_const(v, python_ver)? {
|
||||
ValueObj::Array(arr) | ValueObj::Tuple(arr) => {
|
||||
let mut strs = Vec::with_capacity(arr.len());
|
||||
for c in arr.iter().cloned() {
|
||||
ValueObj::List(lis) | ValueObj::Tuple(lis) => {
|
||||
let mut strs = Vec::with_capacity(lis.len());
|
||||
for c in lis.iter().cloned() {
|
||||
strs.push(self.try_into_str(c)?);
|
||||
}
|
||||
Ok(strs)
|
||||
}
|
||||
other => Err(DeserializeError::type_error(
|
||||
field,
|
||||
&array_t(Type::Str, TyParam::erased(Type::Nat)),
|
||||
&list_t(Type::Str, TyParam::erased(Type::Nat)),
|
||||
&other.class(),
|
||||
)),
|
||||
}
|
||||
|
|
|
@ -2040,8 +2040,8 @@ impl Type {
|
|||
_ => None,
|
||||
},
|
||||
Self::Poly { name, params } => match &name[..] {
|
||||
"Array!" => Some(Self::Poly {
|
||||
name: "Array".into(),
|
||||
"List!" => Some(Self::Poly {
|
||||
name: "List".into(),
|
||||
params: params.clone(),
|
||||
}),
|
||||
"Set!" => Some(Self::Poly {
|
||||
|
@ -2106,13 +2106,13 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
/// value class := mono value object class | (Array | Set)(value class)
|
||||
/// value class := mono value object class | (List | Set)(value class)
|
||||
pub fn is_value_class(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_value_class(),
|
||||
Self::Refinement(refine) => refine.t.is_value_class(),
|
||||
Self::Poly { name, params } => {
|
||||
if &name[..] == "Array" || &name[..] == "Set" {
|
||||
if &name[..] == "List" || &name[..] == "Set" {
|
||||
let Some(elem_t) = params.first().and_then(|p| <&Type>::try_from(p).ok())
|
||||
else {
|
||||
if DEBUG_MODE {
|
||||
|
@ -2195,7 +2195,7 @@ impl Type {
|
|||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_singleton(),
|
||||
Self::Refinement(refine) => refine.t.is_singleton(),
|
||||
Self::Poly { name, params } => {
|
||||
if &name[..] == "Array" || &name[..] == "Set" {
|
||||
if &name[..] == "List" || &name[..] == "Set" {
|
||||
let Some(elem_t) = params.first().and_then(|p| <&Type>::try_from(p).ok())
|
||||
else {
|
||||
if DEBUG_MODE {
|
||||
|
@ -2373,11 +2373,11 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_array(&self) -> bool {
|
||||
pub fn is_list(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_array(),
|
||||
Self::Poly { name, .. } => &name[..] == "Array",
|
||||
Self::Refinement(refine) => refine.t.is_array(),
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_list(),
|
||||
Self::Poly { name, .. } => &name[..] == "List",
|
||||
Self::Refinement(refine) => refine.t.is_list(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -2391,11 +2391,11 @@ impl Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_array_mut(&self) -> bool {
|
||||
pub fn is_list_mut(&self) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_array_mut(),
|
||||
Self::Poly { name, .. } => &name[..] == "Array!",
|
||||
Self::Refinement(refine) => refine.t.is_array_mut(),
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_list_mut(),
|
||||
Self::Poly { name, .. } => &name[..] == "List!",
|
||||
Self::Refinement(refine) => refine.t.is_list_mut(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -3391,7 +3391,7 @@ impl Type {
|
|||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().container_len(),
|
||||
Self::Poly { name, params } => match &name[..] {
|
||||
"Array" => {
|
||||
"List" => {
|
||||
if let TyParam::Value(ValueObj::Nat(n)) = ¶ms[0] {
|
||||
Some(*n as usize)
|
||||
} else {
|
||||
|
@ -3691,7 +3691,7 @@ impl Type {
|
|||
/// ```erg
|
||||
/// (Failure -> Int).replace_failure() == (Obj -> Int)
|
||||
/// (Int -> Failure).replace_failure() == (Int -> Never)
|
||||
/// Array(Failure, 3).replace_failure() == Array(Never, 3)
|
||||
/// List(Failure, 3).replace_failure() == List(Never, 3)
|
||||
/// ```
|
||||
pub fn replace_failure(&self) -> Type {
|
||||
match self {
|
||||
|
@ -4093,7 +4093,7 @@ impl Type {
|
|||
|
||||
/// ```erg
|
||||
/// Int.contained_ts() == {Int}
|
||||
/// Array(Array(Int)).contained_ts() == {Array(Int), Int}
|
||||
/// List(List(Int)).contained_ts() == {List(Int), Int}
|
||||
/// (Int or Str).contained_ts() == {Int, Str}
|
||||
/// ```
|
||||
pub fn contained_ts(&self) -> Set<Type> {
|
||||
|
@ -4460,8 +4460,8 @@ pub enum TypeCode {
|
|||
Bool,
|
||||
Str,
|
||||
StrMut,
|
||||
Array, // 要素数は検査済みなので、気にする必要はない
|
||||
ArrayMut,
|
||||
List, // 要素数は検査済みなので、気にする必要はない
|
||||
ListMut,
|
||||
// Dict,
|
||||
Set,
|
||||
SetMut,
|
||||
|
@ -4493,7 +4493,7 @@ impl From<&Type> for TypeCode {
|
|||
_ => Self::Other,
|
||||
},
|
||||
Type::Poly { name, .. } => match &name[..] {
|
||||
"Array" | "Array!" => Self::Array,
|
||||
"List" | "List!" => Self::List,
|
||||
"Set" | "Set!" => Self::Set,
|
||||
"Func" => Self::Func,
|
||||
"Proc" => Self::Proc,
|
||||
|
@ -4516,7 +4516,7 @@ pub enum TypePair {
|
|||
IntFloat,
|
||||
IntStr,
|
||||
IntBool,
|
||||
IntArray,
|
||||
IntList,
|
||||
IntFunc,
|
||||
IntProc,
|
||||
NatInt,
|
||||
|
@ -4524,7 +4524,7 @@ pub enum TypePair {
|
|||
NatFloat,
|
||||
NatStr,
|
||||
NatBool,
|
||||
NatArray,
|
||||
NatList,
|
||||
NatFunc,
|
||||
NatProc,
|
||||
FloatInt,
|
||||
|
@ -4532,7 +4532,7 @@ pub enum TypePair {
|
|||
FloatFloat,
|
||||
FloatStr,
|
||||
FloatBool,
|
||||
FloatArray,
|
||||
FloatList,
|
||||
FloatFunc,
|
||||
FloatProc,
|
||||
BoolInt,
|
||||
|
@ -4540,7 +4540,7 @@ pub enum TypePair {
|
|||
BoolFloat,
|
||||
BoolStr,
|
||||
BoolBool,
|
||||
BoolArray,
|
||||
BoolList,
|
||||
BoolFunc,
|
||||
BoolProc,
|
||||
StrInt,
|
||||
|
@ -4548,24 +4548,24 @@ pub enum TypePair {
|
|||
StrFloat,
|
||||
StrBool,
|
||||
StrStr,
|
||||
StrArray,
|
||||
StrList,
|
||||
StrFunc,
|
||||
StrProc,
|
||||
// 要素数は検査済みなので、気にする必要はない
|
||||
ArrayInt,
|
||||
ArrayNat,
|
||||
ArrayFloat,
|
||||
ArrayStr,
|
||||
ArrayBool,
|
||||
ArrayArray,
|
||||
ArrayFunc,
|
||||
ArrayProc,
|
||||
ListInt,
|
||||
ListNat,
|
||||
ListFloat,
|
||||
ListStr,
|
||||
ListBool,
|
||||
ListList,
|
||||
ListFunc,
|
||||
ListProc,
|
||||
FuncInt,
|
||||
FuncNat,
|
||||
FuncFloat,
|
||||
FuncStr,
|
||||
FuncBool,
|
||||
FuncArray,
|
||||
FuncList,
|
||||
FuncFunc,
|
||||
FuncProc,
|
||||
ProcInt,
|
||||
|
@ -4573,7 +4573,7 @@ pub enum TypePair {
|
|||
ProcFloat,
|
||||
ProcStr,
|
||||
ProcBool,
|
||||
ProcArray,
|
||||
ProcList,
|
||||
ProcFunc,
|
||||
ProcProc,
|
||||
Others,
|
||||
|
@ -4588,7 +4588,7 @@ impl From<u8> for TypePair {
|
|||
3 => Self::IntFloat,
|
||||
4 => Self::IntStr,
|
||||
5 => Self::IntBool,
|
||||
6 => Self::IntArray,
|
||||
6 => Self::IntList,
|
||||
7 => Self::IntFunc,
|
||||
8 => Self::IntProc,
|
||||
9 => Self::NatInt,
|
||||
|
@ -4596,7 +4596,7 @@ impl From<u8> for TypePair {
|
|||
11 => Self::NatFloat,
|
||||
12 => Self::NatStr,
|
||||
13 => Self::NatBool,
|
||||
14 => Self::NatArray,
|
||||
14 => Self::NatList,
|
||||
15 => Self::NatFunc,
|
||||
16 => Self::NatProc,
|
||||
17 => Self::FloatInt,
|
||||
|
@ -4604,7 +4604,7 @@ impl From<u8> for TypePair {
|
|||
19 => Self::FloatFloat,
|
||||
20 => Self::FloatStr,
|
||||
21 => Self::FloatBool,
|
||||
22 => Self::FloatArray,
|
||||
22 => Self::FloatList,
|
||||
23 => Self::FloatFunc,
|
||||
24 => Self::FloatProc,
|
||||
25 => Self::BoolInt,
|
||||
|
@ -4612,7 +4612,7 @@ impl From<u8> for TypePair {
|
|||
27 => Self::BoolFloat,
|
||||
28 => Self::BoolStr,
|
||||
29 => Self::BoolBool,
|
||||
30 => Self::BoolArray,
|
||||
30 => Self::BoolList,
|
||||
31 => Self::BoolFunc,
|
||||
32 => Self::BoolProc,
|
||||
33 => Self::StrInt,
|
||||
|
@ -4620,24 +4620,24 @@ impl From<u8> for TypePair {
|
|||
35 => Self::StrFloat,
|
||||
36 => Self::StrBool,
|
||||
37 => Self::StrStr,
|
||||
38 => Self::StrArray,
|
||||
38 => Self::StrList,
|
||||
39 => Self::StrFunc,
|
||||
40 => Self::StrProc,
|
||||
// 要素数は検査済みなので、気にする必要はない
|
||||
41 => Self::ArrayInt,
|
||||
42 => Self::ArrayNat,
|
||||
43 => Self::ArrayFloat,
|
||||
44 => Self::ArrayStr,
|
||||
45 => Self::ArrayBool,
|
||||
46 => Self::ArrayArray,
|
||||
47 => Self::ArrayFunc,
|
||||
48 => Self::ArrayProc,
|
||||
41 => Self::ListInt,
|
||||
42 => Self::ListNat,
|
||||
43 => Self::ListFloat,
|
||||
44 => Self::ListStr,
|
||||
45 => Self::ListBool,
|
||||
46 => Self::ListList,
|
||||
47 => Self::ListFunc,
|
||||
48 => Self::ListProc,
|
||||
49 => Self::FuncInt,
|
||||
50 => Self::FuncNat,
|
||||
51 => Self::FuncFloat,
|
||||
52 => Self::FuncStr,
|
||||
53 => Self::FuncBool,
|
||||
54 => Self::FuncArray,
|
||||
54 => Self::FuncList,
|
||||
55 => Self::FuncFunc,
|
||||
56 => Self::FuncProc,
|
||||
57 => Self::ProcInt,
|
||||
|
@ -4645,7 +4645,7 @@ impl From<u8> for TypePair {
|
|||
59 => Self::ProcFloat,
|
||||
60 => Self::ProcStr,
|
||||
61 => Self::ProcBool,
|
||||
62 => Self::ProcArray,
|
||||
62 => Self::ProcList,
|
||||
63 => Self::ProcProc,
|
||||
64 => Self::Others,
|
||||
_ => Self::Illegals,
|
||||
|
@ -4662,7 +4662,7 @@ impl TypePair {
|
|||
(Type::Int, Type::Float) => Self::IntFloat,
|
||||
(Type::Int, Type::Str) => Self::IntStr,
|
||||
(Type::Int, Type::Bool) => Self::IntBool,
|
||||
(Type::Int, Type::Poly { name, .. }) if &name[..] == "Array" => Self::IntArray,
|
||||
(Type::Int, Type::Poly { name, .. }) if &name[..] == "List" => Self::IntList,
|
||||
(Type::Int, Type::Poly { name, .. }) if &name[..] == "Func" => Self::IntFunc,
|
||||
(Type::Int, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::IntProc,
|
||||
(Type::Nat, Type::Int) => Self::NatInt,
|
||||
|
@ -4670,7 +4670,7 @@ impl TypePair {
|
|||
(Type::Nat, Type::Float) => Self::NatFloat,
|
||||
(Type::Nat, Type::Str) => Self::NatStr,
|
||||
(Type::Nat, Type::Bool) => Self::NatBool,
|
||||
(Type::Nat, Type::Poly { name, .. }) if &name[..] == "Array" => Self::NatArray,
|
||||
(Type::Nat, Type::Poly { name, .. }) if &name[..] == "List" => Self::NatList,
|
||||
(Type::Nat, Type::Poly { name, .. }) if &name[..] == "Func" => Self::NatFunc,
|
||||
(Type::Nat, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::NatProc,
|
||||
(Type::Float, Type::Int) => Self::FloatInt,
|
||||
|
@ -4678,7 +4678,7 @@ impl TypePair {
|
|||
(Type::Float, Type::Float) => Self::FloatFloat,
|
||||
(Type::Float, Type::Str) => Self::FloatStr,
|
||||
(Type::Float, Type::Bool) => Self::FloatBool,
|
||||
(Type::Float, Type::Poly { name, .. }) if &name[..] == "Array" => Self::FloatArray,
|
||||
(Type::Float, Type::Poly { name, .. }) if &name[..] == "List" => Self::FloatList,
|
||||
(Type::Float, Type::Poly { name, .. }) if &name[..] == "Func" => Self::FloatFunc,
|
||||
(Type::Float, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::FloatProc,
|
||||
(Type::Bool, Type::Int) => Self::BoolInt,
|
||||
|
@ -4686,7 +4686,7 @@ impl TypePair {
|
|||
(Type::Bool, Type::Float) => Self::BoolFloat,
|
||||
(Type::Bool, Type::Str) => Self::BoolStr,
|
||||
(Type::Bool, Type::Bool) => Self::BoolBool,
|
||||
(Type::Bool, Type::Poly { name, .. }) if &name[..] == "Array" => Self::BoolArray,
|
||||
(Type::Bool, Type::Poly { name, .. }) if &name[..] == "List" => Self::BoolList,
|
||||
(Type::Bool, Type::Poly { name, .. }) if &name[..] == "Func" => Self::BoolFunc,
|
||||
(Type::Bool, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::BoolProc,
|
||||
(Type::Str, Type::Int) => Self::StrInt,
|
||||
|
@ -4694,29 +4694,29 @@ impl TypePair {
|
|||
(Type::Str, Type::Float) => Self::StrFloat,
|
||||
(Type::Str, Type::Bool) => Self::StrBool,
|
||||
(Type::Str, Type::Str) => Self::StrStr,
|
||||
(Type::Str, Type::Poly { name, .. }) if &name[..] == "Array" => Self::StrArray,
|
||||
(Type::Str, Type::Poly { name, .. }) if &name[..] == "List" => Self::StrList,
|
||||
(Type::Str, Type::Poly { name, .. }) if &name[..] == "Func" => Self::StrFunc,
|
||||
(Type::Str, Type::Poly { name, .. }) if &name[..] == "Proc" => Self::StrProc,
|
||||
// 要素数は検査済みなので、気にする必要はない
|
||||
(Type::Poly { name, .. }, Type::Int) if &name[..] == "Array" => Self::ArrayInt,
|
||||
(Type::Poly { name, .. }, Type::Nat) if &name[..] == "Array" => Self::ArrayNat,
|
||||
(Type::Poly { name, .. }, Type::Float) if &name[..] == "Array" => Self::ArrayFloat,
|
||||
(Type::Poly { name, .. }, Type::Str) if &name[..] == "Array" => Self::ArrayStr,
|
||||
(Type::Poly { name, .. }, Type::Bool) if &name[..] == "Array" => Self::ArrayBool,
|
||||
(Type::Poly { name, .. }, Type::Int) if &name[..] == "List" => Self::ListInt,
|
||||
(Type::Poly { name, .. }, Type::Nat) if &name[..] == "List" => Self::ListNat,
|
||||
(Type::Poly { name, .. }, Type::Float) if &name[..] == "List" => Self::ListFloat,
|
||||
(Type::Poly { name, .. }, Type::Str) if &name[..] == "List" => Self::ListStr,
|
||||
(Type::Poly { name, .. }, Type::Bool) if &name[..] == "List" => Self::ListBool,
|
||||
(Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. })
|
||||
if &ln[..] == "Array" && &rn[..] == "Array" =>
|
||||
if &ln[..] == "List" && &rn[..] == "List" =>
|
||||
{
|
||||
Self::ArrayArray
|
||||
Self::ListList
|
||||
}
|
||||
(Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. })
|
||||
if &ln[..] == "Array" && &rn[..] == "Func" =>
|
||||
if &ln[..] == "List" && &rn[..] == "Func" =>
|
||||
{
|
||||
Self::ArrayFunc
|
||||
Self::ListFunc
|
||||
}
|
||||
(Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. })
|
||||
if &ln[..] == "Array" && &rn[..] == "Proc" =>
|
||||
if &ln[..] == "List" && &rn[..] == "Proc" =>
|
||||
{
|
||||
Self::ArrayProc
|
||||
Self::ListProc
|
||||
}
|
||||
(Type::Poly { name, .. }, Type::Int) if &name[..] == "Func" => Self::FuncInt,
|
||||
(Type::Poly { name, .. }, Type::Nat) if &name[..] == "Func" => Self::FuncNat,
|
||||
|
@ -4724,9 +4724,9 @@ impl TypePair {
|
|||
(Type::Poly { name, .. }, Type::Str) if &name[..] == "Func" => Self::FuncStr,
|
||||
(Type::Poly { name, .. }, Type::Bool) if &name[..] == "Func" => Self::FuncBool,
|
||||
(Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. })
|
||||
if &ln[..] == "Func" && &rn[..] == "Array" =>
|
||||
if &ln[..] == "Func" && &rn[..] == "List" =>
|
||||
{
|
||||
Self::FuncArray
|
||||
Self::FuncList
|
||||
}
|
||||
(Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. })
|
||||
if &ln[..] == "Func" && &rn[..] == "Func" =>
|
||||
|
@ -4744,9 +4744,9 @@ impl TypePair {
|
|||
(Type::Poly { name, .. }, Type::Str) if &name[..] == "Proc" => Self::ProcStr,
|
||||
(Type::Poly { name, .. }, Type::Bool) if &name[..] == "Proc" => Self::ProcBool,
|
||||
(Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. })
|
||||
if &ln[..] == "Proc" && &rn[..] == "Array" =>
|
||||
if &ln[..] == "Proc" && &rn[..] == "List" =>
|
||||
{
|
||||
Self::ProcArray
|
||||
Self::ProcList
|
||||
}
|
||||
(Type::Poly { name: ln, .. }, Type::Poly { name: rn, .. })
|
||||
if &ln[..] == "Proc" && &rn[..] == "Func" =>
|
||||
|
|
|
@ -240,9 +240,9 @@ impl TyParamLambda {
|
|||
/// * Type: Int, Add(?R, ?O), ...
|
||||
/// * Mono: I, N, ...
|
||||
/// * Attr: math.PI, ...
|
||||
/// * Array: `[1, 2, N]`
|
||||
/// * List: `[1, 2, N]`
|
||||
/// * Tuple: (1, N, True)
|
||||
/// * App: Array(Int), Fib(10), ...
|
||||
/// * App: List(Int), Fib(10), ...
|
||||
/// * QuantVar: N: Nat, ...
|
||||
/// * FreeVar: ?I: Int, ...
|
||||
/// * UnaryOp: -N, ~B, ...
|
||||
|
@ -252,8 +252,8 @@ impl TyParamLambda {
|
|||
pub enum TyParam {
|
||||
Value(ValueObj),
|
||||
Type(Box<Type>),
|
||||
Array(Vec<TyParam>),
|
||||
UnsizedArray(Box<TyParam>),
|
||||
List(Vec<TyParam>),
|
||||
UnsizedList(Box<TyParam>),
|
||||
Tuple(Vec<TyParam>),
|
||||
Set(Set<TyParam>),
|
||||
Dict(Dict<TyParam, TyParam>),
|
||||
|
@ -296,8 +296,8 @@ impl PartialEq for TyParam {
|
|||
match (self, other) {
|
||||
(Self::Value(l), Self::Value(r)) => l == r,
|
||||
(Self::Type(l), Self::Type(r)) => l == r,
|
||||
(Self::Array(l), Self::Array(r)) => l == r,
|
||||
(Self::UnsizedArray(l), Self::UnsizedArray(r)) => l == r,
|
||||
(Self::List(l), Self::List(r)) => l == r,
|
||||
(Self::UnsizedList(l), Self::UnsizedList(r)) => l == r,
|
||||
(Self::Tuple(l), Self::Tuple(r)) => l == r,
|
||||
(Self::Dict(l), Self::Dict(r)) => l == r,
|
||||
(Self::Record(l), Self::Record(r)) => l == r,
|
||||
|
@ -435,9 +435,9 @@ impl LimitedDisplay for TyParam {
|
|||
write!(f, ")")?;
|
||||
Ok(())
|
||||
}
|
||||
Self::Array(arr) => {
|
||||
Self::List(lis) => {
|
||||
write!(f, "[")?;
|
||||
for (i, t) in arr.iter().enumerate() {
|
||||
for (i, t) in lis.iter().enumerate() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
|
@ -449,7 +449,7 @@ impl LimitedDisplay for TyParam {
|
|||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
Self::UnsizedArray(elem) => {
|
||||
Self::UnsizedList(elem) => {
|
||||
write!(f, "[")?;
|
||||
elem.limited_fmt(f, limit - 1)?;
|
||||
write!(f, "; _]")
|
||||
|
@ -685,16 +685,16 @@ impl TryFrom<TyParam> for ValueObj {
|
|||
type Error = ();
|
||||
fn try_from(tp: TyParam) -> Result<Self, ()> {
|
||||
match tp {
|
||||
TyParam::Array(tps) => {
|
||||
TyParam::List(tps) => {
|
||||
let mut vals = vec![];
|
||||
for tp in tps {
|
||||
vals.push(ValueObj::try_from(tp)?);
|
||||
}
|
||||
Ok(ValueObj::Array(Arc::from(vals)))
|
||||
Ok(ValueObj::List(Arc::from(vals)))
|
||||
}
|
||||
TyParam::UnsizedArray(elem) => {
|
||||
TyParam::UnsizedList(elem) => {
|
||||
let elem = ValueObj::try_from(*elem)?;
|
||||
Ok(ValueObj::UnsizedArray(Box::new(elem)))
|
||||
Ok(ValueObj::UnsizedList(Box::new(elem)))
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
let mut vals = vec![];
|
||||
|
@ -768,7 +768,7 @@ impl TryFrom<TyParam> for Vec<TyParam> {
|
|||
fn try_from(tp: TyParam) -> Result<Self, ()> {
|
||||
match tp {
|
||||
TyParam::FreeVar(fv) if fv.is_linked() => Vec::try_from(fv.crack().clone()),
|
||||
TyParam::Array(tps) => Ok(tps),
|
||||
TyParam::List(tps) => Ok(tps),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -783,7 +783,7 @@ impl<'a> TryFrom<&'a TyParam> for &'a Type {
|
|||
}
|
||||
TyParam::Type(t) => Ok(t.as_ref()),
|
||||
TyParam::Value(v) => <&Type>::try_from(v),
|
||||
// TODO: Array, Dict, Set
|
||||
// TODO: List, Dict, Set
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -805,7 +805,7 @@ impl HasLevel for TyParam {
|
|||
match self {
|
||||
Self::Type(t) => t.level(),
|
||||
Self::FreeVar(fv) => fv.level(),
|
||||
Self::Array(tps) | Self::Tuple(tps) => tps.iter().filter_map(|tp| tp.level()).min(),
|
||||
Self::List(tps) | Self::Tuple(tps) => tps.iter().filter_map(|tp| tp.level()).min(),
|
||||
Self::Dict(tps) => tps
|
||||
.iter()
|
||||
.map(|(k, v)| {
|
||||
|
@ -844,7 +844,7 @@ impl HasLevel for TyParam {
|
|||
v.set_level(level);
|
||||
}
|
||||
}
|
||||
Self::Array(tps) => {
|
||||
Self::List(tps) => {
|
||||
for tp in tps {
|
||||
tp.set_level(level);
|
||||
}
|
||||
|
@ -883,7 +883,7 @@ impl StructuralEq for TyParam {
|
|||
fn structural_eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Self::Type(l), Self::Type(r)) => l.structural_eq(r),
|
||||
(Self::Array(l), Self::Array(r)) => l.iter().zip(r).all(|(l, r)| l.structural_eq(r)),
|
||||
(Self::List(l), Self::List(r)) => l.iter().zip(r).all(|(l, r)| l.structural_eq(r)),
|
||||
(Self::Tuple(l), Self::Tuple(r)) => l.iter().zip(r).all(|(l, r)| l.structural_eq(r)),
|
||||
(Self::Dict(l), Self::Dict(r)) => {
|
||||
if l.len() != r.len() {
|
||||
|
@ -1076,8 +1076,8 @@ impl TyParam {
|
|||
Self::Erased(Box::new(t))
|
||||
}
|
||||
|
||||
pub fn unsized_array(elem: TyParam) -> Self {
|
||||
Self::UnsizedArray(Box::new(elem))
|
||||
pub fn unsized_list(elem: TyParam) -> Self {
|
||||
Self::UnsizedList(Box::new(elem))
|
||||
}
|
||||
|
||||
// if self: Ratio, Succ(self) => self+ε
|
||||
|
@ -1196,7 +1196,7 @@ impl TyParam {
|
|||
}
|
||||
Self::Type(t) => t.qvars(),
|
||||
Self::Proj { obj, .. } => obj.qvars(),
|
||||
Self::Array(ts) | Self::Tuple(ts) => {
|
||||
Self::List(ts) | Self::Tuple(ts) => {
|
||||
ts.iter().fold(set! {}, |acc, t| acc.concat(t.qvars()))
|
||||
}
|
||||
Self::Set(ts) => ts.iter().fold(set! {}, |acc, t| acc.concat(t.qvars())),
|
||||
|
@ -1225,7 +1225,7 @@ impl TyParam {
|
|||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().has_qvar(),
|
||||
Self::Type(t) => t.has_qvar(),
|
||||
Self::Proj { obj, .. } => obj.has_qvar(),
|
||||
Self::Array(tps) | Self::Tuple(tps) => tps.iter().any(|tp| tp.has_qvar()),
|
||||
Self::List(tps) | Self::Tuple(tps) => tps.iter().any(|tp| tp.has_qvar()),
|
||||
Self::Set(tps) => tps.iter().any(|tp| tp.has_qvar()),
|
||||
Self::Dict(tps) => tps.iter().any(|(k, v)| k.has_qvar() || v.has_qvar()),
|
||||
Self::Record(rec) | Self::DataClass { fields: rec, .. } => {
|
||||
|
@ -1247,7 +1247,7 @@ impl TyParam {
|
|||
Self::Type(t) => t.contains_tvar(target),
|
||||
Self::Erased(t) => t.contains_tvar(target),
|
||||
Self::Proj { obj, .. } => obj.contains_tvar(target),
|
||||
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tvar(target)),
|
||||
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tvar(target)),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.contains_tvar(target)),
|
||||
Self::Dict(ts) => ts
|
||||
.iter()
|
||||
|
@ -1273,8 +1273,8 @@ impl TyParam {
|
|||
Self::ProjCall { obj, args, .. } => {
|
||||
obj.contains_type(target) || args.iter().any(|t| t.contains_type(target))
|
||||
}
|
||||
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_type(target)),
|
||||
Self::UnsizedArray(elem) => elem.contains_type(target),
|
||||
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_type(target)),
|
||||
Self::UnsizedList(elem) => elem.contains_type(target),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.contains_type(target)),
|
||||
Self::Dict(ts) => ts
|
||||
.iter()
|
||||
|
@ -1303,8 +1303,8 @@ impl TyParam {
|
|||
Self::ProjCall { obj, args, .. } => {
|
||||
obj.contains_tp(target) || args.iter().any(|t| t.contains_tp(target))
|
||||
}
|
||||
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tp(target)),
|
||||
Self::UnsizedArray(elem) => elem.contains_tp(target),
|
||||
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tp(target)),
|
||||
Self::UnsizedList(elem) => elem.contains_tp(target),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.contains_tp(target)),
|
||||
Self::Dict(ts) => ts
|
||||
.iter()
|
||||
|
@ -1333,8 +1333,8 @@ impl TyParam {
|
|||
Self::UnaryOp { val, .. } => val.contains_tp(self),
|
||||
Self::App { args, .. } => args.iter().any(|t| t.contains_tp(self)),
|
||||
Self::Lambda(lambda) => lambda.body.iter().any(|t| t.contains_tp(self)),
|
||||
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tp(self)),
|
||||
Self::UnsizedArray(elem) => elem.contains_tp(self),
|
||||
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tp(self)),
|
||||
Self::UnsizedList(elem) => elem.contains_tp(self),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.contains_tp(self)),
|
||||
Self::Record(rec) | Self::DataClass { fields: rec, .. } => {
|
||||
rec.iter().any(|(_, t)| t.contains_tp(self))
|
||||
|
@ -1372,8 +1372,8 @@ impl TyParam {
|
|||
Self::ProjCall { obj, args, .. } => {
|
||||
obj.has_unbound_var() || args.iter().any(|t| t.has_unbound_var())
|
||||
}
|
||||
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_unbound_var()),
|
||||
Self::UnsizedArray(elem) => elem.has_unbound_var(),
|
||||
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_unbound_var()),
|
||||
Self::UnsizedList(elem) => elem.has_unbound_var(),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.has_unbound_var()),
|
||||
Self::Dict(kv) => kv
|
||||
.iter()
|
||||
|
@ -1403,8 +1403,8 @@ impl TyParam {
|
|||
Self::ProjCall { obj, args, .. } => {
|
||||
obj.has_undoable_linked_var() || args.iter().any(|t| t.has_undoable_linked_var())
|
||||
}
|
||||
Self::Array(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_undoable_linked_var()),
|
||||
Self::UnsizedArray(elem) => elem.has_undoable_linked_var(),
|
||||
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.has_undoable_linked_var()),
|
||||
Self::UnsizedList(elem) => elem.has_undoable_linked_var(),
|
||||
Self::Set(ts) => ts.iter().any(|t| t.has_undoable_linked_var()),
|
||||
Self::Dict(kv) => kv
|
||||
.iter()
|
||||
|
@ -1432,10 +1432,10 @@ impl TyParam {
|
|||
Self::ProjCall { obj, args, .. } => obj
|
||||
.union_size()
|
||||
.max(args.iter().map(|t| t.union_size()).max().unwrap_or(1)),
|
||||
Self::Array(ts) | Self::Tuple(ts) => {
|
||||
Self::List(ts) | Self::Tuple(ts) => {
|
||||
ts.iter().map(|t| t.union_size()).max().unwrap_or(1)
|
||||
}
|
||||
Self::UnsizedArray(elem) => elem.union_size(),
|
||||
Self::UnsizedList(elem) => elem.union_size(),
|
||||
Self::Set(ts) => ts.iter().map(|t| t.union_size()).max().unwrap_or(1),
|
||||
Self::Dict(kv) => kv
|
||||
.iter()
|
||||
|
@ -1517,10 +1517,10 @@ impl TyParam {
|
|||
let new_val = val.substitute(var, to);
|
||||
TyParam::unary(op, new_val)
|
||||
}
|
||||
TyParam::UnsizedArray(elem) => TyParam::unsized_array(elem.substitute(var, to)),
|
||||
TyParam::Array(tps) => {
|
||||
TyParam::UnsizedList(elem) => TyParam::unsized_list(elem.substitute(var, to)),
|
||||
TyParam::List(tps) => {
|
||||
let new_tps = tps.into_iter().map(|t| t.substitute(var, to)).collect();
|
||||
TyParam::Array(new_tps)
|
||||
TyParam::List(new_tps)
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
let new_tps = tps.into_iter().map(|t| t.substitute(var, to)).collect();
|
||||
|
@ -1610,10 +1610,10 @@ impl TyParam {
|
|||
let new_val = val.replace(target, to);
|
||||
TyParam::unary(op, new_val)
|
||||
}
|
||||
TyParam::UnsizedArray(elem) => TyParam::unsized_array(elem.replace(target, to)),
|
||||
TyParam::Array(tps) => {
|
||||
TyParam::UnsizedList(elem) => TyParam::unsized_list(elem.replace(target, to)),
|
||||
TyParam::List(tps) => {
|
||||
let new_tps = tps.into_iter().map(|t| t.replace(target, to)).collect();
|
||||
TyParam::Array(new_tps)
|
||||
TyParam::List(new_tps)
|
||||
}
|
||||
TyParam::Tuple(tps) => {
|
||||
let new_tps = tps.into_iter().map(|t| t.replace(target, to)).collect();
|
||||
|
@ -1844,12 +1844,12 @@ impl TyParam {
|
|||
arg.dereference();
|
||||
}
|
||||
}
|
||||
Self::Array(ts) | Self::Tuple(ts) => {
|
||||
Self::List(ts) | Self::Tuple(ts) => {
|
||||
for t in ts {
|
||||
t.dereference();
|
||||
}
|
||||
}
|
||||
Self::UnsizedArray(elem) => elem.dereference(),
|
||||
Self::UnsizedList(elem) => elem.dereference(),
|
||||
Self::Set(ts) => {
|
||||
let ts_ = std::mem::take(ts);
|
||||
*ts = ts_
|
||||
|
@ -1922,7 +1922,7 @@ impl TyParam {
|
|||
}
|
||||
set
|
||||
}
|
||||
Self::Array(tps) | Self::Tuple(tps) => {
|
||||
Self::List(tps) | Self::Tuple(tps) => {
|
||||
tps.iter().fold(set! {}, |acc, t| acc.concat(t.variables()))
|
||||
}
|
||||
Self::Set(tps) => tps.iter().fold(set! {}, |acc, t| acc.concat(t.variables())),
|
||||
|
@ -1932,7 +1932,7 @@ impl TyParam {
|
|||
Self::Dict(tps) => tps.iter().fold(set! {}, |acc, (k, v)| {
|
||||
acc.concat(k.variables().concat(v.variables()))
|
||||
}),
|
||||
Self::UnsizedArray(elem) => elem.variables(),
|
||||
Self::UnsizedList(elem) => elem.variables(),
|
||||
Self::BinOp { lhs, rhs, .. } => lhs.variables().concat(rhs.variables()),
|
||||
Self::UnaryOp { val, .. } => val.variables(),
|
||||
Self::Lambda(lambda) => lambda
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::context::Context;
|
|||
use self::value_set::inner_class;
|
||||
|
||||
use super::codeobj::{tuple_into_bytes, CodeObj};
|
||||
use super::constructors::{array_t, dict_t, refinement, set_t, tuple_t, unsized_array_t};
|
||||
use super::constructors::{dict_t, list_t, refinement, set_t, tuple_t, unsized_list_t};
|
||||
use super::typaram::{OpKind, TyParam};
|
||||
use super::{ConstSubr, Field, HasType, Predicate, Type};
|
||||
use super::{CONTAINER_OMIT_THRESHOLD, STR_OMIT_THRESHOLD};
|
||||
|
@ -502,8 +502,8 @@ pub enum ValueObj {
|
|||
Float(f64),
|
||||
Str(Str),
|
||||
Bool(bool),
|
||||
Array(ArcArray<ValueObj>),
|
||||
UnsizedArray(Box<ValueObj>),
|
||||
List(ArcArray<ValueObj>),
|
||||
UnsizedList(Box<ValueObj>),
|
||||
Set(Set<ValueObj>),
|
||||
Dict(Dict<ValueObj, ValueObj>),
|
||||
Tuple(ArcArray<ValueObj>),
|
||||
|
@ -562,8 +562,8 @@ impl fmt::Debug for ValueObj {
|
|||
write!(f, "False")
|
||||
}
|
||||
}
|
||||
Self::Array(arr) => write!(f, "[{}]", fmt_iter(arr.iter())),
|
||||
Self::UnsizedArray(elem) => write!(f, "[{elem}; _]"),
|
||||
Self::List(lis) => write!(f, "[{}]", fmt_iter(lis.iter())),
|
||||
Self::UnsizedList(elem) => write!(f, "[{elem}; _]"),
|
||||
Self::Dict(dict) => {
|
||||
write!(f, "{{")?;
|
||||
for (i, (k, v)) in dict.iter().enumerate() {
|
||||
|
@ -624,9 +624,9 @@ impl LimitedDisplay for ValueObj {
|
|||
write!(f, "\"{}\"", s.escape())
|
||||
}
|
||||
}
|
||||
Self::Array(arr) => {
|
||||
Self::List(lis) => {
|
||||
write!(f, "[")?;
|
||||
for (i, item) in arr.iter().enumerate() {
|
||||
for (i, item) in lis.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
|
@ -751,8 +751,8 @@ impl Hash for ValueObj {
|
|||
Self::Float(f) => f.to_bits().hash(state),
|
||||
Self::Str(s) => s.hash(state),
|
||||
Self::Bool(b) => b.hash(state),
|
||||
Self::Array(arr) => arr.hash(state),
|
||||
Self::UnsizedArray(elem) => {
|
||||
Self::List(lis) => lis.hash(state),
|
||||
Self::UnsizedList(elem) => {
|
||||
"UnsizedArray".hash(state);
|
||||
elem.hash(state)
|
||||
}
|
||||
|
@ -855,7 +855,7 @@ impl From<CodeObj> for ValueObj {
|
|||
|
||||
impl<V: Into<ValueObj>> From<Vec<V>> for ValueObj {
|
||||
fn from(item: Vec<V>) -> Self {
|
||||
ValueObj::Array(ArcArray::from(
|
||||
ValueObj::List(ArcArray::from(
|
||||
&item.into_iter().map(Into::into).collect::<Vec<_>>()[..],
|
||||
))
|
||||
}
|
||||
|
@ -863,7 +863,7 @@ impl<V: Into<ValueObj>> From<Vec<V>> for ValueObj {
|
|||
|
||||
impl<const N: usize, V: Into<ValueObj>> From<[V; N]> for ValueObj {
|
||||
fn from(item: [V; N]) -> Self {
|
||||
ValueObj::Array(ArcArray::from(&item.map(Into::into)[..]))
|
||||
ValueObj::List(ArcArray::from(&item.map(Into::into)[..]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1031,8 +1031,8 @@ impl ValueObj {
|
|||
pub const fn is_container(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Array(_)
|
||||
| Self::UnsizedArray(_)
|
||||
Self::List(_)
|
||||
| Self::UnsizedList(_)
|
||||
| Self::Set(_)
|
||||
| Self::Dict(_)
|
||||
| Self::Tuple(_)
|
||||
|
@ -1124,7 +1124,7 @@ impl ValueObj {
|
|||
Self::Str(s) => str_into_bytes(s, false),
|
||||
Self::Bool(true) => vec![DataTypePrefix::True as u8],
|
||||
Self::Bool(false) => vec![DataTypePrefix::False as u8],
|
||||
Self::Array(elems) | Self::Tuple(elems) => tuple_into_bytes(&elems, python_ver),
|
||||
Self::List(elems) | Self::Tuple(elems) => tuple_into_bytes(&elems, python_ver),
|
||||
Self::None => {
|
||||
vec![DataTypePrefix::None as u8]
|
||||
}
|
||||
|
@ -1169,15 +1169,15 @@ impl ValueObj {
|
|||
Self::Float(_) => Type::Float,
|
||||
Self::Str(_) => Type::Str,
|
||||
Self::Bool(_) => Type::Bool,
|
||||
Self::Array(arr) => array_t(
|
||||
Self::List(lis) => list_t(
|
||||
// REVIEW: Never?
|
||||
arr.iter()
|
||||
lis.iter()
|
||||
.next()
|
||||
.map(|elem| elem.class())
|
||||
.unwrap_or(Type::Never),
|
||||
TyParam::value(arr.len()),
|
||||
TyParam::value(lis.len()),
|
||||
),
|
||||
Self::UnsizedArray(elem) => unsized_array_t(elem.class()),
|
||||
Self::UnsizedList(elem) => unsized_list_t(elem.class()),
|
||||
Self::Dict(dict) => {
|
||||
let tp = dict
|
||||
.iter()
|
||||
|
@ -1295,9 +1295,9 @@ impl ValueObj {
|
|||
(Self::Nat(l), Self::Float(r)) => Some(Self::Float(l as f64 - r)),
|
||||
(Self::Float(l), Self::Int(r)) => Some(Self::Float(l - r as f64)),
|
||||
(Self::Str(l), Self::Str(r)) => Some(Self::Str(Str::from(format!("{l}{r}")))),
|
||||
(Self::Array(l), Self::Array(r)) => {
|
||||
let arr = Arc::from([l, r].concat());
|
||||
Some(Self::Array(arr))
|
||||
(Self::List(l), Self::List(r)) => {
|
||||
let lis = Arc::from([l, r].concat());
|
||||
Some(Self::List(lis))
|
||||
}
|
||||
(Self::Dict(l), Self::Dict(r)) => Some(Self::Dict(l.concat(r))),
|
||||
(inf @ (Self::Inf | Self::NegInf), _) | (_, inf @ (Self::Inf | Self::NegInf)) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ use erg_common::traits::{BlockKind, ExitStatus, Locational, New, Runnable, Strea
|
|||
use erg_compiler::artifact::{Buildable, ErrorArtifact};
|
||||
use erg_compiler::build_package::PackageBuilder;
|
||||
use erg_compiler::error::{CompileError, CompileErrors, CompileWarnings};
|
||||
use erg_compiler::hir::{Accessor, Array, Def, Dict, Expr, Set, Signature, Tuple};
|
||||
use erg_compiler::hir::{Accessor, Def, Dict, Expr, List, Set, Signature, Tuple};
|
||||
use erg_compiler::module::SharedCompilerResource;
|
||||
|
||||
use erg_parser::ParserRunner;
|
||||
|
@ -189,21 +189,21 @@ impl Linter {
|
|||
}
|
||||
}
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
for elem in arr.elems.pos_args.iter() {
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
for elem in lis.elems.pos_args.iter() {
|
||||
lint_fn(self, &elem.expr);
|
||||
}
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
lint_fn(self, &arr.elem);
|
||||
if let Some(len) = &arr.len {
|
||||
List::WithLength(lis) => {
|
||||
lint_fn(self, &lis.elem);
|
||||
if let Some(len) = &lis.len {
|
||||
lint_fn(self, len);
|
||||
}
|
||||
}
|
||||
Array::Comprehension(arr) => {
|
||||
lint_fn(self, &arr.elem);
|
||||
lint_fn(self, &arr.guard);
|
||||
List::Comprehension(lis) => {
|
||||
lint_fn(self, &lis.elem);
|
||||
lint_fn(self, &lis.guard);
|
||||
}
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
|
|
|
@ -202,7 +202,7 @@ pub fn fmt_lines<'a, T: NestedDisplay + 'a>(
|
|||
}
|
||||
|
||||
/// リテラルに実際の値が格納された構造体(定数畳み込み用)
|
||||
/// ArrayやDictはまた別に
|
||||
/// ListやDictはまた別に
|
||||
#[pyclass(get_all, set_all)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Literal {
|
||||
|
@ -865,13 +865,13 @@ impl Accessor {
|
|||
|
||||
#[pyclass(get_all, set_all)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct NormalArray {
|
||||
pub struct NormalList {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub elems: Args,
|
||||
}
|
||||
|
||||
impl NestedDisplay for NormalArray {
|
||||
impl NestedDisplay for NormalList {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
writeln!(f, "[")?;
|
||||
self.elems.fmt_nest(f, level + 1)?;
|
||||
|
@ -879,11 +879,11 @@ impl NestedDisplay for NormalArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(NormalArray);
|
||||
impl_locational!(NormalArray, l_sqbr, elems, r_sqbr);
|
||||
impl_display_from_nested!(NormalList);
|
||||
impl_locational!(NormalList, l_sqbr, elems, r_sqbr);
|
||||
|
||||
#[pymethods]
|
||||
impl NormalArray {
|
||||
impl NormalList {
|
||||
#[pyo3(name = "get")]
|
||||
fn _get(&self, index: usize) -> Option<Expr> {
|
||||
self.get(index).cloned()
|
||||
|
@ -899,7 +899,7 @@ impl NormalArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl NormalArray {
|
||||
impl NormalList {
|
||||
pub fn get(&self, index: usize) -> Option<&Expr> {
|
||||
self.elems.pos_args.get(index).map(|a| &a.expr)
|
||||
}
|
||||
|
@ -911,24 +911,24 @@ impl NormalArray {
|
|||
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ArrayWithLength {
|
||||
pub struct ListWithLength {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub elem: Box<PosArg>,
|
||||
pub len: Box<Expr>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ArrayWithLength {
|
||||
impl NestedDisplay for ListWithLength {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "[{}; {}]", self.elem, self.len)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ArrayWithLength);
|
||||
impl_locational!(ArrayWithLength, l_sqbr, elem, r_sqbr);
|
||||
impl_display_from_nested!(ListWithLength);
|
||||
impl_locational!(ListWithLength, l_sqbr, elem, r_sqbr);
|
||||
|
||||
#[pymethods]
|
||||
impl ArrayWithLength {
|
||||
impl ListWithLength {
|
||||
#[staticmethod]
|
||||
pub fn new(l_sqbr: Token, r_sqbr: Token, elem: PosArg, len: Expr) -> Self {
|
||||
Self {
|
||||
|
@ -942,7 +942,7 @@ impl ArrayWithLength {
|
|||
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ArrayComprehension {
|
||||
pub struct ListComprehension {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub layout: Option<Box<Expr>>,
|
||||
|
@ -950,7 +950,7 @@ pub struct ArrayComprehension {
|
|||
pub guard: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ArrayComprehension {
|
||||
impl NestedDisplay for ListComprehension {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
let mut generators = String::new();
|
||||
for (name, gen) in self.generators.iter() {
|
||||
|
@ -966,11 +966,11 @@ impl NestedDisplay for ArrayComprehension {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ArrayComprehension);
|
||||
impl_locational!(ArrayComprehension, l_sqbr, r_sqbr);
|
||||
impl_display_from_nested!(ListComprehension);
|
||||
impl_locational!(ListComprehension, l_sqbr, r_sqbr);
|
||||
|
||||
#[pymethods]
|
||||
impl ArrayComprehension {
|
||||
impl ListComprehension {
|
||||
#[staticmethod]
|
||||
#[pyo3(signature = (l_sqbr, r_sqbr, layout, generators, guard=None))]
|
||||
pub fn new(
|
||||
|
@ -991,22 +991,22 @@ impl ArrayComprehension {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Array {
|
||||
Normal(NormalArray),
|
||||
WithLength(ArrayWithLength),
|
||||
Comprehension(ArrayComprehension),
|
||||
pub enum List {
|
||||
Normal(NormalList),
|
||||
WithLength(ListWithLength),
|
||||
Comprehension(ListComprehension),
|
||||
}
|
||||
|
||||
impl_nested_display_for_enum!(Array; Normal, WithLength, Comprehension);
|
||||
impl_display_for_enum!(Array; Normal, WithLength, Comprehension);
|
||||
impl_locational_for_enum!(Array; Normal, WithLength, Comprehension);
|
||||
impl_into_py_for_enum!(Array; Normal, WithLength, Comprehension);
|
||||
impl_from_py_for_enum!(Array; Normal(NormalArray), WithLength(ArrayWithLength), Comprehension(ArrayComprehension));
|
||||
impl_nested_display_for_enum!(List; Normal, WithLength, Comprehension);
|
||||
impl_display_for_enum!(List; Normal, WithLength, Comprehension);
|
||||
impl_locational_for_enum!(List; Normal, WithLength, Comprehension);
|
||||
impl_into_py_for_enum!(List; Normal, WithLength, Comprehension);
|
||||
impl_from_py_for_enum!(List; Normal(NormalList), WithLength(ListWithLength), Comprehension(ListComprehension));
|
||||
|
||||
impl Array {
|
||||
impl List {
|
||||
pub fn get(&self, index: usize) -> Option<&Expr> {
|
||||
match self {
|
||||
Self::Normal(array) => array.get(index),
|
||||
Self::Normal(list) => list.get(index),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -2167,36 +2167,36 @@ impl ConstAccessor {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ConstArray {
|
||||
Normal(ConstNormalArray),
|
||||
WithLength(ConstArrayWithLength),
|
||||
pub enum ConstList {
|
||||
Normal(ConstNormalList),
|
||||
WithLength(ConstListWithLength),
|
||||
}
|
||||
|
||||
impl_nested_display_for_enum!(ConstArray; Normal, WithLength);
|
||||
impl_display_from_nested!(ConstArray);
|
||||
impl_locational_for_enum!(ConstArray; Normal, WithLength);
|
||||
impl_into_py_for_enum!(ConstArray; Normal, WithLength);
|
||||
impl_from_py_for_enum!(ConstArray; Normal(ConstNormalArray), WithLength(ConstArrayWithLength));
|
||||
impl_nested_display_for_enum!(ConstList; Normal, WithLength);
|
||||
impl_display_from_nested!(ConstList);
|
||||
impl_locational_for_enum!(ConstList; Normal, WithLength);
|
||||
impl_into_py_for_enum!(ConstList; Normal, WithLength);
|
||||
impl_from_py_for_enum!(ConstList; Normal(ConstNormalList), WithLength(ConstListWithLength));
|
||||
|
||||
impl ConstArray {
|
||||
pub fn downgrade(self) -> Array {
|
||||
impl ConstList {
|
||||
pub fn downgrade(self) -> List {
|
||||
match self {
|
||||
Self::Normal(normal) => Array::Normal(normal.downgrade()),
|
||||
Self::WithLength(with_length) => Array::WithLength(with_length.downgrade()),
|
||||
Self::Normal(normal) => List::Normal(normal.downgrade()),
|
||||
Self::WithLength(with_length) => List::WithLength(with_length.downgrade()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstNormalArray {
|
||||
pub struct ConstNormalList {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub elems: ConstArgs,
|
||||
pub guard: Option<Box<ConstExpr>>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstNormalArray {
|
||||
impl NestedDisplay for ConstNormalList {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
if let Some(guard) = &self.guard {
|
||||
write!(f, "[{} | {}]", self.elems, guard)
|
||||
|
@ -2206,11 +2206,11 @@ impl NestedDisplay for ConstNormalArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ConstNormalArray);
|
||||
impl_locational!(ConstNormalArray, l_sqbr, elems, r_sqbr);
|
||||
impl_display_from_nested!(ConstNormalList);
|
||||
impl_locational!(ConstNormalList, l_sqbr, elems, r_sqbr);
|
||||
|
||||
#[pymethods]
|
||||
impl ConstNormalArray {
|
||||
impl ConstNormalList {
|
||||
#[staticmethod]
|
||||
pub fn new(l_sqbr: Token, r_sqbr: Token, elems: ConstArgs, guard: Option<ConstExpr>) -> Self {
|
||||
Self {
|
||||
|
@ -2222,32 +2222,32 @@ impl ConstNormalArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConstNormalArray {
|
||||
pub fn downgrade(self) -> NormalArray {
|
||||
NormalArray::new(self.l_sqbr, self.r_sqbr, self.elems.downgrade())
|
||||
impl ConstNormalList {
|
||||
pub fn downgrade(self) -> NormalList {
|
||||
NormalList::new(self.l_sqbr, self.r_sqbr, self.elems.downgrade())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ConstArrayWithLength {
|
||||
pub struct ConstListWithLength {
|
||||
pub l_sqbr: Token,
|
||||
pub r_sqbr: Token,
|
||||
pub elem: Box<ConstExpr>,
|
||||
pub length: Box<ConstExpr>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ConstArrayWithLength {
|
||||
impl NestedDisplay for ConstListWithLength {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "[{}; {}]", self.elem, self.length)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ConstArrayWithLength);
|
||||
impl_locational!(ConstArrayWithLength, l_sqbr, elem, r_sqbr);
|
||||
impl_display_from_nested!(ConstListWithLength);
|
||||
impl_locational!(ConstListWithLength, l_sqbr, elem, r_sqbr);
|
||||
|
||||
#[pymethods]
|
||||
impl ConstArrayWithLength {
|
||||
impl ConstListWithLength {
|
||||
#[staticmethod]
|
||||
pub fn new(l_sqbr: Token, r_sqbr: Token, elem: ConstExpr, length: ConstExpr) -> Self {
|
||||
Self {
|
||||
|
@ -2259,9 +2259,9 @@ impl ConstArrayWithLength {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConstArrayWithLength {
|
||||
pub fn downgrade(self) -> ArrayWithLength {
|
||||
ArrayWithLength::new(
|
||||
impl ConstListWithLength {
|
||||
pub fn downgrade(self) -> ListWithLength {
|
||||
ListWithLength::new(
|
||||
self.l_sqbr,
|
||||
self.r_sqbr,
|
||||
PosArg::new(self.elem.downgrade()),
|
||||
|
@ -2830,7 +2830,7 @@ pub enum ConstExpr {
|
|||
Lit(Literal),
|
||||
Accessor(ConstAccessor),
|
||||
App(ConstApp),
|
||||
Array(ConstArray),
|
||||
List(ConstList),
|
||||
Set(ConstSet),
|
||||
Dict(ConstDict),
|
||||
Tuple(ConstTuple),
|
||||
|
@ -2842,11 +2842,11 @@ pub enum ConstExpr {
|
|||
TypeAsc(ConstTypeAsc),
|
||||
}
|
||||
|
||||
impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Set, TypeAsc);
|
||||
impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, List, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Set, TypeAsc);
|
||||
impl_display_from_nested!(ConstExpr);
|
||||
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Set, TypeAsc);
|
||||
impl_into_py_for_enum!(ConstExpr; Lit, Accessor, App, Array, Set, Dict, Tuple, Record, Def, Lambda, BinOp, UnaryOp, TypeAsc);
|
||||
impl_from_py_for_enum!(ConstExpr; Lit(Literal), Accessor(ConstAccessor), App(ConstApp), Array(ConstArray), Set(ConstSet), Dict(ConstDict), Tuple(ConstTuple), Record(ConstRecord), Def(ConstDef), Lambda(ConstLambda), BinOp(ConstBinOp), UnaryOp(ConstUnaryOp), TypeAsc(ConstTypeAsc));
|
||||
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, List, Set, Dict, Tuple, Record, BinOp, UnaryOp, Def, Lambda, Set, TypeAsc);
|
||||
impl_into_py_for_enum!(ConstExpr; Lit, Accessor, App, List, Set, Dict, Tuple, Record, Def, Lambda, BinOp, UnaryOp, TypeAsc);
|
||||
impl_from_py_for_enum!(ConstExpr; Lit(Literal), Accessor(ConstAccessor), App(ConstApp), List(ConstList), Set(ConstSet), Dict(ConstDict), Tuple(ConstTuple), Record(ConstRecord), Def(ConstDef), Lambda(ConstLambda), BinOp(ConstBinOp), UnaryOp(ConstUnaryOp), TypeAsc(ConstTypeAsc));
|
||||
|
||||
impl TryFrom<&ParamPattern> for ConstExpr {
|
||||
type Error = ();
|
||||
|
@ -2856,7 +2856,7 @@ impl TryFrom<&ParamPattern> for ConstExpr {
|
|||
Ok(ConstExpr::Accessor(ConstAccessor::local(name.0.clone())))
|
||||
}
|
||||
ParamPattern::Lit(lit) => Ok(ConstExpr::Lit(lit.clone())),
|
||||
ParamPattern::Array(array) => ConstExpr::try_from(array),
|
||||
ParamPattern::List(list) => ConstExpr::try_from(list),
|
||||
ParamPattern::Tuple(tuple) => ConstExpr::try_from(tuple),
|
||||
_ => Err(()),
|
||||
}
|
||||
|
@ -2878,7 +2878,7 @@ impl ConstExpr {
|
|||
Self::Lit(lit) => Expr::Literal(lit),
|
||||
Self::Accessor(acc) => Expr::Accessor(acc.downgrade()),
|
||||
Self::App(app) => Expr::Call(app.downgrade()),
|
||||
Self::Array(arr) => Expr::Array(arr.downgrade()),
|
||||
Self::List(lis) => Expr::List(lis.downgrade()),
|
||||
Self::Set(set) => Expr::Set(set.downgrade()),
|
||||
Self::Dict(dict) => Expr::Dict(dict.downgrade()),
|
||||
Self::Tuple(tuple) => Expr::Tuple(tuple.downgrade()),
|
||||
|
@ -3338,19 +3338,19 @@ impl SubrTypeSpec {
|
|||
|
||||
#[pyclass]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ArrayTypeSpec {
|
||||
pub struct ListTypeSpec {
|
||||
pub sqbrs: Option<(Token, Token)>,
|
||||
pub ty: Box<TypeSpec>,
|
||||
pub len: ConstExpr,
|
||||
}
|
||||
|
||||
impl fmt::Display for ArrayTypeSpec {
|
||||
impl fmt::Display for ListTypeSpec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "[{}; {}]", self.ty, self.len)
|
||||
}
|
||||
}
|
||||
|
||||
impl Locational for ArrayTypeSpec {
|
||||
impl Locational for ListTypeSpec {
|
||||
fn loc(&self) -> Location {
|
||||
if let Some((lsqbr, rsqbr)) = &self.sqbrs {
|
||||
Location::concat(lsqbr, rsqbr)
|
||||
|
@ -3360,7 +3360,7 @@ impl Locational for ArrayTypeSpec {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArrayTypeSpec {
|
||||
impl ListTypeSpec {
|
||||
pub fn new(ty: TypeSpec, len: ConstExpr, sqbrs: Option<(Token, Token)>) -> Self {
|
||||
Self {
|
||||
ty: Box::new(ty),
|
||||
|
@ -3529,7 +3529,7 @@ impl RefinementTypeSpec {
|
|||
}
|
||||
}
|
||||
|
||||
/// * Array: `[Int; 3]`, `[Int, Ratio, Complex]`, etc.
|
||||
/// * List: `[Int; 3]`, `[Int, Ratio, Complex]`, etc.
|
||||
/// * Dict: `[Str: Str]`, etc.
|
||||
/// * And (Intersection type): Add and Sub and Mul (== Num), etc.
|
||||
/// * Not (Diff type): Pos == Nat not {0}, etc.
|
||||
|
@ -3545,7 +3545,7 @@ pub enum TypeSpec {
|
|||
Infer(Token),
|
||||
PreDeclTy(PreDeclTypeSpec),
|
||||
/* Composite types */
|
||||
Array(ArrayTypeSpec),
|
||||
List(ListTypeSpec),
|
||||
SetWithLen(SetWithLenTypeSpec),
|
||||
Tuple(TupleTypeSpec),
|
||||
Dict(DictTypeSpec),
|
||||
|
@ -3584,7 +3584,7 @@ impl fmt::Display for TypeSpec {
|
|||
Self::And(lhs, rhs) => write!(f, "{lhs} and {rhs}"),
|
||||
Self::Not(ty) => write!(f, "not {ty}"),
|
||||
Self::Or(lhs, rhs) => write!(f, "{lhs} or {rhs}"),
|
||||
Self::Array(arr) => write!(f, "{arr}"),
|
||||
Self::List(lis) => write!(f, "{lis}"),
|
||||
Self::SetWithLen(set) => write!(f, "{set}"),
|
||||
Self::Tuple(tup) => write!(f, "{tup}"),
|
||||
Self::Dict(dict) => dict.fmt(f),
|
||||
|
@ -3613,7 +3613,7 @@ impl Locational for TypeSpec {
|
|||
Location::concat(lhs.as_ref(), rhs.as_ref())
|
||||
}
|
||||
Self::Not(ty) => ty.loc(),
|
||||
Self::Array(arr) => arr.loc(),
|
||||
Self::List(lis) => lis.loc(),
|
||||
Self::SetWithLen(set) => set.loc(),
|
||||
Self::Tuple(tup) => tup.loc(),
|
||||
Self::Dict(dict) => dict.loc(),
|
||||
|
@ -4253,21 +4253,21 @@ impl Identifier {
|
|||
|
||||
#[pyclass(get_all, set_all)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct VarArrayPattern {
|
||||
pub struct VarListPattern {
|
||||
l_sqbr: Token,
|
||||
pub(crate) elems: Vars,
|
||||
r_sqbr: Token,
|
||||
}
|
||||
|
||||
impl fmt::Display for VarArrayPattern {
|
||||
impl fmt::Display for VarListPattern {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "[{}]", self.elems)
|
||||
}
|
||||
}
|
||||
|
||||
impl_locational!(VarArrayPattern, l_sqbr, r_sqbr);
|
||||
impl_locational!(VarListPattern, l_sqbr, r_sqbr);
|
||||
|
||||
impl Stream<VarSignature> for VarArrayPattern {
|
||||
impl Stream<VarSignature> for VarListPattern {
|
||||
#[inline]
|
||||
fn payload(self) -> Vec<VarSignature> {
|
||||
self.elems.payload()
|
||||
|
@ -4282,7 +4282,7 @@ impl Stream<VarSignature> for VarArrayPattern {
|
|||
}
|
||||
}
|
||||
|
||||
impl VarArrayPattern {
|
||||
impl VarListPattern {
|
||||
pub const fn new(l_sqbr: Token, elems: Vars, r_sqbr: Token) -> Self {
|
||||
Self {
|
||||
l_sqbr,
|
||||
|
@ -4439,7 +4439,7 @@ pub enum VarPattern {
|
|||
Discard(Token),
|
||||
Ident(Identifier),
|
||||
/// e.g. `[x, y, z]` of `[x, y, z] = [1, 2, 3]`
|
||||
Array(VarArrayPattern),
|
||||
List(VarListPattern),
|
||||
/// e.g. `(x, y, z)` of `(x, y, z) = (1, 2, 3)`
|
||||
Tuple(VarTuplePattern),
|
||||
// e.g. `{name; age}`, `{_; [car, cdr]}`
|
||||
|
@ -4453,7 +4453,7 @@ impl NestedDisplay for VarPattern {
|
|||
match self {
|
||||
Self::Discard(_) => write!(f, "_"),
|
||||
Self::Ident(ident) => write!(f, "{ident}"),
|
||||
Self::Array(a) => write!(f, "{a}"),
|
||||
Self::List(l) => write!(f, "{l}"),
|
||||
Self::Tuple(t) => write!(f, "{t}"),
|
||||
Self::Record(r) => write!(f, "{r}"),
|
||||
Self::DataPack(d) => write!(f, "{d}"),
|
||||
|
@ -4462,9 +4462,9 @@ impl NestedDisplay for VarPattern {
|
|||
}
|
||||
|
||||
impl_display_from_nested!(VarPattern);
|
||||
impl_locational_for_enum!(VarPattern; Discard, Ident, Array, Tuple, Record, DataPack);
|
||||
impl_into_py_for_enum!(VarPattern; Discard, Ident, Array, Tuple, Record, DataPack);
|
||||
impl_from_py_for_enum!(VarPattern; Discard(Token), Ident(Identifier), Array(VarArrayPattern), Tuple(VarTuplePattern), Record(VarRecordPattern), DataPack(VarDataPackPattern));
|
||||
impl_locational_for_enum!(VarPattern; Discard, Ident, List, Tuple, Record, DataPack);
|
||||
impl_into_py_for_enum!(VarPattern; Discard, Ident, List, Tuple, Record, DataPack);
|
||||
impl_from_py_for_enum!(VarPattern; Discard(Token), Ident(Identifier), List(VarListPattern), Tuple(VarTuplePattern), Record(VarRecordPattern), DataPack(VarDataPackPattern));
|
||||
|
||||
impl VarPattern {
|
||||
pub const fn inspect(&self) -> Option<&Str> {
|
||||
|
@ -4643,31 +4643,31 @@ impl Vars {
|
|||
|
||||
#[pyclass(get_all, set_all)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ParamArrayPattern {
|
||||
pub struct ParamListPattern {
|
||||
pub l_sqbr: Token,
|
||||
pub elems: Params,
|
||||
pub r_sqbr: Token,
|
||||
}
|
||||
|
||||
impl NestedDisplay for ParamArrayPattern {
|
||||
impl NestedDisplay for ParamListPattern {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
write!(f, "[{}]", self.elems)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(ParamArrayPattern);
|
||||
impl_locational!(ParamArrayPattern, l_sqbr, r_sqbr);
|
||||
impl_display_from_nested!(ParamListPattern);
|
||||
impl_locational!(ParamListPattern, l_sqbr, r_sqbr);
|
||||
|
||||
impl TryFrom<&ParamArrayPattern> for Expr {
|
||||
impl TryFrom<&ParamListPattern> for Expr {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &ParamArrayPattern) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: &ParamListPattern) -> Result<Self, Self::Error> {
|
||||
let mut new = vec![];
|
||||
for elem in value.elems.non_defaults.iter() {
|
||||
new.push(PosArg::new(Expr::try_from(&elem.pat)?));
|
||||
}
|
||||
let elems = Args::pos_only(new, None);
|
||||
Ok(Expr::Array(Array::Normal(NormalArray::new(
|
||||
Ok(Expr::List(List::Normal(NormalList::new(
|
||||
value.l_sqbr.clone(),
|
||||
value.r_sqbr.clone(),
|
||||
elems,
|
||||
|
@ -4675,16 +4675,16 @@ impl TryFrom<&ParamArrayPattern> for Expr {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&ParamArrayPattern> for ConstExpr {
|
||||
impl TryFrom<&ParamListPattern> for ConstExpr {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &ParamArrayPattern) -> Result<Self, Self::Error> {
|
||||
fn try_from(value: &ParamListPattern) -> Result<Self, Self::Error> {
|
||||
let mut new = vec![];
|
||||
for elem in value.elems.non_defaults.iter() {
|
||||
new.push(ConstPosArg::new(ConstExpr::try_from(&elem.pat)?));
|
||||
}
|
||||
let elems = ConstArgs::pos_only(new, None);
|
||||
Ok(ConstExpr::Array(ConstArray::Normal(ConstNormalArray::new(
|
||||
Ok(ConstExpr::List(ConstList::Normal(ConstNormalList::new(
|
||||
value.l_sqbr.clone(),
|
||||
value.r_sqbr.clone(),
|
||||
elems,
|
||||
|
@ -4694,7 +4694,7 @@ impl TryFrom<&ParamArrayPattern> for ConstExpr {
|
|||
}
|
||||
|
||||
#[pymethods]
|
||||
impl ParamArrayPattern {
|
||||
impl ParamListPattern {
|
||||
#[staticmethod]
|
||||
pub const fn new(l_sqbr: Token, elems: Params, r_sqbr: Token) -> Self {
|
||||
Self {
|
||||
|
@ -4851,7 +4851,7 @@ pub enum ParamPattern {
|
|||
VarName(VarName),
|
||||
// TODO: ConstAttr(),
|
||||
Lit(Literal),
|
||||
Array(ParamArrayPattern),
|
||||
List(ParamListPattern),
|
||||
Tuple(ParamTuplePattern),
|
||||
Record(ParamRecordPattern),
|
||||
// DataPack(ParamDataPackPattern),
|
||||
|
@ -4859,7 +4859,7 @@ pub enum ParamPattern {
|
|||
RefMut(VarName),
|
||||
}
|
||||
|
||||
impl_into_py_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut);
|
||||
impl_into_py_for_enum!(ParamPattern; Discard, VarName, Lit, List, Tuple, Record, Ref, RefMut);
|
||||
|
||||
impl NestedDisplay for ParamPattern {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||
|
@ -4867,7 +4867,7 @@ impl NestedDisplay for ParamPattern {
|
|||
Self::Discard(tok) => write!(f, "{tok}"),
|
||||
Self::VarName(var_name) => write!(f, "{var_name}"),
|
||||
Self::Lit(lit) => write!(f, "{lit}"),
|
||||
Self::Array(array) => write!(f, "{array}"),
|
||||
Self::List(list) => write!(f, "{list}"),
|
||||
Self::Tuple(tuple) => write!(f, "{tuple}"),
|
||||
Self::Record(record) => write!(f, "{record}"),
|
||||
Self::Ref(var_name) => write!(f, "ref {var_name}"),
|
||||
|
@ -4885,7 +4885,7 @@ impl TryFrom<&ParamPattern> for Expr {
|
|||
Ok(Expr::Accessor(Accessor::local(name.0.clone())))
|
||||
}
|
||||
ParamPattern::Lit(lit) => Ok(Expr::Literal(lit.clone())),
|
||||
ParamPattern::Array(array) => Expr::try_from(array),
|
||||
ParamPattern::List(list) => Expr::try_from(list),
|
||||
ParamPattern::Tuple(tuple) => Expr::try_from(tuple),
|
||||
_ => Err(()),
|
||||
}
|
||||
|
@ -4893,7 +4893,7 @@ impl TryFrom<&ParamPattern> for Expr {
|
|||
}
|
||||
|
||||
impl_display_from_nested!(ParamPattern);
|
||||
impl_locational_for_enum!(ParamPattern; Discard, VarName, Lit, Array, Tuple, Record, Ref, RefMut);
|
||||
impl_locational_for_enum!(ParamPattern; Discard, VarName, Lit, List, Tuple, Record, Ref, RefMut);
|
||||
|
||||
impl ParamPattern {
|
||||
pub const fn inspect(&self) -> Option<&Str> {
|
||||
|
@ -5890,7 +5890,7 @@ impl Compound {
|
|||
pub enum Expr {
|
||||
Literal(Literal),
|
||||
Accessor(Accessor),
|
||||
Array(Array),
|
||||
List(List),
|
||||
Tuple(Tuple),
|
||||
Dict(Dict),
|
||||
Set(Set),
|
||||
|
@ -5912,12 +5912,12 @@ pub enum Expr {
|
|||
Dummy(Dummy),
|
||||
}
|
||||
|
||||
impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_from_trait_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_nested_display_for_chunk_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_from_trait_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_display_from_nested!(Expr);
|
||||
impl_locational_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_into_py_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_from_py_for_enum!(Expr; Literal, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_locational_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_into_py_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
impl_from_py_for_enum!(Expr; Literal, Accessor, List, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAscription, Def, Methods, ClassDef, PatchDef, ReDef, Compound, InlineModule, Dummy);
|
||||
|
||||
impl Expr {
|
||||
pub fn is_match_call(&self) -> bool {
|
||||
|
@ -5939,7 +5939,7 @@ impl Expr {
|
|||
match self {
|
||||
Self::Literal(_) => "literal",
|
||||
Self::Accessor(_) => "accessor",
|
||||
Self::Array(_) => "array",
|
||||
Self::List(_) => "list",
|
||||
Self::Tuple(_) => "tuple",
|
||||
Self::Dict(_) => "dict",
|
||||
Self::Set(_) => "set",
|
||||
|
@ -6075,9 +6075,9 @@ impl Expr {
|
|||
}
|
||||
sum
|
||||
}
|
||||
Self::Array(Array::Normal(arr)) => {
|
||||
Self::List(List::Normal(lis)) => {
|
||||
let mut sum = 0;
|
||||
for elem in arr.elems.pos_args.iter() {
|
||||
for elem in lis.elems.pos_args.iter() {
|
||||
sum += elem.expr.complexity();
|
||||
}
|
||||
sum
|
||||
|
|
|
@ -27,11 +27,11 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
Ok(Signature::Subr(subr))
|
||||
}
|
||||
Expr::Array(array) => {
|
||||
let array_pat = self
|
||||
.convert_array_to_array_pat(array)
|
||||
Expr::List(list) => {
|
||||
let list_pat = self
|
||||
.convert_list_to_list_pat(list)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
let var = VarSignature::new(VarPattern::Array(array_pat), None);
|
||||
let var = VarSignature::new(VarPattern::List(list_pat), None);
|
||||
debug_exit_info!(self);
|
||||
Ok(Signature::Var(var))
|
||||
}
|
||||
|
@ -96,12 +96,12 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
fn convert_array_to_array_pat(&mut self, array: Array) -> ParseResult<VarArrayPattern> {
|
||||
fn convert_list_to_list_pat(&mut self, list: List) -> ParseResult<VarListPattern> {
|
||||
debug_call_info!(self);
|
||||
match array {
|
||||
Array::Normal(arr) => {
|
||||
match list {
|
||||
List::Normal(lis) => {
|
||||
let mut vars = Vars::empty();
|
||||
for elem in arr.elems.pos_args {
|
||||
for elem in lis.elems.pos_args {
|
||||
let pat = self
|
||||
.convert_rhs_to_sig(elem.expr)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
|
@ -117,7 +117,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Some(var) = arr.elems.var_args {
|
||||
if let Some(var) = lis.elems.var_args {
|
||||
let pat = self
|
||||
.convert_rhs_to_sig(var.expr)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
|
@ -133,21 +133,21 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
}
|
||||
let pat = VarArrayPattern::new(arr.l_sqbr, vars, arr.r_sqbr);
|
||||
let pat = VarListPattern::new(lis.l_sqbr, vars, lis.r_sqbr);
|
||||
debug_exit_info!(self);
|
||||
Ok(pat)
|
||||
}
|
||||
Array::Comprehension(arr) => {
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, arr.loc());
|
||||
List::Comprehension(lis) => {
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, lis.loc());
|
||||
self.errs.push(err);
|
||||
debug_exit_info!(self);
|
||||
Err(())
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
List::WithLength(lis) => {
|
||||
let err = ParseError::feature_error(
|
||||
line!() as usize,
|
||||
arr.loc(),
|
||||
"array-with-length pattern",
|
||||
lis.loc(),
|
||||
"list-with-length pattern",
|
||||
);
|
||||
self.errs.push(err);
|
||||
debug_exit_info!(self);
|
||||
|
@ -480,11 +480,11 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
Ok(param)
|
||||
}
|
||||
Expr::Array(array) => {
|
||||
let array_pat = self
|
||||
.convert_array_to_param_array_pat(array)
|
||||
Expr::List(list) => {
|
||||
let list_pat = self
|
||||
.convert_list_to_param_list_pat(list)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
let pat = ParamPattern::Array(array_pat);
|
||||
let pat = ParamPattern::List(list_pat);
|
||||
let param = NonDefaultParamSignature::new(pat, None);
|
||||
debug_exit_info!(self);
|
||||
Ok(param)
|
||||
|
@ -570,17 +570,17 @@ impl Parser {
|
|||
Ok(param)
|
||||
}
|
||||
|
||||
fn convert_array_to_param_array_pat(&mut self, array: Array) -> ParseResult<ParamArrayPattern> {
|
||||
fn convert_list_to_param_list_pat(&mut self, list: List) -> ParseResult<ParamListPattern> {
|
||||
debug_call_info!(self);
|
||||
match array {
|
||||
Array::Normal(arr) => {
|
||||
match list {
|
||||
List::Normal(lis) => {
|
||||
let mut params = vec![];
|
||||
for arg in arr.elems.into_iters().0 {
|
||||
for arg in lis.elems.into_iters().0 {
|
||||
params.push(self.convert_pos_arg_to_non_default_param(arg, false)?);
|
||||
}
|
||||
let params = Params::new(params, None, vec![], None, None);
|
||||
debug_exit_info!(self);
|
||||
Ok(ParamArrayPattern::new(arr.l_sqbr, params, arr.r_sqbr))
|
||||
Ok(ParamListPattern::new(lis.l_sqbr, params, lis.r_sqbr))
|
||||
}
|
||||
other => {
|
||||
let err = ParseError::feature_error(line!() as usize, other.loc(), "?");
|
||||
|
@ -717,11 +717,11 @@ impl Parser {
|
|||
debug_exit_info!(self);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
}
|
||||
Expr::Array(array) => {
|
||||
let arr = self
|
||||
.convert_array_to_param_array_pat(array)
|
||||
Expr::List(list) => {
|
||||
let lis = self
|
||||
.convert_list_to_param_list_pat(list)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
let param = NonDefaultParamSignature::new(ParamPattern::Array(arr), None);
|
||||
let param = NonDefaultParamSignature::new(ParamPattern::List(lis), None);
|
||||
let params = Params::single(param);
|
||||
debug_exit_info!(self);
|
||||
Ok(LambdaSignature::new(params, None, TypeBoundSpecs::empty()))
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
//! e.g. Literal parameters, Multi assignment
|
||||
//! 型チェックなどによる検証は行わない
|
||||
|
||||
use erg_common::consts::PYTHON_MODE;
|
||||
use erg_common::error::Location;
|
||||
use erg_common::fresh::FreshNameGenerator;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
|
@ -12,16 +11,15 @@ use erg_common::{debug_power_assert, Str};
|
|||
use erg_common::{enum_unwrap, get_hash, log, set};
|
||||
|
||||
use crate::ast::{
|
||||
Accessor, Args, Array, ArrayComprehension, ArrayTypeSpec, ArrayWithLength, BinOp, Block, Call,
|
||||
ClassAttr, ClassAttrs, ClassDef, Compound, ConstExpr, DataPack, Def, DefBody, DefId,
|
||||
DefaultParamSignature, Dict, Dummy, Expr, GuardClause, Identifier, InlineModule, KeyValue,
|
||||
KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module,
|
||||
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
|
||||
ParamPattern, ParamRecordAttr, ParamTuplePattern, Params, PatchDef, PosArg, ReDef, Record,
|
||||
RecordAttrOrIdent, RecordAttrs, RecordTypeSpec, Set as astSet, SetComprehension, SetWithLength,
|
||||
Signature, SubrSignature, Tuple, TupleTypeSpec, TypeAppArgs, TypeAppArgsKind, TypeBoundSpecs,
|
||||
TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
||||
VisModifierSpec, AST,
|
||||
Accessor, Args, BinOp, Block, Call, ClassAttr, ClassAttrs, ClassDef, Compound, ConstExpr,
|
||||
DataPack, Def, DefBody, DefId, DefaultParamSignature, Dict, Dummy, Expr, GuardClause,
|
||||
Identifier, InlineModule, KeyValue, KwArg, Lambda, LambdaSignature, List, ListComprehension,
|
||||
ListTypeSpec, ListWithLength, Literal, Methods, MixedRecord, Module, NonDefaultParamSignature,
|
||||
NormalDict, NormalList, NormalRecord, NormalSet, NormalTuple, ParamPattern, ParamRecordAttr,
|
||||
ParamTuplePattern, Params, PatchDef, PosArg, ReDef, Record, RecordAttrOrIdent, RecordAttrs,
|
||||
RecordTypeSpec, Set as astSet, SetComprehension, SetWithLength, Signature, SubrSignature,
|
||||
Tuple, TupleTypeSpec, TypeAppArgs, TypeAppArgsKind, TypeBoundSpecs, TypeSpec, TypeSpecWithOp,
|
||||
UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature, VisModifierSpec, AST,
|
||||
};
|
||||
use crate::token::{Token, TokenKind, COLON, DOT};
|
||||
|
||||
|
@ -57,7 +55,7 @@ pub fn symop_to_dname(op: &str) -> Option<&'static str> {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum BufIndex<'i> {
|
||||
Array(usize),
|
||||
List(usize),
|
||||
Tuple(usize),
|
||||
Record(&'i Identifier),
|
||||
}
|
||||
|
@ -189,34 +187,34 @@ impl Desugarer {
|
|||
};
|
||||
Expr::DataPack(DataPack::new(class, pack.connector, args))
|
||||
}
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
let (elems, ..) = arr.elems.deconstruct();
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
let (elems, ..) = lis.elems.deconstruct();
|
||||
let elems = elems
|
||||
.into_iter()
|
||||
.map(|elem| PosArg::new(desugar(elem.expr)))
|
||||
.collect();
|
||||
let elems = Args::pos_only(elems, None);
|
||||
let arr = NormalArray::new(arr.l_sqbr, arr.r_sqbr, elems);
|
||||
Expr::Array(Array::Normal(arr))
|
||||
let lis = NormalList::new(lis.l_sqbr, lis.r_sqbr, elems);
|
||||
Expr::List(List::Normal(lis))
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
let elem = PosArg::new(desugar(arr.elem.expr));
|
||||
let len = desugar(*arr.len);
|
||||
let arr = ArrayWithLength::new(arr.l_sqbr, arr.r_sqbr, elem, len);
|
||||
Expr::Array(Array::WithLength(arr))
|
||||
List::WithLength(lis) => {
|
||||
let elem = PosArg::new(desugar(lis.elem.expr));
|
||||
let len = desugar(*lis.len);
|
||||
let lis = ListWithLength::new(lis.l_sqbr, lis.r_sqbr, elem, len);
|
||||
Expr::List(List::WithLength(lis))
|
||||
}
|
||||
Array::Comprehension(arr) => {
|
||||
let layout = arr.layout.map(|ex| desugar(*ex));
|
||||
let generators = arr
|
||||
List::Comprehension(lis) => {
|
||||
let layout = lis.layout.map(|ex| desugar(*ex));
|
||||
let generators = lis
|
||||
.generators
|
||||
.into_iter()
|
||||
.map(|(ident, gen)| (ident, desugar(gen)))
|
||||
.collect();
|
||||
let guard = arr.guard.map(|ex| desugar(*ex));
|
||||
let arr =
|
||||
ArrayComprehension::new(arr.l_sqbr, arr.r_sqbr, layout, generators, guard);
|
||||
Expr::Array(Array::Comprehension(arr))
|
||||
let guard = lis.guard.map(|ex| desugar(*ex));
|
||||
let lis =
|
||||
ListComprehension::new(lis.l_sqbr, lis.r_sqbr, layout, generators, guard);
|
||||
Expr::List(List::Comprehension(lis))
|
||||
}
|
||||
},
|
||||
Expr::Tuple(tuple) => match tuple {
|
||||
|
@ -718,16 +716,16 @@ impl Desugarer {
|
|||
self.desugar_rest_values(new, var, &buf_name, elems_len);
|
||||
}
|
||||
}
|
||||
VarPattern::Array(arr) => {
|
||||
VarPattern::List(lis) => {
|
||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
||||
let body = self.desugar_pattern_in_body(body);
|
||||
let buf_def = Def::new(buf_sig, body);
|
||||
new.push(Expr::Def(buf_def));
|
||||
for (n, elem) in arr.elems.iter().enumerate() {
|
||||
self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Array(n));
|
||||
for (n, elem) in lis.elems.iter().enumerate() {
|
||||
self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::List(n));
|
||||
}
|
||||
let elems_len = arr.elems.len();
|
||||
if let Some(var) = arr.elems.starred.as_ref() {
|
||||
let elems_len = lis.elems.len();
|
||||
if let Some(var) = lis.elems.starred.as_ref() {
|
||||
self.desugar_rest_values(new, var, &buf_name, elems_len);
|
||||
}
|
||||
}
|
||||
|
@ -886,7 +884,7 @@ impl Desugarer {
|
|||
);
|
||||
let acc = match buf_index {
|
||||
BufIndex::Tuple(n) => obj.tuple_attr(Literal::nat(n, sig.ln_begin().unwrap_or(1))),
|
||||
BufIndex::Array(n) => {
|
||||
BufIndex::List(n) => {
|
||||
let r_brace = Token::new(
|
||||
TokenKind::RBrace,
|
||||
"]",
|
||||
|
@ -921,17 +919,12 @@ impl Desugarer {
|
|||
);
|
||||
}
|
||||
}
|
||||
VarPattern::Array(arr) => {
|
||||
VarPattern::List(lis) => {
|
||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(sig.loc(), None);
|
||||
let buf_def = Def::new(buf_sig, body);
|
||||
new_module.push(Expr::Def(buf_def));
|
||||
for (n, elem) in arr.elems.iter().enumerate() {
|
||||
self.desugar_nested_var_pattern(
|
||||
new_module,
|
||||
elem,
|
||||
&buf_name,
|
||||
BufIndex::Array(n),
|
||||
);
|
||||
for (n, elem) in lis.elems.iter().enumerate() {
|
||||
self.desugar_nested_var_pattern(new_module, elem, &buf_name, BufIndex::List(n));
|
||||
}
|
||||
}
|
||||
VarPattern::Record(rec) => {
|
||||
|
@ -1054,7 +1047,7 @@ impl Desugarer {
|
|||
NormalRecord::new(record.l_brace, record.r_brace, attrs)
|
||||
}
|
||||
|
||||
fn dummy_array_expr(len: Literal) -> Expr {
|
||||
fn dummy_list_expr(len: Literal) -> Expr {
|
||||
let l_sqbr = Token {
|
||||
content: "[".into(),
|
||||
kind: TokenKind::LSqBr,
|
||||
|
@ -1066,13 +1059,13 @@ impl Desugarer {
|
|||
..len.token
|
||||
};
|
||||
let elem = Expr::local("Obj", l_sqbr.lineno, l_sqbr.col_begin, l_sqbr.col_end);
|
||||
let array = Array::WithLength(ArrayWithLength::new(
|
||||
let list = List::WithLength(ListWithLength::new(
|
||||
l_sqbr,
|
||||
r_sqbr,
|
||||
PosArg::new(elem),
|
||||
Expr::Literal(len),
|
||||
));
|
||||
Expr::Array(array)
|
||||
Expr::List(list)
|
||||
}
|
||||
|
||||
fn dummy_set_expr(lit: Literal) -> Expr {
|
||||
|
@ -1271,11 +1264,11 @@ impl Desugarer {
|
|||
param.pat = buf_param;
|
||||
guards
|
||||
}
|
||||
ParamPattern::Array(arr) => {
|
||||
ParamPattern::List(lis) => {
|
||||
fn const_check(expr: &Expr) -> bool {
|
||||
match &expr {
|
||||
Expr::Accessor(Accessor::Ident(ident)) => ident.is_const(),
|
||||
Expr::Array(Array::Normal(arr)) => arr
|
||||
Expr::List(List::Normal(lis)) => lis
|
||||
.elems
|
||||
.pos_args()
|
||||
.iter()
|
||||
|
@ -1283,21 +1276,21 @@ impl Desugarer {
|
|||
_ => true,
|
||||
}
|
||||
}
|
||||
let expr = Expr::try_from(&*arr).and_then(|expr| {
|
||||
let expr = Expr::try_from(&*lis).and_then(|expr| {
|
||||
if const_check(&expr) {
|
||||
Ok(expr)
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
});
|
||||
let (buf_name, buf_param) = self.gen_buf_nd_param(arr.loc());
|
||||
guards.push(Self::len_guard(buf_name.clone(), arr.elems.len(), arr));
|
||||
for (n, elem) in arr.elems.non_defaults.iter_mut().enumerate() {
|
||||
let gs = self.desugar_nested_param_pattern(elem, &buf_name, BufIndex::Array(n));
|
||||
let (buf_name, buf_param) = self.gen_buf_nd_param(lis.loc());
|
||||
guards.push(Self::len_guard(buf_name.clone(), lis.elems.len(), lis));
|
||||
for (n, elem) in lis.elems.non_defaults.iter_mut().enumerate() {
|
||||
let gs = self.desugar_nested_param_pattern(elem, &buf_name, BufIndex::List(n));
|
||||
guards.extend(gs);
|
||||
}
|
||||
if param.t_spec.is_none() {
|
||||
let len = arr.elems.non_defaults.len();
|
||||
let len = lis.elems.non_defaults.len();
|
||||
let len = Literal::new(Token::new_fake(
|
||||
TokenKind::NatLit,
|
||||
len.to_string(),
|
||||
|
@ -1306,10 +1299,10 @@ impl Desugarer {
|
|||
0,
|
||||
));
|
||||
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
||||
let t_spec = ArrayTypeSpec::new(
|
||||
let t_spec = ListTypeSpec::new(
|
||||
TypeSpec::Infer(infer),
|
||||
ConstExpr::Lit(len.clone()),
|
||||
Some((arr.l_sqbr.clone(), arr.r_sqbr.clone())),
|
||||
Some((lis.l_sqbr.clone(), lis.r_sqbr.clone())),
|
||||
);
|
||||
// [1, 2] -> ...
|
||||
// => _: {[1, 2]} -> ...
|
||||
|
@ -1320,11 +1313,11 @@ impl Desugarer {
|
|||
Args::single(PosArg::new(expr)),
|
||||
)))
|
||||
} else {
|
||||
Self::dummy_array_expr(len)
|
||||
Self::dummy_list_expr(len)
|
||||
};
|
||||
param.t_spec = Some(TypeSpecWithOp::new(
|
||||
Token::dummy(TokenKind::Colon, ":"),
|
||||
TypeSpec::Array(t_spec),
|
||||
TypeSpec::List(t_spec),
|
||||
t_spec_as_expr,
|
||||
));
|
||||
}
|
||||
|
@ -1419,7 +1412,7 @@ impl Desugarer {
|
|||
);
|
||||
let acc = match buf_index {
|
||||
BufIndex::Tuple(n) => obj.tuple_attr(Literal::nat(n, sig.ln_begin().unwrap_or(1))),
|
||||
BufIndex::Array(n) => {
|
||||
BufIndex::List(n) => {
|
||||
let r_brace = Token::new(
|
||||
TokenKind::RBrace,
|
||||
"]",
|
||||
|
@ -1490,8 +1483,8 @@ impl Desugarer {
|
|||
sig.pat = buf_sig;
|
||||
guards
|
||||
}
|
||||
ParamPattern::Array(arr) => {
|
||||
let (buf_name, buf_sig) = self.gen_buf_nd_param(arr.loc());
|
||||
ParamPattern::List(lis) => {
|
||||
let (buf_name, buf_sig) = self.gen_buf_nd_param(lis.loc());
|
||||
let def = Def::new(
|
||||
Signature::Var(VarSignature::new(
|
||||
VarPattern::Ident(Identifier::private(Str::from(&buf_name))),
|
||||
|
@ -1500,13 +1493,13 @@ impl Desugarer {
|
|||
body,
|
||||
);
|
||||
guards.push(GuardClause::Bind(def));
|
||||
guards.push(Self::len_guard(buf_name.clone(), arr.elems.len(), arr));
|
||||
for (n, elem) in arr.elems.non_defaults.iter_mut().enumerate() {
|
||||
let gs = self.desugar_nested_param_pattern(elem, &buf_name, BufIndex::Array(n));
|
||||
guards.push(Self::len_guard(buf_name.clone(), lis.elems.len(), lis));
|
||||
for (n, elem) in lis.elems.non_defaults.iter_mut().enumerate() {
|
||||
let gs = self.desugar_nested_param_pattern(elem, &buf_name, BufIndex::List(n));
|
||||
guards.extend(gs);
|
||||
}
|
||||
if sig.t_spec.is_none() {
|
||||
let len = arr.elems.non_defaults.len();
|
||||
let len = lis.elems.non_defaults.len();
|
||||
let len = Literal::new(Token::new_fake(
|
||||
TokenKind::NatLit,
|
||||
len.to_string(),
|
||||
|
@ -1515,15 +1508,15 @@ impl Desugarer {
|
|||
0,
|
||||
));
|
||||
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
||||
let t_spec = ArrayTypeSpec::new(
|
||||
let t_spec = ListTypeSpec::new(
|
||||
TypeSpec::Infer(infer),
|
||||
ConstExpr::Lit(len.clone()),
|
||||
Some((arr.l_sqbr.clone(), arr.r_sqbr.clone())),
|
||||
Some((lis.l_sqbr.clone(), lis.r_sqbr.clone())),
|
||||
);
|
||||
let t_spec_as_expr = Self::dummy_array_expr(len);
|
||||
let t_spec_as_expr = Self::dummy_list_expr(len);
|
||||
sig.t_spec = Some(TypeSpecWithOp::new(
|
||||
COLON,
|
||||
TypeSpec::Array(t_spec),
|
||||
TypeSpec::List(t_spec),
|
||||
t_spec_as_expr,
|
||||
));
|
||||
}
|
||||
|
@ -1754,8 +1747,8 @@ impl Desugarer {
|
|||
}
|
||||
|
||||
/// ```erg
|
||||
/// [y | x <- xs] ==> array(map(x -> y, xs))
|
||||
/// [(a, b) | x <- xs; y <- ys] ==> array(map(((x, y),) -> (a, b), itertools.product(xs, ys)))
|
||||
/// [y | x <- xs] ==> list(map(x -> y, xs))
|
||||
/// [(a, b) | x <- xs; y <- ys] ==> list(map(((x, y),) -> (a, b), itertools.product(xs, ys)))
|
||||
/// {k: v | x <- xs} ==> dict(map(x -> (k, v), xs))
|
||||
/// {y | x <- xs} ==> set(map(x -> y, xs))
|
||||
/// {x <- xs | x <= 10} ==> set(filter(x -> x <= 10, xs))
|
||||
|
@ -1763,15 +1756,16 @@ impl Desugarer {
|
|||
/// ```
|
||||
fn rec_desugar_comprehension(expr: Expr) -> Expr {
|
||||
match expr {
|
||||
Expr::Array(Array::Comprehension(mut comp)) => {
|
||||
Expr::List(List::Comprehension(mut comp)) => {
|
||||
debug_power_assert!(comp.generators.len(), >, 0);
|
||||
if comp.generators.len() != 1 {
|
||||
return Expr::Array(Array::Comprehension(comp));
|
||||
return Expr::List(List::Comprehension(comp));
|
||||
}
|
||||
let (ident, iter) = comp.generators.remove(0);
|
||||
let iterator = Self::desugar_layout_and_guard(ident, iter, comp.layout, comp.guard);
|
||||
let array = if PYTHON_MODE { "list" } else { "array" };
|
||||
Identifier::auto(array.into()).call1(iterator.into()).into()
|
||||
Identifier::auto("list".into())
|
||||
.call1(iterator.into())
|
||||
.into()
|
||||
}
|
||||
Expr::Dict(Dict::Comprehension(mut comp)) => {
|
||||
debug_power_assert!(comp.generators.len(), >, 0);
|
||||
|
|
|
@ -518,7 +518,7 @@ impl LexError {
|
|||
let method = StyledStr::new("メソッド", Some(HINT), Some(ATTR));
|
||||
let lit = StyledStr::new("NatLit", Some(HINT), Some(ATTR));
|
||||
let newline = StyledStr::new("改行", Some(HINT), Some(ATTR));
|
||||
let arr = StyledStr::new("配列", Some(HINT), Some(ATTR));
|
||||
let arr = StyledStr::new("リスト", Some(HINT), Some(ATTR));
|
||||
format!("予期: {method}、{lit}、{newline}、{arr}")
|
||||
},
|
||||
"simplified_chinese" => {
|
||||
|
@ -539,7 +539,7 @@ impl LexError {
|
|||
let method = StyledStr::new("method", Some(HINT), Some(ATTR));
|
||||
let lit = StyledStr::new("NatLit", Some(HINT), Some(ATTR));
|
||||
let newline = StyledStr::new("newline", Some(HINT), Some(ATTR));
|
||||
let arr = StyledStr::new("array", Some(HINT), Some(ATTR));
|
||||
let arr = StyledStr::new("list", Some(HINT), Some(ATTR));
|
||||
format!("expect: {method}, {lit}, {newline}, {arr}")
|
||||
},
|
||||
);
|
||||
|
|
|
@ -40,7 +40,7 @@ pub fn erg_parser(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|||
m.add_function(wrap_pyfunction!(_parse, m)?)?;
|
||||
let expr = PyModule::new(py, "expr")?;
|
||||
expr.add_class::<ast::Literal>()?;
|
||||
expr.add_class::<ast::NormalArray>()?;
|
||||
expr.add_class::<ast::NormalList>()?;
|
||||
expr.add_class::<ast::NormalTuple>()?;
|
||||
expr.add_class::<ast::NormalDict>()?;
|
||||
expr.add_class::<ast::NormalSet>()?;
|
||||
|
@ -71,7 +71,7 @@ pub fn erg_parser(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|||
ast.add_class::<ast::TupleAttribute>()?;
|
||||
ast.add_class::<ast::Subscript>()?;
|
||||
ast.add_class::<ast::TypeApp>()?;
|
||||
ast.add_class::<ast::NormalArray>()?;
|
||||
ast.add_class::<ast::NormalList>()?;
|
||||
ast.add_class::<ast::NormalTuple>()?;
|
||||
ast.add_class::<ast::NormalDict>()?;
|
||||
ast.add_class::<ast::NormalSet>()?;
|
||||
|
|
|
@ -135,7 +135,7 @@ enum ArgKind {
|
|||
KwVar(PosArg),
|
||||
}
|
||||
|
||||
pub enum ArrayInner {
|
||||
pub enum ListInner {
|
||||
Normal(Args),
|
||||
WithLength(PosArg, Expr),
|
||||
Comprehension {
|
||||
|
@ -145,7 +145,7 @@ pub enum ArrayInner {
|
|||
},
|
||||
}
|
||||
|
||||
impl ArrayInner {
|
||||
impl ListInner {
|
||||
pub const fn comp(
|
||||
layout: Option<Expr>,
|
||||
generators: Vec<(Identifier, Expr)>,
|
||||
|
@ -857,7 +857,7 @@ impl Parser {
|
|||
Ok(acc)
|
||||
}
|
||||
|
||||
fn try_reduce_array_elems(&mut self) -> ParseResult<ArrayInner> {
|
||||
fn try_reduce_list_elems(&mut self) -> ParseResult<ListInner> {
|
||||
debug_call_info!(self);
|
||||
if self.cur_is(EOF) {
|
||||
let tk = self.tokens.last().unwrap();
|
||||
|
@ -868,7 +868,7 @@ impl Parser {
|
|||
if self.cur_category_is(TC::REnclosure) {
|
||||
let args = Args::empty();
|
||||
debug_exit_info!(self);
|
||||
return Ok(ArrayInner::Normal(args));
|
||||
return Ok(ListInner::Normal(args));
|
||||
}
|
||||
let first = self
|
||||
.try_reduce_elem()
|
||||
|
@ -891,7 +891,7 @@ impl Parser {
|
|||
self.stack_dec(fn_name!())
|
||||
})?;
|
||||
debug_exit_info!(self);
|
||||
return Ok(ArrayInner::WithLength(elems.remove_pos(0), len));
|
||||
return Ok(ListInner::WithLength(elems.remove_pos(0), len));
|
||||
}
|
||||
Some(PreStar) => {
|
||||
self.lpop();
|
||||
|
@ -900,7 +900,7 @@ impl Parser {
|
|||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
elems.set_var_args(PosArg::new(rest));
|
||||
debug_exit_info!(self);
|
||||
return Ok(ArrayInner::Normal(elems));
|
||||
return Ok(ListInner::Normal(elems));
|
||||
}
|
||||
Some(Inclusion) => {
|
||||
self.lpop();
|
||||
|
@ -925,7 +925,7 @@ impl Parser {
|
|||
.try_reduce_expr(false, false, false, false)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
debug_exit_info!(self);
|
||||
return Ok(ArrayInner::comp(None, generators, Some(guard)));
|
||||
return Ok(ListInner::comp(None, generators, Some(guard)));
|
||||
}
|
||||
Some(VBar) => {
|
||||
self.lpop();
|
||||
|
@ -956,7 +956,7 @@ impl Parser {
|
|||
None
|
||||
};
|
||||
debug_exit_info!(self);
|
||||
return Ok(ArrayInner::comp(Some(elem), generators, guard));
|
||||
return Ok(ListInner::comp(Some(elem), generators, guard));
|
||||
}
|
||||
Some(RParen | RSqBr | RBrace | Dedent | Comma) => {}
|
||||
Some(_) => {
|
||||
|
@ -1027,7 +1027,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
debug_exit_info!(self);
|
||||
Ok(ArrayInner::Normal(elems))
|
||||
Ok(ListInner::Normal(elems))
|
||||
}
|
||||
|
||||
fn try_reduce_elem(&mut self) -> ParseResult<PosArg> {
|
||||
|
@ -2601,11 +2601,11 @@ impl Parser {
|
|||
Ok(expr)
|
||||
}
|
||||
Some(t) if t.is(LSqBr) => {
|
||||
let array = self
|
||||
.try_reduce_array()
|
||||
let list = self
|
||||
.try_reduce_list()
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
debug_exit_info!(self);
|
||||
Ok(Expr::Array(array))
|
||||
Ok(Expr::List(list))
|
||||
}
|
||||
Some(t) if t.is(LBrace) => {
|
||||
match self
|
||||
|
@ -2874,15 +2874,15 @@ impl Parser {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn try_reduce_array(&mut self) -> ParseResult<Array> {
|
||||
fn try_reduce_list(&mut self) -> ParseResult<List> {
|
||||
debug_call_info!(self);
|
||||
let l_sqbr = expect_pop!(self, fail_next LSqBr);
|
||||
let inner = self
|
||||
.try_reduce_array_elems()
|
||||
.try_reduce_list_elems()
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
let r_sqbr = expect_pop!(self, fail_next RSqBr);
|
||||
let arr = match inner {
|
||||
ArrayInner::Normal(mut elems) => {
|
||||
let lis = match inner {
|
||||
ListInner::Normal(mut elems) => {
|
||||
let elems = if elems
|
||||
.pos_args()
|
||||
.first()
|
||||
|
@ -2896,21 +2896,21 @@ impl Parser {
|
|||
} else {
|
||||
elems
|
||||
};
|
||||
Array::Normal(NormalArray::new(l_sqbr, r_sqbr, elems))
|
||||
List::Normal(NormalList::new(l_sqbr, r_sqbr, elems))
|
||||
}
|
||||
ArrayInner::WithLength(elem, len) => {
|
||||
Array::WithLength(ArrayWithLength::new(l_sqbr, r_sqbr, elem, len))
|
||||
ListInner::WithLength(elem, len) => {
|
||||
List::WithLength(ListWithLength::new(l_sqbr, r_sqbr, elem, len))
|
||||
}
|
||||
ArrayInner::Comprehension {
|
||||
ListInner::Comprehension {
|
||||
layout,
|
||||
generators,
|
||||
guard,
|
||||
} => Array::Comprehension(ArrayComprehension::new(
|
||||
} => List::Comprehension(ListComprehension::new(
|
||||
l_sqbr, r_sqbr, layout, generators, guard,
|
||||
)),
|
||||
};
|
||||
debug_exit_info!(self);
|
||||
Ok(arr)
|
||||
Ok(lis)
|
||||
}
|
||||
|
||||
/// Set, Dict, Record
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#[array]#
|
||||
#[list]#
|
||||
[1,,]
|
||||
[Nat;2;] # [Nat; 1]
|
||||
a = [1: "a"] # [1: Nat]
|
||||
|
@ -37,4 +37,4 @@ t = (1, True, "a")
|
|||
t.-1
|
||||
|
||||
r = {name = "John Doe"; age = 21; from="Unknown"}
|
||||
r.attr
|
||||
r.attr
|
||||
|
|
|
@ -26,28 +26,28 @@ impl Parser {
|
|||
"complex const accessor",
|
||||
)),
|
||||
},
|
||||
Expr::Array(array) => match array {
|
||||
Array::Normal(arr) => {
|
||||
let (elems, ..) = arr.elems.deconstruct();
|
||||
Expr::List(list) => match list {
|
||||
List::Normal(lis) => {
|
||||
let (elems, ..) = lis.elems.deconstruct();
|
||||
let mut const_elems = vec![];
|
||||
for elem in elems.into_iter() {
|
||||
let const_expr = Self::validate_const_expr(elem.expr)?;
|
||||
const_elems.push(ConstPosArg::new(const_expr));
|
||||
}
|
||||
let elems = ConstArgs::pos_only(const_elems, None);
|
||||
let const_arr = ConstNormalArray::new(arr.l_sqbr, arr.r_sqbr, elems, None);
|
||||
Ok(ConstExpr::Array(ConstArray::Normal(const_arr)))
|
||||
let const_lis = ConstNormalList::new(lis.l_sqbr, lis.r_sqbr, elems, None);
|
||||
Ok(ConstExpr::List(ConstList::Normal(const_lis)))
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
let elem = Self::validate_const_expr(arr.elem.expr)?;
|
||||
let len = Self::validate_const_expr(*arr.len)?;
|
||||
let const_arr = ConstArrayWithLength::new(arr.l_sqbr, arr.r_sqbr, elem, len);
|
||||
Ok(ConstExpr::Array(ConstArray::WithLength(const_arr)))
|
||||
List::WithLength(lis) => {
|
||||
let elem = Self::validate_const_expr(lis.elem.expr)?;
|
||||
let len = Self::validate_const_expr(*lis.len)?;
|
||||
let const_lis = ConstListWithLength::new(lis.l_sqbr, lis.r_sqbr, elem, len);
|
||||
Ok(ConstExpr::List(ConstList::WithLength(const_lis)))
|
||||
}
|
||||
other => Err(ParseError::feature_error(
|
||||
line!() as usize,
|
||||
other.loc(),
|
||||
"const array comprehension",
|
||||
"const list comprehension",
|
||||
)),
|
||||
},
|
||||
Expr::Set(set) => match set {
|
||||
|
@ -375,25 +375,25 @@ impl Parser {
|
|||
))
|
||||
}
|
||||
|
||||
fn array_to_array_type_spec(array: Array) -> Result<ArrayTypeSpec, ParseError> {
|
||||
match array {
|
||||
Array::Normal(arr) => {
|
||||
fn list_to_list_type_spec(list: List) -> Result<ListTypeSpec, ParseError> {
|
||||
match list {
|
||||
List::Normal(lis) => {
|
||||
// TODO: add hint
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, arr.loc());
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, lis.loc());
|
||||
Err(err)
|
||||
}
|
||||
Array::WithLength(arr) => {
|
||||
let t_spec = Self::expr_to_type_spec(arr.elem.expr)?;
|
||||
let len = Self::validate_const_expr(*arr.len)?;
|
||||
Ok(ArrayTypeSpec::new(
|
||||
List::WithLength(lis) => {
|
||||
let t_spec = Self::expr_to_type_spec(lis.elem.expr)?;
|
||||
let len = Self::validate_const_expr(*lis.len)?;
|
||||
Ok(ListTypeSpec::new(
|
||||
t_spec,
|
||||
len,
|
||||
Some((arr.l_sqbr, arr.r_sqbr)),
|
||||
Some((lis.l_sqbr, lis.r_sqbr)),
|
||||
))
|
||||
}
|
||||
Array::Comprehension(arr) => {
|
||||
List::Comprehension(lis) => {
|
||||
// TODO: add hint
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, arr.loc());
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, lis.loc());
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
@ -508,9 +508,9 @@ impl Parser {
|
|||
let lambda = Self::lambda_to_subr_type_spec(lambda)?;
|
||||
Ok(TypeSpec::Subr(lambda))
|
||||
}
|
||||
Expr::Array(array) => {
|
||||
let array = Self::array_to_array_type_spec(array)?;
|
||||
Ok(TypeSpec::Array(array))
|
||||
Expr::List(list) => {
|
||||
let list = Self::list_to_list_type_spec(list)?;
|
||||
Ok(TypeSpec::List(list))
|
||||
}
|
||||
Expr::Set(set) => {
|
||||
let set = Self::set_to_set_type_spec(set)?;
|
||||
|
|
|
@ -52,7 +52,7 @@ Returns the class of `object`.
|
|||
However, since classes cannot be compared, use `object in Class` instead of `classof(object) == Class` if you want to judge instances.
|
||||
The structure type determined at compile time is obtained with `Typeof`.
|
||||
|
||||
## Iterator, Array generation system
|
||||
## Iterator, List generation system
|
||||
|
||||
### repeat|T|(x: T) -> RepeatIterator T
|
||||
|
||||
|
@ -96,11 +96,11 @@ match jan:
|
|||
_ -> log "Other"
|
||||
```
|
||||
|
||||
|
||||
### Inherit
|
||||
|
||||
Inherit classes. You can use the methods of the parent class ('Super') as is. The second parameter 'Layout' can specify a new layout.
|
||||
It must be 'Super.Base:> Layout'.
|
||||
|
||||
```python
|
||||
@ Inheritable
|
||||
C = Class {i = Int}
|
||||
|
|
|
@ -20,5 +20,5 @@ Infers a function given its arguments and return value.
|
|||
|
||||
```python
|
||||
1.guess((1,), 2) # <Int.__add__ method>
|
||||
[1, 2].guess((3, 4), [1, 2, 3, 4]) # <Array(T, N).concat method>
|
||||
```
|
||||
[1, 2].guess((3, 4), [1, 2, 3, 4]) # <List(T, N).concat method>
|
||||
```
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Array! T, N
|
||||
# List! T, N
|
||||
|
||||
Variable length array at compile time. `[t; n]` There is also a sugar cane syntax.
|
||||
|
||||
|
@ -11,17 +11,14 @@ Variable length array at compile time. `[t; n]` There is also a sugar cane synta
|
|||
* sample!(ref! self) -> T
|
||||
* sample! ref! self, M: Nat -> [T; M]
|
||||
|
||||
|
||||
Select a random element and return a copy.
|
||||
|
||||
* shuffle!(ref! self)
|
||||
|
||||
|
||||
Shuffle contents.
|
||||
|
||||
* assert_len ref! self(_ ~> N, ...), N: Nat -> () or Panic
|
||||
|
||||
|
||||
Verify length
|
||||
Incorrect length will cause `panic`
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Array T: Type, N: Nat
|
||||
# List T: Type, N: Nat
|
||||
|
||||
`[T; N]` is syntactic sugar. `N` can be emitted (`[T; _]`).
|
||||
|
||||
|
@ -23,7 +23,7 @@ assert ["a", "b", "c", "d", "e"].values_at([0, 1, 3]) == ["a", "b", "d"]
|
|||
assert all(False for _in[])
|
||||
```
|
||||
|
||||
## methods of Array T, N | T <: Eq
|
||||
## methods of List T, N | T <: Eq
|
||||
|
||||
* freq self -> [{T: Nat}]
|
||||
Returns the frequency of occurrence of an object.
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
## impl classes
|
||||
|
||||
* `Array`
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Str`
|
||||
* `Range`
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Hashable
|
||||
# Hash
|
||||
|
||||
## required methods
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
## impl classes
|
||||
|
||||
* `Array`
|
||||
* `List`
|
||||
* `Tuple`
|
||||
* `Str`
|
||||
* `Range`
|
||||
|
|
|
@ -30,10 +30,10 @@ It succeeds only if the only type with `co_consts` in the namespace is `Code` (o
|
|||
Erg closes function type checking within a module, so even if a type with `co_consts` is defined outside the module, passing an instance of it to the `consts` function will result in an error (to make this possible, you must use `Structural`, described below). This constraint allows the `consts` function to infer.
|
||||
|
||||
When a class attribute is defined, the type inferrer keeps track of the "attribute" and "defining class, attribute type" pairs.
|
||||
In the case of ``co_consts``, this pair is `{co_consts: {Code, Array(Obj, _)}}`.
|
||||
In the case of ``co_consts``, this pair is `{co_consts: {Code, List(Obj, _)}}`.
|
||||
|
||||
```erg
|
||||
method_to_classes: {co_consts: [{Code, Array(Obj, _)}], real: [{Int, Int}], times!: [{Nat, (self: Nat, proc!: () => NoneType) => NoneType}], ...}
|
||||
method_to_classes: {co_consts: [{Code, List(Obj, _)}], real: [{Int, Int}], times!: [{Nat, (self: Nat, proc!: () => NoneType) => NoneType}], ...}
|
||||
```
|
||||
|
||||
Note that the value of the key-value pair is an array. Only if this array is of length 1, or has the smallest type element, the key is uniquely determined (otherwise a type error will occur).
|
||||
|
@ -41,11 +41,11 @@ Note that the value of the key-value pair is an array. Only if this array is of
|
|||
Once the key is identified, the definition type is back-propagated to the type of ``?2``.
|
||||
|
||||
```erg
|
||||
?2(<: Code).co_consts: Array(Obj, _)
|
||||
?2(<: Code).co_consts: List(Obj, _)
|
||||
```
|
||||
|
||||
Finally, the type of `consts` is `Code -> Array(Obj, _)`.
|
||||
Finally, the type of `consts` is `Code -> List(Obj, _)`.
|
||||
|
||||
```erg
|
||||
consts(c: Code): Array(Obj, _) = c.co_consts
|
||||
consts(c: Code): List(Obj, _) = c.co_consts
|
||||
```
|
||||
|
|
|
@ -25,7 +25,7 @@ AST(Module[
|
|||
body: Block[
|
||||
Unary Op {
|
||||
op: "!",
|
||||
expr: Array([]),
|
||||
expr: List([]),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -82,7 +82,7 @@ HIR(Module[
|
|||
body: Block[
|
||||
expr: UnaryOp{
|
||||
op: "!",
|
||||
expr: Array([]),
|
||||
expr: List([]),
|
||||
t: [0..10, 0]!,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -50,19 +50,19 @@ The specific operations are as follows.
|
|||
line 1. Def{sig: v, block: ![]}
|
||||
get block type:
|
||||
get UnaryOp type:
|
||||
getArray type: `['T; 0]`
|
||||
getList type: `['T; 0]`
|
||||
instantiate: `[?T; 0]`
|
||||
(substitute, eval are omitted)
|
||||
result: `Γ: {v: [?T; 0]!}`
|
||||
expr returns `NoneType`: OK
|
||||
|
||||
line 2. CallMethod {obj: v, name: push!, args: [1]}
|
||||
get obj type: `Array!(?T, 0)`
|
||||
search: `Γ Array!(?T, 0).push!(Nat)`
|
||||
get: `Array!('T ~> 'T, 'N ~> 'N+1).push!: 'T => NoneType`
|
||||
instantiate: `Array!(?T, ?N).push!(?T) => NoneType`
|
||||
substitute(`S: {?T --> Nat, ?N --> 0}`): `Array!(Nat ~> Nat, 0 ~> 0+1).push!: Nat => NoneType`
|
||||
eval: `Array!(Nat, 0 ~> 1).push!: Nat => NoneType`
|
||||
get obj type: `List!(?T, 0)`
|
||||
search: `Γ List!(?T, 0).push!(Nat)`
|
||||
get: `List!('T ~> 'T, 'N ~> 'N+1).push!: 'T => NoneType`
|
||||
instantiate: `List!(?T, ?N).push!(?T) => NoneType`
|
||||
substitute(`S: {?T --> Nat, ?N --> 0}`): `List!(Nat ~> Nat, 0 ~> 0+1).push!: Nat => NoneType`
|
||||
eval: `List!(Nat, 0 ~> 1).push!: Nat => NoneType`
|
||||
result: `Γ: {v: [Nat; 1]!}`
|
||||
expr returns `NoneType`: OK
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ In fact, there is (very confusingly) a right-sided value on the left side of `=`
|
|||
There can even be a left-side value within a right-side value.
|
||||
|
||||
```python
|
||||
# i is the left-hand side value, Array(Int) and [1, 2, 3] are the right-hand side values
|
||||
i: Array(Int) = [1, 2, 3]
|
||||
# i is the left-hand side value, List(Int) and [1, 2, 3] are the right-hand side values
|
||||
i: List(Int) = [1, 2, 3]
|
||||
# `[1, 2, 3].iter().map i -> i + 1` is the right-hand side value, but i to the left of -> is the left-hand side value
|
||||
a = [1, 2, 3].iter().map i -> i + 1
|
||||
# {x = 1; y = 2} is the right side value, but x, y are the left side values
|
||||
|
|
|
@ -35,10 +35,10 @@ Also, input that is valid according to the specification but deemed undesirable
|
|||
## Why doesn't Tuple have a constructor (`__call__`)?
|
||||
|
||||
Erg tuples must have a compile-time length. Therefore, a tuple is constructed almost only by a tuple literal.
|
||||
If the length is not known until runtime, an immutable array (`Array`) can be used instead.
|
||||
If the length is not known until runtime, an immutable array (`List`) can be used instead.
|
||||
|
||||
```erg
|
||||
arr = Array map(int, input!().split " ")
|
||||
arr = List map(int, input!().split " ")
|
||||
```
|
||||
|
||||
## I got runtime errors in Erg that I did not get in Python. What could be the cause?
|
||||
|
|
|
@ -70,7 +70,7 @@ assert 1e-10 == 0.0000000001
|
|||
|
||||
Each of these literals has its own documentation describing them separately, so please refer to that documentation for details.
|
||||
|
||||
### [Array Literal](./10_array.md)
|
||||
### [List Literal](./10_list.md)
|
||||
|
||||
```python
|
||||
[], [1], [1, 2, 3], ["1", "2",], ...
|
||||
|
@ -100,7 +100,7 @@ Each of these literals has its own documentation describing them separately, so
|
|||
{}, {1}, {1, 2, 3}, {"1", "2", "1"}, ...
|
||||
```
|
||||
|
||||
As a difference from `Array` literals, duplicate elements are removed in `Set`.
|
||||
As a difference from `List` literals, duplicate elements are removed in `Set`.
|
||||
|
||||
```python
|
||||
assert {1, 2, 1} == {1, 2}
|
||||
|
|
|
@ -29,7 +29,7 @@ l1 = l2 = [1, 2, 3] # SyntaxError: multiple assignment not allowed
|
|||
```python
|
||||
# OK
|
||||
l1 = [1, 2, 3]
|
||||
l2 = l1.clone()
|
||||
l2 = l1
|
||||
```
|
||||
|
||||
It is also not possible to reassign to a variable. The syntax that can be used instead, to hold mutable states, are described later.
|
||||
|
|
|
@ -28,7 +28,7 @@ C!.
|
|||
x
|
||||
```
|
||||
|
||||
Procedural methods can also take [ownership](./19_ownership.md) of `self`. Remove `ref` or `ref!` from the method definition.
|
||||
Procedural methods can also take [ownership](./20_ownership.md) of `self`. Remove `ref` or `ref!` from the method definition.
|
||||
|
||||
```python,compile_fail
|
||||
n = 1
|
||||
|
|
|
@ -10,5 +10,5 @@ Although in pure Erg semantics no difference can be found between objects with t
|
|||
```
|
||||
|
||||
<p align='center'>
|
||||
<a href='./08_procedure.md'>Previous</a> | <a href='./10_array.md'>Next</a>
|
||||
<a href='./08_procedure.md'>Previous</a> | <a href='./10_list.md'>Next</a>
|
||||
</p>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Array
|
||||
# List
|
||||
|
||||
Arrays are the most basic __collection (aggregate)__.
|
||||
A list is the most basic __collection (aggregate)__.
|
||||
A collection is an object that can hold multiple objects inside it.
|
||||
|
||||
```python
|
||||
|
@ -14,7 +14,7 @@ mut_a[0].inc!()
|
|||
assert mut_a == [2, 2, 3]
|
||||
```
|
||||
|
||||
As a rule, arrays cannot contain objects of different types.
|
||||
As a rule, lists cannot contain objects of different types.
|
||||
|
||||
```python,compile_fail
|
||||
[1, "a"] # TypeError: 1st element is Int, but 2nd element is Str
|
||||
|
@ -23,12 +23,12 @@ As a rule, arrays cannot contain objects of different types.
|
|||
However, you can bypass the restriction by explicitly specifying the type like this.
|
||||
|
||||
```python
|
||||
[1: Int or Str, "a"]
|
||||
[1, "a"]: [Int or Str; 2]
|
||||
```
|
||||
|
||||
## Slice
|
||||
|
||||
An array can also have multiple values taken out at once. This is called slicing.
|
||||
A list can also have multiple values taken out at once. This is called slicing.
|
||||
|
||||
```python
|
||||
l = [1, 2, 3, 4]
|
||||
|
@ -41,7 +41,7 @@ assert l[1..1] == [2]
|
|||
assert l[..].step(2) == [2, 4]
|
||||
```
|
||||
|
||||
The object obtained by slicing is an (immutable) copy to an array.
|
||||
The object obtained by slicing is an (immutable) copy to a list.
|
||||
|
||||
```python
|
||||
print! Typeof l[1..2] # [Int; 4]
|
|
@ -7,7 +7,7 @@ ids = {"Alice": 145, "Bob": 214, "Charlie": 301}
|
|||
assert ids["Alice"] == 145
|
||||
```
|
||||
|
||||
The key does not have to be a string if it is a `Hashable` object.
|
||||
The key does not have to be a string if it is a `Hash` object.
|
||||
|
||||
```python
|
||||
# deprecated to use a range object as a key (confused with slice)
|
||||
|
@ -73,5 +73,5 @@ x = "a"
|
|||
```
|
||||
|
||||
<p align='center'>
|
||||
<a href='./10_array.md'>Previous</a> | <a href='./12_container_ownership.md'>Next</a>
|
||||
</p>
|
||||
<a href='./10_list.md'>Previous</a> | <a href='./12_container_ownership.md'>Next</a>
|
||||
</p>
|
||||
|
|
|
@ -32,22 +32,22 @@ The type `{Iterator}` of the `.Iterator` attribute is so-called set-kind (kind i
|
|||
```python
|
||||
assert [1, 2, 3] in Iterable(Int)
|
||||
assert 1..3 in Iterable(Int)
|
||||
assert [1, 2, 3].Iterator == ArrayIterator
|
||||
assert [1, 2, 3].Iterator == ListIterator
|
||||
assert (1..3).Iterator == RangeIterator
|
||||
|
||||
log [1, 2, 3].iter() # <ArrayIterator object
|
||||
log [1, 2, 3].iter() # <ListIterator object
|
||||
log (1..3).iter() # <RangeIterator object>
|
||||
```
|
||||
|
||||
Both `ArrayIterator` and `RangeIterator` are classes that implement `Iterator` and exist only to give `Array` and `Range` iteration functions.
|
||||
Both `ListIterator` and `RangeIterator` are classes that implement `Iterator` and exist only to give `List` and `Range` iteration functions.
|
||||
Such a design pattern is called companion class [<sup id="f1">1</sup>](#1).
|
||||
And the `IteratorImpl` patch is the core of the iteration functionality. `Iterator` requires only one `.next` method, `IteratorImpl` provides dozens of methods indeed. `ArrayIterator` and `RangeIterator` can use the implementation method of `IteratorImpl` just by implementing the `.next` method. For this convenience, the standard library implements a number of iterators.
|
||||
And the `IteratorImpl` patch is the core of the iteration functionality. `Iterator` requires only one `.next` method, `IteratorImpl` provides dozens of methods indeed. `ListIterator` and `RangeIterator` can use the implementation method of `IteratorImpl` just by implementing the `.next` method. For this convenience, the standard library implements a number of iterators.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Array~T~ {
|
||||
class List~T~ {
|
||||
...
|
||||
iter() ArrayIterator~T~
|
||||
iter() ListIterator~T~
|
||||
}
|
||||
class Range~T~ {
|
||||
...
|
||||
|
@ -57,10 +57,10 @@ classDiagram
|
|||
<<trait>>
|
||||
iter() Iterator~T~
|
||||
}
|
||||
Iterable~T~ <|.. Array~T~: Impl
|
||||
Iterable~T~ <|.. List~T~: Impl
|
||||
Iterable~T~ <|.. Range~T~: Impl
|
||||
class ArrayIterator~T~ {
|
||||
array: Array~T~
|
||||
class ListIterator~T~ {
|
||||
list: List~T~
|
||||
next() T
|
||||
}
|
||||
class RangeIterator~T~ {
|
||||
|
@ -71,10 +71,10 @@ classDiagram
|
|||
<<trait>>
|
||||
next() T
|
||||
}
|
||||
Iterator~T~ <|.. ArrayIterator~T~: Impl
|
||||
Iterator~T~ <|.. ListIterator~T~: Impl
|
||||
Iterator~T~ <|.. RangeIterator~T~: Impl
|
||||
|
||||
Array <-- ArrayIterator
|
||||
List <-- ListIterator
|
||||
Range <-- RangeIterator
|
||||
```
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ print! id! _a # 0x000002A798DFE980
|
|||
|
||||
The `id!` procedure returns the address in memory where the object resides.
|
||||
|
||||
`b` is a `Nat` "dynamic" array. The content of the object changes, but the variables point to the same thing.
|
||||
`b` is a `Nat` "dynamic" list. The content of the object changes, but the variables point to the same thing.
|
||||
|
||||
```python
|
||||
b = ![1, 2, 3]
|
||||
|
|
|
@ -36,11 +36,11 @@ A subroutine that needs to duplicate an object is said to be an "argument consum
|
|||
|
||||
```python
|
||||
capitalize s: Str!=
|
||||
s. capitalize!()
|
||||
s.capitalize!()
|
||||
s
|
||||
|
||||
s1 = !"hello"
|
||||
s2 = capitalize s1.clone()
|
||||
s2 = capitalize s1.copy()
|
||||
log s2, s1 # !"HELLO hello"
|
||||
```
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ Call `.clone` if you want the contents of the mutable object at the time the fun
|
|||
|
||||
```python
|
||||
i = !0
|
||||
immut_i = i.clone().freeze()
|
||||
immut_i = i.copy().freeze()
|
||||
fx = immut_i + x
|
||||
assert f 1 == 1
|
||||
i.add! 1
|
||||
|
|
|
@ -23,7 +23,7 @@ fn: Int -> Int = x -> x + 1
|
|||
# higher-order type
|
||||
a: [Int; 4] = [0, 1, 2, 3]
|
||||
# or
|
||||
a: Array Int, 4 = [0, 1, 2, 3]
|
||||
a: List Int, 4 = [0, 1, 2, 3]
|
||||
```
|
||||
|
||||
### Literal patterns
|
||||
|
@ -66,8 +66,8 @@ name = match num:
|
|||
|
||||
```python,checker_ignore
|
||||
# these two are the same
|
||||
Array(T, N: {N | N >= 3})
|
||||
Array(T, N | N >= 3)
|
||||
List(T, N: {N | N >= 3})
|
||||
List(T, N | N >= 3)
|
||||
|
||||
f M, N | M >= 0, N >= 1 = ...
|
||||
f(1, 0) # TypeError: N (2nd parameter) must be 1 or more
|
||||
|
@ -106,7 +106,7 @@ m, n = 1, 2
|
|||
f(x, y) = ...
|
||||
```
|
||||
|
||||
### array pattern
|
||||
### list pattern
|
||||
|
||||
```python
|
||||
[i, j] = [1, 2]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Comprehension
|
||||
|
||||
You can create an Array with `[(expr |)? (name <- iterable;)+ (| predicate)?]`,
|
||||
You can create an List with `[(expr |)? (name <- iterable;)+ (| predicate)?]`,
|
||||
a set with `{(expr |)? (name <- iterable;)+ (| predicate)?}`,
|
||||
a Dict with `{(key: value |)? (name <- iterable;)+ (| predicate)?}`.
|
||||
|
||||
|
|
|
@ -17,14 +17,14 @@ log rand # 0.2597...
|
|||
|
||||
1+1*2 |>.times do log("a", end := "") # aaa
|
||||
|
||||
evens = 1..100 |>.iter() |>.filter i -> i % 2 == 0 |>.collect Array
|
||||
evens = 1..100 |>.iter() |>.filter i -> i % 2 == 0 |>.collect List
|
||||
# When implemented without the pipeline operator,
|
||||
_evens = (1..100).iter().filter(i -> i % 2 == 0).collect(Array)
|
||||
_evens = (1..100).iter().filter(i -> i % 2 == 0).collect(List)
|
||||
# or
|
||||
__evens = 1..100 \
|
||||
.iter() \
|
||||
.filter i -> i % 2 == 0 \
|
||||
.collect Array
|
||||
.collect List
|
||||
```
|
||||
|
||||
<p align='center'>
|
||||
|
|
|
@ -15,7 +15,7 @@ This file is for generating The Erg Book. Do not add badges, etc.
|
|||
- [Side effects and procedures](./07_side_effect.md)
|
||||
- [Procedures](./08_procedure.md)
|
||||
- [Built-in procedure](./09_builtin_procs.md)
|
||||
- [Array](./10_array.md)
|
||||
- [List](./10_list.md)
|
||||
- [Dict](./11_dict.md)
|
||||
- [Subscript (index access)](./12_container_ownership.md)
|
||||
- [Tuple](./13_tuple.md)
|
||||
|
|
|
@ -8,17 +8,17 @@ Also, see [here](../terms.md) for terminology.
|
|||
|
||||
* ! → [side effect](./07_side_effect.md)
|
||||
* !-type → [mutable type](./type/18_mut.md)
|
||||
* ? → [error handling](./31_error_handling.md)
|
||||
* # → [Str](./00_basic.md/#comments)
|
||||
* ? → [error handling](./32_error_handling.md)
|
||||
* # → [Str](./00_basic.md#comments)
|
||||
* $ → [shared](./type/advanced/shared.md)
|
||||
* %
|
||||
* &
|
||||
* &&
|
||||
* [′ (single quote)](./21_naming_rule.md#literal-identifiers)
|
||||
* [′ (single quote)](./22_naming_rule.md#literal-identifiers)
|
||||
* [" (double quote)](./01_literal.md#str-literal)
|
||||
* () → [Tuple](./13_tuple.md)
|
||||
* *
|
||||
* * → [*-less multiplication](./01_literal.md/#less-multiplication)
|
||||
* * → [*-less multiplication](./01_literal.md#less-multiplication)
|
||||
* + (prefix) → [operator](./06_operator.md)
|
||||
* +_ → + (prefix)
|
||||
* + (infix) → [operator](./06_operator.md)
|
||||
|
@ -28,42 +28,42 @@ Also, see [here](../terms.md) for terminology.
|
|||
* −_ → − (prefix)
|
||||
* − (infix) → [operator](./06_operator.md)
|
||||
* − (infix) → [Trait](./type/03_trait.md)
|
||||
* −> → [anonymous function](./22_lambda.md)
|
||||
* . → [Visibility](./20_visibility.md)
|
||||
* .. → [closed range operator](./01_literal.md/#range-object)
|
||||
* ..< → [right-open range operator](./01_literal.md/#range-object)
|
||||
* −> → [anonymous function](./23_lambda.md)
|
||||
* . → [Visibility](./21_visibility.md)
|
||||
* .. → [closed range operator](./01_literal.md#range-object)
|
||||
* ..< → [right-open range operator](./01_literal.md#range-object)
|
||||
* ...
|
||||
* ... → [Extract assignment](./29_spread_syntax.md#extract-assignment)
|
||||
* ... → [Extract assignment](./30_spread_syntax.md#extract-assignment)
|
||||
* ... → [Variable-length arguments](./04_function.md#variable-length-arguments)
|
||||
* /
|
||||
* :
|
||||
* : → [Colon application style](./04_function.md)
|
||||
* : → [Type ascription](./03_declaration.md)
|
||||
* : → [Keyword arguments](./04_function.md)
|
||||
* :: → [private variable modifier](./20_visibility.md)
|
||||
* :: → [private variable modifier](./21_visibility.md)
|
||||
* := → [default parameters](./04_function.md)
|
||||
* ;
|
||||
* <
|
||||
* <: → [Subtype specification](./type/02_basic.md)
|
||||
* <<
|
||||
* <=
|
||||
* <.. → [left-open range operator](./01_literal.md/#range-object)
|
||||
* <..< → [open range operator](./01_literal.md/#range-object)
|
||||
* = → [Variable](./20_visibility.md)
|
||||
* <.. → [left-open range operator](./01_literal.md#range-object)
|
||||
* <..< → [open range operator](./01_literal.md#range-object)
|
||||
* = → [Variable](./21_visibility.md)
|
||||
* ==
|
||||
* => → [anonymous procedure operator](./08_procedure.md)
|
||||
* >
|
||||
* >>
|
||||
* >=
|
||||
* @ → [decorator](./30_decorator.md)
|
||||
* [] → [Array](./10_array.md)
|
||||
* @ → [decorator](./31_decorator.md)
|
||||
* [] → [List](./10_list.md)
|
||||
* \ → [Escaping](./00_basic.md)
|
||||
* ^
|
||||
* ^^
|
||||
* _ → [Type erasure](./type/advanced/erasure.md)
|
||||
* _+_ → + (infix)
|
||||
* _-_ → − (infix)
|
||||
* [`` (back quote)](./23_subroutine.md#operator)
|
||||
* [`` (back quote)](./24_subroutine.md#operator)
|
||||
* {}
|
||||
* [{} type](./type/01_type_system.md)
|
||||
* {=} → [Type System](./type/01_type_system.md#classification)
|
||||
|
@ -83,11 +83,11 @@ Also, see [here](../terms.md) for terminology.
|
|||
* [algebraic type](./type/13_algebraic.md)
|
||||
* [And]
|
||||
* [and]
|
||||
* [anonymous function](./22_lambda.md)
|
||||
* [anonymous function](./23_lambda.md)
|
||||
* anonymous type → [Type system](./type/01_type_system.md)
|
||||
* [Array](./10_array.md)
|
||||
* [List](./10_list.md)
|
||||
* assert
|
||||
* [Attach](./30_decorator.md#attach)
|
||||
* [Attach](./31_decorator.md#attach)
|
||||
* [attribute](type/09_attributive.md)
|
||||
* [Attribute definitions](./type/02_basic.md#attribute-definitions)
|
||||
* [Attribute type](./type/09_attributive.md)
|
||||
|
@ -96,7 +96,7 @@ Also, see [here](../terms.md) for terminology.
|
|||
|
||||
* [Bool, Boolean](./01_literal.md#boolean-object)
|
||||
* [Boolean object](./01_literal.md#boolean-object)
|
||||
* [borrowing](./19_ownership.md#borrow)
|
||||
* [borrowing](./20_ownership.md#borrow)
|
||||
|
||||
### C
|
||||
|
||||
|
@ -104,24 +104,24 @@ Also, see [here](../terms.md) for terminology.
|
|||
* [Comments](./00_basic.md#comments)
|
||||
* [Complex object](./01_literal.md#complex-object)
|
||||
* [Compile-time functions](./04_function.md#compile-time-functions)
|
||||
* [circular references](./19_ownership.md#circular-references)
|
||||
* [circular references](./20_ownership.md#circular-references)
|
||||
* [Class](./type/04_class.md)
|
||||
* [Class relationship](./type/04_class.md#class-relationships)
|
||||
* [Class upcasting](./type/16_subtyping.md#class-upcasting)
|
||||
* [Colon application style](./04_function.md#colon-application-style)
|
||||
* [Closure](./24_closure.md)
|
||||
* [Closure](./25_closure.md)
|
||||
* [Compound literals](./01_literal.md#compound-literals)
|
||||
* [Complement](./type/13_algebraic.md#complement)
|
||||
* [Comprehension](./28_comprehension.md)
|
||||
* [constant](./18_mutability.md#constant)
|
||||
* [Comprehension](./29_comprehension.md)
|
||||
* [constant](./19_mutability.md#constant)
|
||||
* [Constants](./02_name.md#constants)
|
||||
* [Context](./31_error_handling.md#context)
|
||||
* [Context](./32_error_handling.md#context)
|
||||
|
||||
### D
|
||||
|
||||
* [Data type](./type/01_type_system.md#data-type)
|
||||
* [Declaration](./03_declaration.md)
|
||||
* [decorator](./30_decorator.md)
|
||||
* [decorator](./31_decorator.md)
|
||||
* [Default parameters](./04_function.md#default-parameters)
|
||||
* [Del](./02_name.md#delete-an-variable)
|
||||
* [Dependent type](./type/14_dependent.md)
|
||||
|
@ -137,10 +137,10 @@ Also, see [here](../terms.md) for terminology.
|
|||
* [Enum class](./type/04_class.md#enum-class)
|
||||
* [Enum type](./type/11_enum.md)
|
||||
* [Enumerated, Interval and Refinement types](./type/12_refinement.md#enumerated-interval-and-refinement-types)
|
||||
* [error handling](./31_error_handling.md)
|
||||
* [error handling](./32_error_handling.md)
|
||||
* [Existential type](./type/advanced/existential.md)
|
||||
* [Exponential literal](./01_literal.md#exponential-literal)
|
||||
* [Extract assignment](./29_spread_syntax.md#extract-assignment)
|
||||
* [Extract assignment](./30_spread_syntax.md#extract-assignment)
|
||||
|
||||
### F
|
||||
|
||||
|
@ -148,14 +148,14 @@ Also, see [here](../terms.md) for terminology.
|
|||
* [Float object](./01_literal.md#float-object)
|
||||
* [for](./05_builtin_funcs.md#for)
|
||||
* [For-All patch](./type/07_patch.md#for-all-patch)
|
||||
* [freeze](./19_ownership.md#freeze)
|
||||
* [freeze](./20_ownership.md#freeze)
|
||||
* [Function](./04_function.md)
|
||||
* [Function definition with multiple patterns](./04_function.md#function-definition-with-multiple-patterns)
|
||||
|
||||
### G
|
||||
|
||||
* [GADTs(Generalized Algebraic Data Types)](./type/advanced/GADTs.md)
|
||||
* [Generator](./35_generator.md)
|
||||
* [Generator](./36_generator.md)
|
||||
* [Glue Patch](./type/07_patch.md#glue-patch)
|
||||
|
||||
### H
|
||||
|
@ -166,19 +166,19 @@ Also, see [here](../terms.md) for terminology.
|
|||
|
||||
* [id](./09_builtin_procs.md#id)
|
||||
* [if](./05_builtin_funcs.md#if)
|
||||
* [import](./34_package_system.md)
|
||||
* [impl](./30_decorator.md#impl)
|
||||
* [import](./35_package_system.md)
|
||||
* [impl](./31_decorator.md#impl)
|
||||
* in
|
||||
* [Indention](./00_basic.md#indentation)
|
||||
* [Instant block](./14_record.md#instant-block)
|
||||
* [Instance/class attributes](./type/04_class.md#instance-and-class-attributes)
|
||||
* [inheritable](./30_decorator.md#inheritable)
|
||||
* [inheritable](./31_decorator.md#inheritable)
|
||||
* [inheritance](./type/05_inheritance.md)
|
||||
* [Int](./01_literal.md)
|
||||
* [Integration with Python](./33_integration_with_Python.md)
|
||||
* [Integration with Python](./34_integration_with_Python.md)
|
||||
* [Interval Type](./type/10_interval.md)
|
||||
* [Intersection](./type/13_algebraic.md#intersection)
|
||||
* [Iterator](./17_iterator.md)
|
||||
* [Iterator](./18_iterator.md)
|
||||
|
||||
### J
|
||||
|
||||
|
@ -189,22 +189,22 @@ Also, see [here](../terms.md) for terminology.
|
|||
|
||||
### L
|
||||
|
||||
* lambda → [anonymous function](./22_lambda.md)
|
||||
* lambda → [anonymous function](./23_lambda.md)
|
||||
* let-polymorphism → [rank 1 polymorphism]
|
||||
* [Literal Identifiers](./21_naming_rule.md#literal-identifiers)
|
||||
* [Literal Identifiers](./22_naming_rule.md#literal-identifiers)
|
||||
|
||||
### M
|
||||
|
||||
* match
|
||||
* [Marker trait](./type/advanced/marker_trait.md)
|
||||
* [Method](./07_side_effect.md#methods)
|
||||
* Modifier → [decorator](./30_decorator.md)
|
||||
* [module](./25_module.md)
|
||||
* Modifier → [decorator](./31_decorator.md)
|
||||
* [module](./26_module.md)
|
||||
* [Multiple inheritance](type/05_inheritance.md#multiple-inheritance)
|
||||
* [Multi-layer (multi-level) Inheritance](type/05_inheritance.md#multi-layer-multi-level-inheritance)
|
||||
* [Mutable type](./type/18_mut.md)
|
||||
* [Mutable structure type](./type/advanced/mut_struct.md)
|
||||
* [Mutability](./18_mutability.md)
|
||||
* [Mutability](./19_mutability.md)
|
||||
|
||||
### N
|
||||
|
||||
|
@ -220,28 +220,28 @@ Also, see [here](../terms.md) for terminology.
|
|||
|
||||
### O
|
||||
|
||||
* [Object](./26_object_system.md)
|
||||
* [Object](./27_object_system.md)
|
||||
* [Option]
|
||||
* [Or]
|
||||
* [or]
|
||||
* [Ord]
|
||||
* [ownership system](./19_ownership.md)
|
||||
* [ownership system](./20_ownership.md)
|
||||
* [Overloading](./type/advanced/overloading.md)
|
||||
* [Overriding](./type/05_inheritance.md#overriding)
|
||||
* [Override in trait](./type/03_trait.md#override-in-trait)
|
||||
|
||||
### P
|
||||
|
||||
* [Panic](./31_error_handling.md#panic)
|
||||
* [Panic](./32_error_handling.md#panic)
|
||||
* [Patch](./type/07_patch.md)
|
||||
* [Pattern match](./27_pattern_matching.md)
|
||||
* [Pattern match](./28_pattern_matching.md)
|
||||
* [Phantom class](./type/advanced/phantom.md)
|
||||
* [pipeline operator](./32_pipeline.md)
|
||||
* [pipeline operator](./33_pipeline.md)
|
||||
* [Predicate](./type/19_bound.md#predicate)
|
||||
* print!
|
||||
* [Procedures](./08_procedure.md)
|
||||
* [Projection type](./type/advanced/projection.md)
|
||||
* Python → [Integration with Python](./33_integration_with_Python.md)
|
||||
* Python → [Integration with Python](./34_integration_with_Python.md)
|
||||
|
||||
### Q
|
||||
|
||||
|
@ -257,9 +257,9 @@ Also, see [here](../terms.md) for terminology.
|
|||
* [Recursive functions](./04_function.md#recursive-functions)
|
||||
* [Refinement pattern](./type/12_refinement.md#refinement-pattern)
|
||||
* [Refinement type](./type/12_refinement.md)
|
||||
* [replication](./19_ownership.md#replication)
|
||||
* [replication](./20_ownership.md#replication)
|
||||
* [Replacing traits](./type/05_inheritance.md#replacing-traits-or-what-looks-like-it)
|
||||
* Result → [error handling](./31_error_handling.md)
|
||||
* Result → [error handling](./32_error_handling.md)
|
||||
|
||||
### S
|
||||
|
||||
|
@ -269,9 +269,9 @@ Also, see [here](../terms.md) for terminology.
|
|||
* [Shared reference](./type/advanced/shared.md)
|
||||
* [side-effect](./07_side_effect.md)
|
||||
* [Smart cast](./type/12_refinement.md#smart-cast)
|
||||
* [Spread assignment](./29_spread_syntax.md)
|
||||
* [Spread assignment](./30_spread_syntax.md)
|
||||
* [special type variables](./type/advanced/special.md#special-type-variables)
|
||||
* [Stack trace](./31_error_handling.md#stack-trace)
|
||||
* [Stack trace](./32_error_handling.md#stack-trace)
|
||||
* [Structure type](./type/01_type_system.md#structure-type-anonymous-type)
|
||||
* [Structural patch](./type/07_patch.md#structural-patch)
|
||||
* [Structural trait](./type/03_trait.md#structural-traits)
|
||||
|
@ -282,11 +282,11 @@ Also, see [here](../terms.md) for terminology.
|
|||
* [Subtyping of subroutines](./type/16_subtyping.md#subtyping-of-subroutines)
|
||||
* [Subtype specification](./type/02_basic.md#subtype-specification)
|
||||
* [Subtyping of polymorphic function types](./type/15_quantified.md#subtyping-of-polymorphic-function-types)
|
||||
* [Subroutine signatures](./23_subroutine.md)
|
||||
* [Subroutine signatures](./24_subroutine.md)
|
||||
|
||||
### T
|
||||
|
||||
* [Test](./30_decorator.md#test)
|
||||
* [Test](./31_decorator.md#test)
|
||||
* [Traits](./type/03_trait.md)
|
||||
* [Trait inclusion](./type/03_trait.md#trait-inclusion)
|
||||
* True → [Boolean object](./01_literal.md#boolean-object)
|
||||
|
|
|
@ -222,7 +222,7 @@ right(_, r) = r
|
|||
|
||||
### Variable length patterns
|
||||
|
||||
Used in combination with the tuple/array/record pattern described later.
|
||||
Used in combination with the tuple/list/record pattern described later.
|
||||
|
||||
```python
|
||||
[i, *j] = [1, 2, 3, 4]
|
||||
|
@ -240,7 +240,7 @@ assert first(1, 2, 3) == 1
|
|||
m, n = 1, 2
|
||||
```
|
||||
|
||||
### Array pattern
|
||||
### List pattern
|
||||
|
||||
```python
|
||||
length [] = 0
|
||||
|
|
|
@ -45,14 +45,14 @@ In Erg, the nominal types are classes and traits. When we simply say class/trait
|
|||
|
||||
The type for the entire nominal type (`NominalType`) and the type for the entire structural type (`StructuralType`) are subtypes of the type for the entire type (`Type`).
|
||||
|
||||
Erg can pass arguments (type arguments) to the type definition. An `Option`, `Array`, etc. with type arguments are called a polynomial kind. These are not themselves types, but they become types by applying arguments. Types such as `Int`, `Str`, etc., which have no arguments, are called simple types (scalar types).
|
||||
Erg can pass arguments (type arguments) to the type definition. An `Option`, `List`, etc. with type arguments are called a polynomial kind. These are not themselves types, but they become types by applying arguments. Types such as `Int`, `Str`, etc., which have no arguments, are called simple types (scalar types).
|
||||
|
||||
A type can be regarded as a set, and there is an inclusion relation. For example, `Num` contains `Add`, `Sub`, etc., and `Int` contains `Nat`.
|
||||
The upper class of all classes is `Object == Class {:}` and the lower class of all types is `Never == Class {}`. This is described below.
|
||||
|
||||
## Types
|
||||
|
||||
A type like `Array T` can be regarded as a function of type `Type -> Type` that takes type `T` as an argument and returns type `Array T` (also called Kind in type theory). Types like `Array T` are specifically called polymorphic types, and `Array` itself is called unary Kind.
|
||||
A type like `List T` can be regarded as a function of type `Type -> Type` that takes type `T` as an argument and returns type `List T` (also called Kind in type theory). Types like `List T` are specifically called polymorphic types, and `List` itself is called unary Kind.
|
||||
|
||||
The type of a function whose argument and return types are known is denoted as `(T, U) -> V`. If you want to specify an entire two-argument function of the same type, you can use `|T| (T, T) -> T`, and if you want to specify an entire N-argument function, you can use `Func N`. However, the `Func N` type has no information about the number of arguments or their types, so all return values are of type `Obj` when called.
|
||||
|
||||
|
@ -60,7 +60,7 @@ The `Proc` type is denoted as `() => Int` and so on. Also, the name of the `Proc
|
|||
|
||||
A `Method` type is a function/procedure whose first argument is the object `self` to which it belongs (by reference). For dependent types, you can also specify the type of yourself after the method is applied. This is `T!(!N)` type and `T!(N ~> N-1). () => Int` and so on.
|
||||
|
||||
Erg's array (Array) is what Python calls a list. `[Int; 3]` is an array class that contains three objects of type `Int`.
|
||||
Erg's array (List) is what Python calls a list. `[Int; 3]` is an array class that contains three objects of type `Int`.
|
||||
|
||||
> __Note__: `(Type; N)` is both a type and a value, so it can be used like this.
|
||||
>
|
||||
|
@ -113,7 +113,7 @@ Since types are also objects, there are attributes on the types themselves. Such
|
|||
As mentioned earlier, a "type" in Erg roughly means a set of objects.
|
||||
|
||||
The following is a definition of the `Add` type, which requires `+` (the middle operator). `R, O` are the so-called type parameters, which can be a true type (class) such as `Int` or `Str`. In other languages, type parameters are given a special notation (generics, templates, etc.), but in Erg they can be defined just like normal parameters.
|
||||
Type parameters can also be used for types other than type objects. For example, the array type `[Int; 3]` is a syntax sugar for `Array Int, 3`. If the type implementations overlap, the user must explicitly choose one.
|
||||
Type parameters can also be used for types other than type objects. For example, the array type `[Int; 3]` is a syntax sugar for `List Int, 3`. If the type implementations overlap, the user must explicitly choose one.
|
||||
|
||||
```python
|
||||
Add R = Trait {
|
||||
|
|
|
@ -15,11 +15,11 @@ Type specifications are more useful when defining subroutines and types.
|
|||
|
||||
```python
|
||||
# Type specification for parameters
|
||||
f x, y: Array Int = ...
|
||||
T X, Y: Array Int = ...
|
||||
f x, y: List Int = ...
|
||||
T X, Y: List Int = ...
|
||||
```
|
||||
|
||||
Note that in the above case, `x, y` are both `Array Int`.
|
||||
Note that in the above case, `x, y` are both `List Int`.
|
||||
|
||||
```python
|
||||
# The value of a capital variable must be a constant expression
|
||||
|
@ -137,7 +137,7 @@ Types can be aliased. This allows long types, such as record types, to be shorte
|
|||
Id = Int
|
||||
Point3D = {x = Int; y = Int; z = Int}
|
||||
IorS = Int or Str
|
||||
Vector = Array Int
|
||||
Vector = List Int
|
||||
```
|
||||
|
||||
Also, when displaying errors, the compiler will use aliases for composite types (in the above example, right-hand-side types other than the first) if they are defined.
|
||||
|
@ -150,8 +150,8 @@ The purpose is also to prevent adding aliases on top of types that already have
|
|||
Id = Int
|
||||
UserId = Int # TypeWarning: duplicate aliases: Id and UserId
|
||||
|
||||
Ids = Array Id
|
||||
Ints = Array Int # TypeWarning: duplicate aliases: Isd and Ints
|
||||
Ids = List Id
|
||||
Ints = List Int # TypeWarning: duplicate aliases: Isd and Ints
|
||||
|
||||
IorS = Int or Str
|
||||
IorSorB = IorS or Bool
|
||||
|
|
|
@ -77,7 +77,7 @@ Trait is also a type, so it can be used for normal type specification.
|
|||
|
||||
```python
|
||||
points: [Norm; 2] = [Point2D::new(1, 2), Point2D::new(3, 4)]
|
||||
assert points.iter().map(x -> x.norm()).collect(Array) == [5, 25].
|
||||
assert points.iter().map(x -> x.norm()).collect(List) == [5, 25].
|
||||
```
|
||||
|
||||
## Trait inclusion
|
||||
|
@ -151,11 +151,11 @@ Mapper T: Type = Trait {
|
|||
.map = (self: Self, T -> U) -> Self.MapIter U
|
||||
}
|
||||
|
||||
# ArrayIterator <: Mapper
|
||||
# ArrayIterator.MapIter == ArrayMapper
|
||||
# [1, 2, 3].iter(): ArrayIterator Int
|
||||
# [1, 2, 3].iter().map(x -> "\{x}"): ArrayMapper Str
|
||||
assert [1, 2, 3].iter().map(x -> "\{x}").collect(Array) == ["1", "2", "3"].
|
||||
# ListIterator <: Mapper
|
||||
# ListIterator.MapIter == ListMapper
|
||||
# [1, 2, 3].iter(): ListIterator Int
|
||||
# [1, 2, 3].iter().map(x -> "\{x}"): ListMapper Str
|
||||
assert [1, 2, 3].iter().map(x -> "\{x}").collect(List) == ["1", "2", "3"].
|
||||
```
|
||||
|
||||
## Override in Trait
|
||||
|
|
|
@ -12,7 +12,7 @@ Value = (
|
|||
or Bool
|
||||
or Str
|
||||
or NoneType
|
||||
or Array Const
|
||||
or List Const
|
||||
or Tuple Const
|
||||
or Set Const
|
||||
or ConstFunc(Const, _)
|
||||
|
|
|
@ -10,8 +10,8 @@ Nat = 0.. _
|
|||
Odd = {N: Int | N % 2 == 1}
|
||||
Char = StrWithLen 1
|
||||
# StrWithLen 1 == {_: StrWithLen N | N == 1}
|
||||
[Int; 3] == {_: Array Int, N | N == 3}
|
||||
Array3OrMore == {A: Array _, N | N >= 3}
|
||||
[Int; 3] == {_: List Int, N | N == 3}
|
||||
List3OrMore == {A: List _, N | N >= 3}
|
||||
```
|
||||
|
||||
When there are multiple preds, they can be separated by `;` or `and` or `or`. `;` and `and` mean the same thing.
|
||||
|
@ -83,7 +83,7 @@ Just as `_: {X}` can be rewritten as `X` (constant pattern), `_: {X: T | Pred}`
|
|||
|
||||
```python
|
||||
# method `.m` is defined for arrays of length 3 or greater
|
||||
Array(T, N | N >= 3)
|
||||
List(T, N | N >= 3)
|
||||
.m(&self) = ...
|
||||
```
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
Dependent types are a feature that can be said to be the biggest feature of Erg.
|
||||
A dependent type is a type that takes a value as an argument. Ordinary polymorphic types can take only types as arguments, but dependent types relax that restriction.
|
||||
|
||||
Dependent types are equivalent to `[T; N]` (`Array(T, N)`).
|
||||
Dependent types are equivalent to `[T; N]` (`List(T, N)`).
|
||||
This type is determined not only by the content type `T` but also by the number of contents `N`. `N` contains an object of type `Nat`.
|
||||
|
||||
```python
|
||||
|
@ -67,7 +67,7 @@ vm.stop!() # TypeError: VM!(!"stopped", 1) doesn't have .stop!()
|
|||
You can also embed or inherit existing types to create dependent types.
|
||||
|
||||
```python
|
||||
MyArray(T, N) = Inherit[T; N]
|
||||
MyList(T, N) = Inherit[T; N]
|
||||
|
||||
# The type of self: Self(T, N) changes in conjunction with .array
|
||||
MyStruct!(T, N: Nat!) = Class {.array: [T; !N]}
|
||||
|
@ -75,4 +75,4 @@ MyStruct!(T, N: Nat!) = Class {.array: [T; !N]}
|
|||
|
||||
<p align='center'>
|
||||
<a href='./13_algebraic.md'>Previous</a> | <a href='./15_quantified.md'>Next</a>
|
||||
</p>
|
||||
</p>
|
||||
|
|
|
@ -99,7 +99,7 @@ Iterator T = Trait {
|
|||
}
|
||||
|
||||
it = [1, 2, 3].iter().map i -> i + 1
|
||||
it.collect(Array) # [2, 3, 4].
|
||||
it.collect(List) # [2, 3, 4].
|
||||
```
|
||||
|
||||
Type variables can only be declared during `||`. However, once declared, they can be used anywhere until they exit scope.
|
||||
|
|
|
@ -37,7 +37,7 @@ The `.freeze_map` method operates on values unchanged.
|
|||
|
||||
```python
|
||||
a = [1, 2, 3].into [Nat; !3]
|
||||
x = a.freeze_map a: [Nat; 3] -> a.iter().map(i -> i + 1).filter(i -> i % 2 == 0).collect(Array)
|
||||
x = a.freeze_map a: [Nat; 3] -> a.iter().map(i -> i + 1).filter(i -> i % 2 == 0).collect(List)
|
||||
```
|
||||
|
||||
In a polymorphic immutable type the type argument `T` of the type is implicitly assumed to be immutable.
|
||||
|
|
|
@ -24,7 +24,7 @@ However, these rules do not apply to the tuple-like part of a Function type, bec
|
|||
|
||||
In addition, return values of Unit types can be ignored, but return values of other tuple types cannot be ignored.
|
||||
|
||||
## Array Type
|
||||
## List Type
|
||||
|
||||
```erg
|
||||
[], [X; 0], [X; 1], [X; 2], ..., [X; _] == [X]
|
||||
|
@ -37,7 +37,7 @@ The same subtype rules exist for arrays as for tuples.
|
|||
* forall N in 0..<Len(T) (Len(T) <= Len(U)), U[N] == T[N] => U <: T (oblivion rule)
|
||||
```
|
||||
|
||||
Arrays like the one below are not valid types. It is an intentional design to emphasize that the elements of the array are homogenized.
|
||||
Lists like the one below are not valid types. It is an intentional design to emphasize that the elements of the array are homogenized.
|
||||
|
||||
```erg
|
||||
[Int, Str]
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Type erasure is the process of setting a type argument to `_` and deliberately discarding its information. Type erasure is a feature of many polymorphic languages, but in the context of Erg's syntax, it is more accurate to call it type argument erasure.
|
||||
|
||||
The most common example of a type that has been type-erased is `[T, _]`. Arrays are not always known their length at compile-time. For example, `sys.argv`, which refers to command line arguments, is of type `[Str, _]`. Since Erg's compiler has no way of knowing the length of command line arguments, information about their length must be given up.
|
||||
The most common example of a type that has been type-erased is `[T, _]`. Lists are not always known their length at compile-time. For example, `sys.argv`, which refers to command line arguments, is of type `[Str, _]`. Since Erg's compiler has no way of knowing the length of command line arguments, information about their length must be given up.
|
||||
However, a type that has been type-erased becomes a supertype of a type that has not been (e.g. `[T; N] <: [T; _]`), so it can accept more objects.
|
||||
Objects of type `[T; N]` can of course use methods of type `[T; _]`, but the `N` information is erased after use. If the length does not change, then it is possible to use `[T; N]` in the signature. If the length remains the same, it must be indicated by a signature.
|
||||
|
||||
|
@ -18,14 +18,14 @@ For non-type type arguments (Int, Bool, etc.), the parameter with `_` will be un
|
|||
|
||||
```python
|
||||
i: _ # i: Object
|
||||
[_; _] == [Object; _] == Array
|
||||
[_; _] == [Object; _] == List
|
||||
```
|
||||
|
||||
Type erasure is not the same as omitting a type specification. Once the type argument information has been erased, it will not be returned unless you assert it again.
|
||||
|
||||
```python
|
||||
implicit = (1..5).iter().map(i -> i * 2).to_arr()
|
||||
explicit = (1..5).iter().map(i -> i * 2).into(Array(Nat))
|
||||
explicit = (1..5).iter().map(i -> i * 2).into(List(Nat))
|
||||
```
|
||||
|
||||
In Rust, this corresponds to the following code.
|
||||
|
@ -38,6 +38,6 @@ Erg does not allow partial omission of types, but uses higher-order kind polymor
|
|||
|
||||
```python
|
||||
# collect is a higher-order Kind method that takes Kind
|
||||
hk = (1..5).iter().map(i -> i * 2).collect(Array)
|
||||
hk: Array(Int)
|
||||
hk = (1..5).iter().map(i -> i * 2).collect(List)
|
||||
hk: List(Int)
|
||||
```
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Everything is typed in Erg. Types themselves are no exception. __kind__ represents the "type of type". For example, `Int` belongs to `Type`, just as `1` belongs to `Int`. `Type` is the simplest kind, the __atomic kind__. In type-theoretic notation, `Type` corresponds to `*`.
|
||||
|
||||
In the concept of kind, what is practically important is one or more kinds (multinomial kind). One-term kind, for example `Option`, belongs to it. A unary kind is represented as `Type -> Type` [<sup id="f1">1</sup>](#1). A __container__ such as `Array` or `Option` is specifically a polynomial kind that takes a type as an argument.
|
||||
In the concept of kind, what is practically important is one or more kinds (multinomial kind). One-term kind, for example `Option`, belongs to it. A unary kind is represented as `Type -> Type` [<sup id="f1">1</sup>](#1). A __container__ such as `List` or `Option` is specifically a polynomial kind that takes a type as an argument.
|
||||
As the notation `Type -> Type` indicates, `Option` is actually a function that receives a type `T` and returns a type `Option T`. However, since this function is not a function in the usual sense, it is usually called the unary kind.
|
||||
|
||||
Note that `->` itself, which is an anonymous function operator, can also be seen as a kind when it receives a type and returns a type.
|
||||
|
|
|
@ -26,7 +26,7 @@ v: [Str; !1].
|
|||
```
|
||||
|
||||
For mutable structure types, Mutable type arguments are marked with `!`. In the above case, the type `[Str; !0]` can be changed to `[Str; !1]` and so on. That is, the length can be changed.
|
||||
Incidentally, the `[T; !N]` type is the sugar-coated syntax of the `ArrayWithLength!(T, !N)` type.
|
||||
Incidentally, the `[T; !N]` type is the sugar-coated syntax of the `ListWithLength!(T, !N)` type.
|
||||
|
||||
Mutable structure types can of course be user-defined. Note, however, that there are some differences from invariant structure types in terms of the construction method.
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ Erg has quantified and dependent types. Then naturally, it is possible to create
|
|||
|
||||
```python
|
||||
NonNullStr = |N: Nat| StrWithLen N | N ! = 0 # same as {S | N: Nat; S: StrWithLen N; N ! = 0}
|
||||
NonEmptyArray = |N: Nat| [_; N | N > 0] # same as {A | N: Nat; A: Array(_, N); N > 0}
|
||||
NonEmptyList = |N: Nat| [_; N | N > 0] # same as {A | N: Nat; A: List(_, N); N > 0}
|
||||
```
|
||||
|
||||
The standard form of quantified dependent types are `K(A, ... | Pred)`. ``K`` is a type constructor, `A, B` are type arguments, and `Pred` is a conditional expression.
|
||||
|
|
|
@ -5,19 +5,19 @@ Erg can subtype polymorphic types, but there are some caveats.
|
|||
First, consider the inclusion relation of ordinary polymorphic types. In general, there is a container `K` and a type `A, B` to which it assigns, and when `A < B`, `K A < K B`.
|
||||
For example, `Option Int < Option Object`. Therefore, methods defined in `Option Object` can also be used in `Option Int`.
|
||||
|
||||
Consider the typical polymorphic type `Array!(T)`.
|
||||
Note that this time it's not `Array!(T, N)` because we don't care about the number of elements.
|
||||
Now, the `Array!(T)` type has methods called `.push!` and `.pop!`, which mean adding and removing elements, respectively. Here is the type:
|
||||
Consider the typical polymorphic type `List!(T)`.
|
||||
Note that this time it's not `List!(T, N)` because we don't care about the number of elements.
|
||||
Now, the `List!(T)` type has methods called `.push!` and `.pop!`, which mean adding and removing elements, respectively. Here is the type:
|
||||
|
||||
Array.push!: Self(T).(T) => NoneType
|
||||
Array.pop!: Self(T).() => T
|
||||
List.push!: Self(T).(T) => NoneType
|
||||
List.pop!: Self(T).() => T
|
||||
|
||||
As can be intuitively understood,
|
||||
|
||||
* `Array!(Object).push!(s)` is OK when `s: Str` (just upcast `Str` to `Object`)
|
||||
* When `o: Object`, `Array!(Str).push!(o)` is NG
|
||||
* `Array!(Object).pop!().into(Str)` is NG
|
||||
* `Array!(Str).pop!().into(Object)` is OK
|
||||
* `List!(Object).push!(s)` is OK when `s: Str` (just upcast `Str` to `Object`)
|
||||
* When `o: Object`, `List!(Str).push!(o)` is NG
|
||||
* `List!(Object).pop!().into(Str)` is NG
|
||||
* `List!(Str).pop!().into(Object)` is OK
|
||||
|
||||
is. In terms of the type system, this is
|
||||
|
||||
|
|
|
@ -46,11 +46,6 @@ Use attributes. By the way, a record is a function that can define an object wit
|
|||
Giving arguments to a subroutine object and getting a result.
|
||||
Use Call. This is because Application has a usage of "application software".
|
||||
|
||||
## Array, List
|
||||
|
||||
Use Arrays. Erg arrays are (generally) contiguous in memory.
|
||||
List refers to a so-called linked list, or a list as a Python data type.
|
||||
|
||||
## lambda functions, lambda expressions, anonymous functions
|
||||
|
||||
Unify with anonymous functions. In English, Lambda can be used to shorten the number of characters, but the official name is Anonymous function.
|
||||
|
|
|
@ -56,7 +56,7 @@ codeをコードとして評価し返す。
|
|||
ただしクラスは比較できないため、インスタンス判定がしたい場合は`classof(object) == Class`ではなく`object in Class`を使う。
|
||||
コンパイル時に決定される構造型は`Typeof`で得られる。
|
||||
|
||||
## Iterator, Array生成系
|
||||
## Iterator, List生成系
|
||||
|
||||
### repeat|T|(x: T) -> RepeatIterator T
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue