mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
feat: support symbolized operators
This commit is contained in:
parent
64874f4169
commit
21cb0bb4c1
5 changed files with 187 additions and 147 deletions
|
@ -837,6 +837,8 @@ impl_locational_for_enum!(ClassAttr; Def, Decl, Doc);
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct ClassAttrs(Vec<ClassAttr>);
|
pub struct ClassAttrs(Vec<ClassAttr>);
|
||||||
|
|
||||||
|
impl_stream!(ClassAttrs, ClassAttr);
|
||||||
|
|
||||||
impl NestedDisplay for ClassAttrs {
|
impl NestedDisplay for ClassAttrs {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
fmt_lines(self.0.iter(), f, level)?;
|
fmt_lines(self.0.iter(), f, level)?;
|
||||||
|
@ -856,28 +858,6 @@ impl From<Vec<ClassAttr>> for ClassAttrs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClassAttrs {
|
|
||||||
pub const fn new(attrs: Vec<ClassAttr>) -> Self {
|
|
||||||
Self(attrs)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &ClassAttr> {
|
|
||||||
self.0.iter()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut ClassAttr> {
|
|
||||||
self.0.iter_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoIterator for ClassAttrs {
|
|
||||||
type Item = ClassAttr;
|
|
||||||
type IntoIter = <Vec<ClassAttr> as IntoIterator>::IntoIter;
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
|
||||||
self.0.into_iter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct RecordAttrs(Vec<Def>);
|
pub struct RecordAttrs(Vec<Def>);
|
||||||
|
|
||||||
|
@ -3135,6 +3115,10 @@ impl VarName {
|
||||||
pub fn trim_end_proc_mark(&mut self) {
|
pub fn trim_end_proc_mark(&mut self) {
|
||||||
self.0.content = Str::rc(self.0.content.trim_end_matches('!'));
|
self.0.content = Str::rc(self.0.content.trim_end_matches('!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rename(&mut self, new: Str) {
|
||||||
|
self.0.content = new;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -23,6 +23,36 @@ use crate::ast::{
|
||||||
};
|
};
|
||||||
use crate::token::{Token, TokenKind, COLON, DOT};
|
use crate::token::{Token, TokenKind, COLON, DOT};
|
||||||
|
|
||||||
|
pub fn symop_to_dname(op: &str) -> Option<&'static str> {
|
||||||
|
match op {
|
||||||
|
"`_+_`" => Some("__add__"),
|
||||||
|
"`_-_`" => Some("__sub__"),
|
||||||
|
"`*`" | "`cross`" => Some("__mul__"),
|
||||||
|
"`/`" => Some("__div__"),
|
||||||
|
"`//`" => Some("__floordiv__"),
|
||||||
|
"`**`" => Some("__pow__"),
|
||||||
|
"`%`" => Some("__mod__"),
|
||||||
|
"`@`" | "`dot`" => Some("__matmul__"),
|
||||||
|
"`&&`" => Some("__and__"),
|
||||||
|
"`||`" => Some("__or__"),
|
||||||
|
"`^`" => Some("__xor__"),
|
||||||
|
"`==`" => Some("__eq__"),
|
||||||
|
"`!=`" => Some("__ne__"),
|
||||||
|
"`<`" => Some("__lt__"),
|
||||||
|
"`<=`" => Some("__le__"),
|
||||||
|
"`>`" => Some("__gt__"),
|
||||||
|
"`>=`" => Some("__ge__"),
|
||||||
|
"`<<`" => Some("__lshift__"),
|
||||||
|
"`>>`" => Some("__rshift__"),
|
||||||
|
"`+_`" => Some("__pos__"),
|
||||||
|
"`-_`" => Some("__neg__"),
|
||||||
|
"`~`" => Some("__invert__"),
|
||||||
|
"`!`" => Some("__mutate__"),
|
||||||
|
"`...`" => Some("__spread__"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
enum BufIndex<'i> {
|
enum BufIndex<'i> {
|
||||||
Array(usize),
|
Array(usize),
|
||||||
|
@ -623,6 +653,107 @@ impl Desugarer {
|
||||||
Block::new(self.desugar_pattern(block.into_iter()))
|
Block::new(self.desugar_pattern(block.into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn desugar_def_pattern(&mut self, def: Def, new: &mut Vec<Expr>) {
|
||||||
|
match def {
|
||||||
|
Def {
|
||||||
|
sig: Signature::Var(mut v),
|
||||||
|
body,
|
||||||
|
} => match &v.pat {
|
||||||
|
VarPattern::Tuple(tup) => {
|
||||||
|
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
||||||
|
let block = body
|
||||||
|
.block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let block = self.desugar_pattern_in_block(block);
|
||||||
|
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
||||||
|
new.push(Expr::Def(buf_def));
|
||||||
|
for (n, elem) in tup.elems.iter().enumerate() {
|
||||||
|
self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Tuple(n));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VarPattern::Array(arr) => {
|
||||||
|
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
||||||
|
let block = body
|
||||||
|
.block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let block = self.desugar_pattern_in_block(block);
|
||||||
|
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VarPattern::Record(rec) => {
|
||||||
|
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
||||||
|
let block = body
|
||||||
|
.block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let block = self.desugar_pattern_in_block(block);
|
||||||
|
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
||||||
|
new.push(Expr::Def(buf_def));
|
||||||
|
for VarRecordAttr { lhs, rhs } in rec.attrs.iter() {
|
||||||
|
self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VarPattern::DataPack(pack) => {
|
||||||
|
let t_spec =
|
||||||
|
TypeSpecWithOp::new(COLON, pack.class.clone(), *pack.class_as_expr.clone());
|
||||||
|
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(
|
||||||
|
v.loc(),
|
||||||
|
Some(t_spec), // TODO: これだとvの型指定の意味がなくなる
|
||||||
|
);
|
||||||
|
let block = body
|
||||||
|
.block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let block = self.desugar_pattern_in_block(block);
|
||||||
|
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
||||||
|
new.push(Expr::Def(buf_def));
|
||||||
|
for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() {
|
||||||
|
self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VarPattern::Ident(_) | VarPattern::Discard(_) => {
|
||||||
|
if let VarPattern::Ident(ident) = v.pat {
|
||||||
|
v.pat = VarPattern::Ident(Self::desugar_ident(ident));
|
||||||
|
}
|
||||||
|
let block = body
|
||||||
|
.block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let block = self.desugar_pattern_in_block(block);
|
||||||
|
let body = DefBody::new(body.op, block, body.id);
|
||||||
|
let def = Def::new(Signature::Var(v), body);
|
||||||
|
new.push(Expr::Def(def));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Def {
|
||||||
|
sig: Signature::Subr(mut subr),
|
||||||
|
mut body,
|
||||||
|
} => {
|
||||||
|
subr.ident = Self::desugar_ident(subr.ident);
|
||||||
|
self.desugar_params_patterns(&mut subr.params, &mut body.block);
|
||||||
|
let block = body
|
||||||
|
.block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let block = self.desugar_pattern_in_block(block);
|
||||||
|
let body = DefBody::new(body.op, block, body.id);
|
||||||
|
let def = Def::new(Signature::Subr(subr), body);
|
||||||
|
new.push(Expr::Def(def));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: nested function pattern
|
// TODO: nested function pattern
|
||||||
/// `[i, j] = [1, 2]` -> `i = 1; j = 2`
|
/// `[i, j] = [1, 2]` -> `i = 1; j = 2`
|
||||||
/// `[i, j] = l` -> `i = l[0]; j = l[1]`
|
/// `[i, j] = l` -> `i = l[0]; j = l[1]`
|
||||||
|
@ -636,120 +767,33 @@ impl Desugarer {
|
||||||
let mut new = Vec::with_capacity(chunks.len());
|
let mut new = Vec::with_capacity(chunks.len());
|
||||||
for chunk in chunks.into_iter() {
|
for chunk in chunks.into_iter() {
|
||||||
match chunk {
|
match chunk {
|
||||||
Expr::Def(Def {
|
Expr::Def(def) => {
|
||||||
sig: Signature::Var(v),
|
self.desugar_def_pattern(def, &mut new);
|
||||||
body,
|
}
|
||||||
}) => match &v.pat {
|
Expr::Methods(methods) => {
|
||||||
VarPattern::Tuple(tup) => {
|
let mut new_attrs = Vec::with_capacity(methods.attrs.len());
|
||||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
for attr in methods.attrs.into_iter() {
|
||||||
let block = body
|
match attr {
|
||||||
.block
|
ClassAttr::Def(def) => {
|
||||||
.into_iter()
|
let mut new = vec![];
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
self.desugar_def_pattern(def, &mut new);
|
||||||
.collect();
|
let Expr::Def(def) = new.remove(0) else {
|
||||||
let block = self.desugar_pattern_in_block(block);
|
todo!("{new:?}")
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
};
|
||||||
new.push(Expr::Def(buf_def));
|
new_attrs.push(ClassAttr::Def(def));
|
||||||
for (n, elem) in tup.elems.iter().enumerate() {
|
}
|
||||||
self.desugar_nested_var_pattern(
|
_ => {
|
||||||
&mut new,
|
new_attrs.push(attr);
|
||||||
elem,
|
}
|
||||||
&buf_name,
|
|
||||||
BufIndex::Tuple(n),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VarPattern::Array(arr) => {
|
let methods = Methods::new(
|
||||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
methods.class,
|
||||||
let block = body
|
*methods.class_as_expr,
|
||||||
.block
|
methods.vis,
|
||||||
.into_iter()
|
ClassAttrs::from(new_attrs),
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
);
|
||||||
.collect();
|
new.push(Expr::Methods(methods));
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
|
||||||
new.push(Expr::Def(buf_def));
|
|
||||||
for (n, elem) in arr.elems.iter().enumerate() {
|
|
||||||
self.desugar_nested_var_pattern(
|
|
||||||
&mut new,
|
|
||||||
elem,
|
|
||||||
&buf_name,
|
|
||||||
BufIndex::Array(n),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VarPattern::Record(rec) => {
|
|
||||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
|
||||||
let block = body
|
|
||||||
.block
|
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
|
||||||
new.push(Expr::Def(buf_def));
|
|
||||||
for VarRecordAttr { lhs, rhs } in rec.attrs.iter() {
|
|
||||||
self.desugar_nested_var_pattern(
|
|
||||||
&mut new,
|
|
||||||
rhs,
|
|
||||||
&buf_name,
|
|
||||||
BufIndex::Record(lhs),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VarPattern::DataPack(pack) => {
|
|
||||||
let t_spec = TypeSpecWithOp::new(
|
|
||||||
COLON,
|
|
||||||
pack.class.clone(),
|
|
||||||
*pack.class_as_expr.clone(),
|
|
||||||
);
|
|
||||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(
|
|
||||||
v.loc(),
|
|
||||||
Some(t_spec), // TODO: これだとvの型指定の意味がなくなる
|
|
||||||
);
|
|
||||||
let block = body
|
|
||||||
.block
|
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
|
||||||
new.push(Expr::Def(buf_def));
|
|
||||||
for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() {
|
|
||||||
self.desugar_nested_var_pattern(
|
|
||||||
&mut new,
|
|
||||||
rhs,
|
|
||||||
&buf_name,
|
|
||||||
BufIndex::Record(lhs),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VarPattern::Ident(_) | VarPattern::Discard(_) => {
|
|
||||||
let block = body
|
|
||||||
.block
|
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let body = DefBody::new(body.op, block, body.id);
|
|
||||||
let def = Def::new(Signature::Var(v), body);
|
|
||||||
new.push(Expr::Def(def));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Expr::Def(Def {
|
|
||||||
sig: Signature::Subr(mut subr),
|
|
||||||
mut body,
|
|
||||||
}) => {
|
|
||||||
self.desugar_params_patterns(&mut subr.params, &mut body.block);
|
|
||||||
let block = body
|
|
||||||
.block
|
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let body = DefBody::new(body.op, block, body.id);
|
|
||||||
let def = Def::new(Signature::Subr(subr), body);
|
|
||||||
new.push(Expr::Def(def));
|
|
||||||
}
|
}
|
||||||
Expr::Dummy(dummy) => {
|
Expr::Dummy(dummy) => {
|
||||||
let loc = dummy.loc;
|
let loc = dummy.loc;
|
||||||
|
@ -1450,6 +1494,8 @@ impl Desugarer {
|
||||||
|
|
||||||
/// x[y] => x.__getitem__(y)
|
/// x[y] => x.__getitem__(y)
|
||||||
/// x.0 => x.__Tuple_getitem__(0)
|
/// x.0 => x.__Tuple_getitem__(0)
|
||||||
|
/// `==`(x, y) => __eq__(x, y)
|
||||||
|
/// x.`==` y => x.__eq__ y
|
||||||
fn desugar_acc(module: Module) -> Module {
|
fn desugar_acc(module: Module) -> Module {
|
||||||
Self::desugar_all_chunks(module, Self::rec_desugar_acc)
|
Self::desugar_all_chunks(module, Self::rec_desugar_acc)
|
||||||
}
|
}
|
||||||
|
@ -1500,12 +1546,20 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
Accessor::Attr(mut attr) => {
|
Accessor::Attr(mut attr) => {
|
||||||
attr.obj = Box::new(Self::rec_desugar_acc(*attr.obj));
|
attr.obj = Box::new(Self::rec_desugar_acc(*attr.obj));
|
||||||
|
attr.ident = Self::desugar_ident(attr.ident);
|
||||||
Expr::Accessor(Accessor::Attr(attr))
|
Expr::Accessor(Accessor::Attr(attr))
|
||||||
}
|
}
|
||||||
other => Expr::Accessor(other),
|
Accessor::Ident(ident) => Expr::Accessor(Accessor::Ident(Self::desugar_ident(ident))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn desugar_ident(mut ident: Identifier) -> Identifier {
|
||||||
|
if let Some(name) = symop_to_dname(ident.inspect()) {
|
||||||
|
ident.name.rename(name.into());
|
||||||
|
}
|
||||||
|
ident
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: pipeline desugaring (move from `Parser`)
|
// TODO: pipeline desugaring (move from `Parser`)
|
||||||
fn desugar_operator(module: Module) -> Module {
|
fn desugar_operator(module: Module) -> Module {
|
||||||
Self::desugar_all_chunks(module, Self::rec_desugar_operator)
|
Self::desugar_all_chunks(module, Self::rec_desugar_operator)
|
||||||
|
|
|
@ -277,18 +277,17 @@ impl Lexer /*<'a>*/ {
|
||||||
matches!(
|
matches!(
|
||||||
s,
|
s,
|
||||||
"+_" | "_+_"
|
"+_" | "_+_"
|
||||||
|
| "-_"
|
||||||
| "-"
|
| "-"
|
||||||
| "*"
|
| "*"
|
||||||
| "/"
|
| "/"
|
||||||
| "//"
|
| "//"
|
||||||
| "**"
|
| "**"
|
||||||
| "%"
|
| "%"
|
||||||
| ".."
|
|
||||||
| "..="
|
|
||||||
| "~"
|
| "~"
|
||||||
| "&&"
|
| "&&"
|
||||||
| "||"
|
| "||"
|
||||||
| "^^"
|
| "^"
|
||||||
| ">>"
|
| ">>"
|
||||||
| "<<"
|
| "<<"
|
||||||
| "=="
|
| "=="
|
||||||
|
@ -1544,12 +1543,14 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Symbolized operators (シンボル化された演算子)
|
// Symbolized operators (シンボル化された演算子)
|
||||||
// e.g. `-`(l, r) = l + (-r)
|
// e.g. `-`(l, r) == __sub__(1, r) == l - r
|
||||||
Some('`') => {
|
Some('`') => {
|
||||||
let mut op = "".to_string();
|
let mut op = "".to_string();
|
||||||
while let Some(c) = self.consume() {
|
while let Some(c) = self.consume() {
|
||||||
if c == '`' {
|
if c == '`' {
|
||||||
if Self::is_definable_operator(&op[..]) {
|
if Self::is_definable_operator(&op[..]) {
|
||||||
|
op.insert(0, '`');
|
||||||
|
op.push('`');
|
||||||
return self.accept(Symbol, &op);
|
return self.accept(Symbol, &op);
|
||||||
} else {
|
} else {
|
||||||
let token = self.emit_token(Illegal, &op);
|
let token = self.emit_token(Illegal, &op);
|
||||||
|
@ -1569,10 +1570,10 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
token.loc(),
|
token.loc(),
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"japanese" => format!("`{}`はユーザー定義できません", &token.content),
|
"japanese" => format!("`{}`は存在しないか、ユーザー定義できません", &token.content),
|
||||||
"simplified_chinese" => format!("`{}`不能由用户定义", &token.content),
|
"simplified_chinese" => format!("`{}`不存在或不能由用户定义", &token.content),
|
||||||
"traditional_chinese" => format!("`{}`不能由用戶定義", &token.content),
|
"traditional_chinese" => format!("`{}`不存在或不能由用戶定義", &token.content),
|
||||||
"english" => format!("`{}` cannot be defined by user", &token.content),
|
"english" => format!("`{}` does not exist or cannot be defined by user", &token.content),
|
||||||
),
|
),
|
||||||
hint,
|
hint,
|
||||||
)));
|
)));
|
||||||
|
|
|
@ -5,5 +5,5 @@ private = "this is a private variable"
|
||||||
.C.
|
.C.
|
||||||
x = 1
|
x = 1
|
||||||
.C|<: Eq|.
|
.C|<: Eq|.
|
||||||
__eq__ self, other =
|
`==` self, other =
|
||||||
self.x == other.x
|
self.x == other.x
|
||||||
|
|
|
@ -4,14 +4,15 @@ Point.
|
||||||
norm self = self::x**2 + self::y**2
|
norm self = self::x**2 + self::y**2
|
||||||
Point|<: Add(Point)|.
|
Point|<: Add(Point)|.
|
||||||
Output = Point
|
Output = Point
|
||||||
__add__ self, other: Point =
|
# This is same as `__add__ self, other: Point = ...`
|
||||||
|
`_+_` self, other: Point =
|
||||||
Point.new(self::x + other::x, self::y + other::y)
|
Point.new(self::x + other::x, self::y + other::y)
|
||||||
Point|<: Mul(Point)|.
|
Point|<: Mul(Point)|.
|
||||||
Output = Int
|
Output = Int
|
||||||
__mul__ self, other: Point =
|
`*` self, other: Point =
|
||||||
self::x * other::x + self::y * other::y
|
self::x * other::x + self::y * other::y
|
||||||
Point|<: Eq|.
|
Point|<: Eq|.
|
||||||
__eq__ self, other: Point =
|
`==` self, other: Point =
|
||||||
self::x == other::x and self::y == other::y
|
self::x == other::x and self::y == other::y
|
||||||
|
|
||||||
p = Point.new 1, 2
|
p = Point.new 1, 2
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue