mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
Fix: doc comments cannot be used in method defs
This commit is contained in:
parent
d6bbb91015
commit
0019147007
7 changed files with 108 additions and 43 deletions
|
@ -1478,7 +1478,7 @@ impl ASTLowerer {
|
|||
errs
|
||||
})?;
|
||||
}
|
||||
ast::ClassAttr::Decl(_decl) => {}
|
||||
ast::ClassAttr::Decl(_) | ast::ClassAttr::Doc(_) => {}
|
||||
}
|
||||
}
|
||||
for attr in methods.attrs.into_iter() {
|
||||
|
@ -1499,6 +1499,14 @@ impl ASTLowerer {
|
|||
self.errs.extend(errs);
|
||||
}
|
||||
},
|
||||
ast::ClassAttr::Doc(doc) => match self.lower_literal(doc) {
|
||||
Ok(doc) => {
|
||||
hir_methods.push(hir::Expr::Lit(doc));
|
||||
}
|
||||
Err(errs) => {
|
||||
self.errs.extend(errs);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Err(errs) = self.module.context.check_decls() {
|
||||
|
@ -1597,7 +1605,7 @@ impl ASTLowerer {
|
|||
errs
|
||||
})?;
|
||||
}
|
||||
ast::ClassAttr::Decl(_decl) => {}
|
||||
ast::ClassAttr::Decl(_) | ast::ClassAttr::Doc(_) => {}
|
||||
}
|
||||
}
|
||||
for attr in methods.attrs.into_iter() {
|
||||
|
@ -1618,6 +1626,14 @@ impl ASTLowerer {
|
|||
self.errs.extend(errs);
|
||||
}
|
||||
},
|
||||
ast::ClassAttr::Doc(doc) => match self.lower_literal(doc) {
|
||||
Ok(doc) => {
|
||||
hir_methods.push(hir::Expr::Lit(doc));
|
||||
}
|
||||
Err(errs) => {
|
||||
self.errs.extend(errs);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Err(errs) = self.module.context.check_decls() {
|
||||
|
|
|
@ -748,7 +748,12 @@ impl ValueObj {
|
|||
pub fn from_str(t: Type, content: Str) -> Option<Self> {
|
||||
match t {
|
||||
Type::Int => content.replace('_', "").parse::<i32>().ok().map(Self::Int),
|
||||
Type::Nat => content.replace('_', "").parse::<u64>().ok().map(Self::Nat),
|
||||
Type::Nat => content
|
||||
.trim_start_matches('-') // -0 -> 0
|
||||
.replace('_', "")
|
||||
.parse::<u64>()
|
||||
.ok()
|
||||
.map(Self::Nat),
|
||||
Type::Float => content
|
||||
.replace('_', "")
|
||||
.parse::<f64>()
|
||||
|
|
|
@ -727,11 +727,12 @@ impl_locational_for_enum!(Dict; Normal, Comprehension);
|
|||
pub enum ClassAttr {
|
||||
Def(Def),
|
||||
Decl(TypeAscription),
|
||||
Doc(Literal),
|
||||
}
|
||||
|
||||
impl_nested_display_for_enum!(ClassAttr; Def, Decl);
|
||||
impl_display_for_enum!(ClassAttr; Def, Decl);
|
||||
impl_locational_for_enum!(ClassAttr; Def, Decl);
|
||||
impl_nested_display_for_enum!(ClassAttr; Def, Decl, Doc);
|
||||
impl_display_for_enum!(ClassAttr; Def, Decl, Doc);
|
||||
impl_locational_for_enum!(ClassAttr; Def, Decl, Doc);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ClassAttrs(Vec<ClassAttr>);
|
||||
|
|
|
@ -287,6 +287,9 @@ impl Desugarer {
|
|||
let expr = desugar(*decl.expr);
|
||||
new_attrs.push(ClassAttr::Decl(expr.type_asc(decl.op, decl.t_spec)));
|
||||
}
|
||||
ClassAttr::Doc(doc) => {
|
||||
new_attrs.push(ClassAttr::Doc(doc));
|
||||
}
|
||||
}
|
||||
}
|
||||
let new_attrs = ClassAttrs::from(new_attrs);
|
||||
|
|
|
@ -984,6 +984,7 @@ impl Parser {
|
|||
let first = match first {
|
||||
Expr::Def(def) => ClassAttr::Def(def),
|
||||
Expr::TypeAsc(tasc) => ClassAttr::Decl(tasc),
|
||||
Expr::Lit(lit) if lit.is_doc_comment() => ClassAttr::Doc(lit),
|
||||
_ => {
|
||||
// self.restore();
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
|
|
|
@ -8,7 +8,7 @@ Please think that the parts not mentioned are the same as Python.
|
|||
|
||||
## Basic calculation
|
||||
|
||||
Erg has a strict type. However, types are automatically casting if subtypes due to the flexibility provided by classes and traits (see [API] for details).
|
||||
Erg has a strict type. However, types are automatically casting if subtypes due to the flexibility provided by classes and traits (see [API](../API) for details).
|
||||
|
||||
In addition, different types can be calculated for each other as long as the type is a numeric type.
|
||||
|
||||
|
@ -20,16 +20,16 @@ d = c * 0 # -0.0: Float
|
|||
e = f // 2 # 0: Nat
|
||||
```
|
||||
|
||||
If you do not want to allow these implicit type conversions, you can specify the type at declaration time to detect them as errors at compile time.
|
||||
If you do not want to allow unexpected type widening, you can specify the type at declaration time to detect them as errors at compile time.
|
||||
|
||||
```python
|
||||
a = 1
|
||||
b: Int = a / 2
|
||||
# error message
|
||||
Error[#0047]: File <stdin>, line 1, in <module>
|
||||
2│ b: Int = int / 2
|
||||
2│ b: Int = a / 2
|
||||
^
|
||||
TypeError: the type of ratio is mismatched:
|
||||
TypeError: the type of b is mismatched:
|
||||
expected: Int
|
||||
but found: Float
|
||||
```
|
||||
|
@ -48,7 +48,7 @@ False == 0.0 # NG
|
|||
True == "a" # NG
|
||||
```
|
||||
|
||||
## variables, constants
|
||||
## Variables, constants
|
||||
|
||||
Variables are defined with `=`. As with Haskell, variables once defined cannot be changed. However, it can be shadowed in another scope.
|
||||
|
||||
|
@ -61,6 +61,7 @@ assert i == 0
|
|||
|
||||
Anything starting with an uppercase letter is a constant. Only things that can be computed at compile time can be constants.
|
||||
Also, a constant is identical in all scopes since its definition.
|
||||
This property allows constants to be used in pattern matching.
|
||||
|
||||
```python
|
||||
PI = 3.141592653589793
|
||||
|
@ -110,11 +111,13 @@ i.update! x -> x + 1
|
|||
assert i == 1
|
||||
```
|
||||
|
||||
## procedures
|
||||
## Procedures
|
||||
|
||||
Subroutines with side effects are called procedures and are marked with `!`.
|
||||
Functions are subroutines that do not have side effects (pure).
|
||||
|
||||
You cannot call procedures in functions.
|
||||
This explicitly isolates side effects.
|
||||
|
||||
```python
|
||||
print! 1 # 1
|
||||
|
@ -166,9 +169,9 @@ assert foo.x == 1
|
|||
foo.y # VisibilityError
|
||||
```
|
||||
|
||||
## pattern matching
|
||||
## Pattern matching
|
||||
|
||||
### variable pattern
|
||||
### Variable pattern
|
||||
|
||||
```python
|
||||
# basic assignments
|
||||
|
@ -197,7 +200,7 @@ fib1 = 1
|
|||
fibn: Nat = fibn-1 + fibn-2
|
||||
```
|
||||
|
||||
### constant pattern
|
||||
### Constant pattern
|
||||
|
||||
```python
|
||||
PI = 3.141592653589793
|
||||
|
@ -209,7 +212,7 @@ name = match num:
|
|||
_ -> "unnamed"
|
||||
```
|
||||
|
||||
### discard (wildcard) pattern
|
||||
### Discard (wildcard) pattern
|
||||
|
||||
```python
|
||||
_ = 1
|
||||
|
@ -222,9 +225,9 @@ right(_, r) = r
|
|||
Used in combination with the tuple/array/record pattern described later.
|
||||
|
||||
```python
|
||||
[i,...j] = [1, 2, 3, 4]
|
||||
[i, *j] = [1, 2, 3, 4]
|
||||
assert j == [2, 3, 4]
|
||||
first|T|(fst: T, ...rest: T) = fst
|
||||
first|T|(fst: T, *rest: T) = fst
|
||||
assert first(1, 2, 3) == 1
|
||||
```
|
||||
|
||||
|
@ -237,17 +240,17 @@ assert first(1, 2, 3) == 1
|
|||
m, n = 1, 2
|
||||
```
|
||||
|
||||
### array pattern
|
||||
### Array pattern
|
||||
|
||||
```python
|
||||
length[] = 0
|
||||
length[_, ...rest] = 1 + lengthrest
|
||||
length [] = 0
|
||||
length [_, *rest] = 1 + lengthrest
|
||||
```
|
||||
|
||||
#### record pattern
|
||||
#### Record pattern
|
||||
|
||||
```python
|
||||
{sin; cos; tan; ...} = import "math"
|
||||
{sin; cos; tan} = import "math"
|
||||
{*} = import "math" # import all
|
||||
|
||||
person = {name = "John Smith"; age = 20}
|
||||
|
@ -270,11 +273,20 @@ Point::{x; y} = p
|
|||
odds = [i | i <- 1..100; i % 2 == 0]
|
||||
```
|
||||
|
||||
## class
|
||||
## Class
|
||||
|
||||
Erg does not support multiple/multilevel inheritance.
|
||||
Erg does not support multiple inheritance.
|
||||
|
||||
## Traits
|
||||
Classes are non-inheritable by default, and you must define inheritable classes with the `Inheritable` decorator.
|
||||
|
||||
```python
|
||||
@Inheritable
|
||||
Point2D = Class {x = Int; y = Int}
|
||||
|
||||
Point3D = Inherit Point2D, Base := {x = Int; y = Int; z = Int}
|
||||
```
|
||||
|
||||
## Trait
|
||||
|
||||
They are similar to Rust traits, but in a more literal sense, allowing composition and decoupling, and treating attributes and methods as equals.
|
||||
Also, it does not involve implementation.
|
||||
|
@ -291,11 +303,19 @@ Point.
|
|||
...
|
||||
```
|
||||
|
||||
## patch
|
||||
## Patch
|
||||
|
||||
You can give implementations to classes and traits.
|
||||
You can retrofit a class or trait with an implementation.
|
||||
|
||||
## Refinement type
|
||||
````python
|
||||
Invert = Patch Bool
|
||||
Invert.
|
||||
invert self = not self
|
||||
|
||||
assert False.invert()
|
||||
````
|
||||
|
||||
## Refinement types
|
||||
|
||||
A predicate expression can be type-restricted.
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
ergプログラムは、コンパイル時にすべて厳密に型付けされています。しかし、型はクラスやトレイトによって部分型であると判断できる場合には自動的にキャスティングされます(詳細については[Num](../API/types/traits/Num.md)を参照してください)。
|
||||
|
||||
よって、例えば数値型であれば異なる型同士で計算をすることもできます。
|
||||
よって、例えば数値型であれば異なる型同士でも計算をすることもできます。
|
||||
|
||||
```python
|
||||
a = 1 # 1: Nat(Int)
|
||||
|
@ -22,16 +22,16 @@ d = c * 0 # -0.0: Float
|
|||
e = f // 2 # 0: Nat(Int)
|
||||
```
|
||||
|
||||
これら暗黙的な型の変換を許容したくない場合には宣言時に型を指定することでコンパイル時にエラーとして検出できます。
|
||||
意図しない型の拡大を許容したくない場合には、宣言時に型を指定することでコンパイル時にエラーとして検出できます。
|
||||
|
||||
```python
|
||||
a = 1
|
||||
b: Int = a / 2
|
||||
# error message
|
||||
Error[#0047]: File <stdin>, line 1, in <module>
|
||||
2│ b: Int = int / 2
|
||||
2│ b: Int = a / 2
|
||||
^
|
||||
TypeError: the type of ratio is mismatched:
|
||||
TypeError: the type of b is mismatched:
|
||||
expected: Int
|
||||
but found: Float
|
||||
```
|
||||
|
@ -40,9 +40,9 @@ but found: Float
|
|||
|
||||
True、Falseは真偽値型のシングルトンですが、整数型を汎化型として持ちます。
|
||||
|
||||
そのため、整数型や整数の部分型にあたる自然型、それらの汎化型になる有理数型や浮動小数型で比較をすることができます。
|
||||
そのため、整数型や整数の部分型にあたる自然数型、それらの汎化型になる有理数型や浮動小数点数型で比較をすることができます。
|
||||
|
||||
ただし、浮動小数型は`Eq`をsupersに持たないため、`==`を使うとコンパイルエラーになります。
|
||||
ただし、浮動小数点数型は`Eq`を汎化型に持たないため、`==`を使うとコンパイルエラーになります。
|
||||
|
||||
```python
|
||||
True == 1 # OK
|
||||
|
@ -65,7 +65,7 @@ assert i == 0
|
|||
```
|
||||
|
||||
大文字で始まるものは定数です。コンパイル時計算できるものだけが定数にできます。
|
||||
また、定数は定義以降すべてのスコープで同一です。
|
||||
また、定数は定義以降すべてのスコープで同一です。この性質により、パターンマッチで定数を使うことができます。
|
||||
|
||||
```python
|
||||
random = import "random" # pythonの標準ライブラリをインポートできる
|
||||
|
@ -88,7 +88,7 @@ i = 1.0 # NG
|
|||
|
||||
## 関数
|
||||
|
||||
Haskellなどと同じように定義できます。
|
||||
概ねHaskellと同じように定義できます。
|
||||
|
||||
```python
|
||||
fib 0 = 0
|
||||
|
@ -120,7 +120,9 @@ assert i == 1
|
|||
## プロシージャ
|
||||
|
||||
副作用のあるサブルーチンはプロシージャと呼ばれ、`!`がついています。
|
||||
副作用のないサブルーチンは関数と呼びます。
|
||||
プロシージャを関数中で呼び出すことはできません。
|
||||
これにより、副作用は明示的に分離されます。
|
||||
|
||||
```python
|
||||
print! 1 # 1
|
||||
|
@ -145,7 +147,7 @@ assert p.x == 1
|
|||
|
||||
## 所有権
|
||||
|
||||
Ergは可変オブジェクト(`!`演算子で可変化したオブジェクト)に所有権がついており、複数の場所から書き換えられません。
|
||||
Ergは可変オブジェクト(`!`演算子で可変化したオブジェクト)に所有権がついており、複数の場所からは書き換えられません。
|
||||
|
||||
```python
|
||||
i = !0
|
||||
|
@ -228,9 +230,9 @@ right(_, r) = r
|
|||
後述するタプル/配列/レコードパターンと組み合わせて使う。
|
||||
|
||||
```python
|
||||
[i, ...j] = [1, 2, 3, 4]
|
||||
[i, *j] = [1, 2, 3, 4]
|
||||
assert j == [2, 3, 4]
|
||||
first|T|(fst: T, ...rest: T) = fst
|
||||
first|T|(fst: T, *rest: T) = fst
|
||||
assert first(1, 2, 3) == 1
|
||||
```
|
||||
|
||||
|
@ -247,7 +249,7 @@ m, n = 1, 2
|
|||
|
||||
```python
|
||||
length [] = 0
|
||||
length [_, ...rest] = 1 + length rest
|
||||
length [_, *rest] = 1 + length rest
|
||||
```
|
||||
|
||||
#### レコードパターン
|
||||
|
@ -278,7 +280,16 @@ odds = [i | i <- 1..100; i % 2 == 0]
|
|||
|
||||
## クラス
|
||||
|
||||
Ergでは多重・多段継承をサポートしていません。
|
||||
Ergでは多重継承をサポートしていません。
|
||||
|
||||
クラスはデフォルトで継承不可能であり、継承可能クラスを定義する際は`Inheritable`デコレータをつけます。
|
||||
|
||||
```python
|
||||
@Inheritable
|
||||
Point2D = Class {x = Int; y = Int}
|
||||
|
||||
Point3D = Inherit Point2D, Base := {x = Int; y = Int; z = Int}
|
||||
```
|
||||
|
||||
## トレイト
|
||||
|
||||
|
@ -299,7 +310,15 @@ Point.
|
|||
|
||||
## パッチ
|
||||
|
||||
クラスやトレイトに実装を与えたりできます。
|
||||
クラスやトレイトに後付けで実装を与えたりできます。
|
||||
|
||||
```python
|
||||
Invert = Patch Bool
|
||||
Invert.
|
||||
invert self = not self
|
||||
|
||||
assert False.invert()
|
||||
```
|
||||
|
||||
## 篩型
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue