mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 12:14:43 +00:00
fix(compiler): runtime type matching system
This commit is contained in:
parent
92614ce8d2
commit
af0fff8226
25 changed files with 793 additions and 429 deletions
|
@ -480,8 +480,40 @@ impl<'a> HIRVisitor<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_sig_info(&self, sig: &Signature, token: &Token) -> Option<VarInfo> {
|
||||||
|
match sig {
|
||||||
|
Signature::Var(var) => {
|
||||||
|
self.return_var_info_if_same(&var.ident, var.ident.name.token(), token)
|
||||||
|
}
|
||||||
|
Signature::Subr(subr) => self
|
||||||
|
.return_var_info_if_same(&subr.ident, subr.ident.name.token(), token)
|
||||||
|
.or_else(|| self.get_params_info(&subr.params, token)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_params_info(&self, params: &Params, token: &Token) -> Option<VarInfo> {
|
||||||
|
for param in params.non_defaults.iter() {
|
||||||
|
if param.raw.pat.loc() == token.loc() {
|
||||||
|
return Some(param.vi.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(var) = ¶ms.var_params {
|
||||||
|
if var.raw.pat.loc() == token.loc() {
|
||||||
|
return Some(var.vi.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for param in params.defaults.iter() {
|
||||||
|
if param.sig.raw.pat.loc() == token.loc() {
|
||||||
|
return Some(param.sig.vi.clone());
|
||||||
|
} else if let Some(vi) = self.get_expr_info(¶m.default_val, token) {
|
||||||
|
return Some(vi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn get_def_info(&self, def: &Def, token: &Token) -> Option<VarInfo> {
|
fn get_def_info(&self, def: &Def, token: &Token) -> Option<VarInfo> {
|
||||||
self.return_var_info_if_same(def.sig.ident(), def.sig.ident().name.token(), token)
|
self.get_sig_info(&def.sig, token)
|
||||||
.or_else(|| self.get_block_info(&def.body.block, token))
|
.or_else(|| self.get_block_info(&def.body.block, token))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,13 +522,7 @@ impl<'a> HIRVisitor<'a> {
|
||||||
.require_or_sup
|
.require_or_sup
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|req_sup| self.get_expr_info(req_sup, token))
|
.and_then(|req_sup| self.get_expr_info(req_sup, token))
|
||||||
.or_else(|| {
|
.or_else(|| self.get_sig_info(&class_def.sig, token))
|
||||||
self.return_var_info_if_same(
|
|
||||||
class_def.sig.ident(),
|
|
||||||
class_def.sig.ident().name.token(),
|
|
||||||
token,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.or_else(|| self.get_block_info(&class_def.methods, token))
|
.or_else(|| self.get_block_info(&class_def.methods, token))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
for (nd_param, nd_t) in subr.params.non_defaults.iter().zip(nd_ts) {
|
for (nd_param, nd_t) in subr.params.non_defaults.iter().zip(nd_ts) {
|
||||||
if nd_param.t_spec.is_some() {
|
if nd_param.raw.t_spec.is_some() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let hint = type_anot(
|
let hint = type_anot(
|
||||||
|
@ -125,7 +125,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
result.push(hint);
|
result.push(hint);
|
||||||
}
|
}
|
||||||
for (d_param, d_t) in subr.params.defaults.iter().zip(d_ts) {
|
for (d_param, d_t) in subr.params.defaults.iter().zip(d_ts) {
|
||||||
if d_param.sig.t_spec.is_some() {
|
if d_param.sig.raw.t_spec.is_some() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let hint = type_anot(
|
let hint = type_anot(
|
||||||
|
@ -185,7 +185,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
for (nd_param, nd_t) in lambda.params.non_defaults.iter().zip(nd_ts) {
|
for (nd_param, nd_t) in lambda.params.non_defaults.iter().zip(nd_ts) {
|
||||||
if nd_param.t_spec.is_some() {
|
if nd_param.raw.t_spec.is_some() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let hint = type_anot(
|
let hint = type_anot(
|
||||||
|
@ -197,7 +197,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
||||||
result.push(hint);
|
result.push(hint);
|
||||||
}
|
}
|
||||||
for (d_param, d_t) in lambda.params.defaults.iter().zip(d_ts) {
|
for (d_param, d_t) in lambda.params.defaults.iter().zip(d_ts) {
|
||||||
if d_param.sig.t_spec.is_some() {
|
if d_param.sig.raw.t_spec.is_some() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let hint = type_anot(
|
let hint = type_anot(
|
||||||
|
|
|
@ -25,9 +25,7 @@ use erg_common::{
|
||||||
use erg_parser::ast::{DefId, DefKind};
|
use erg_parser::ast::{DefId, DefKind};
|
||||||
use CommonOpcode::*;
|
use CommonOpcode::*;
|
||||||
|
|
||||||
use erg_parser::ast::PreDeclTypeSpec;
|
use erg_parser::ast::{ParamPattern, VarName};
|
||||||
use erg_parser::ast::TypeSpec;
|
|
||||||
use erg_parser::ast::{NonDefaultParamSignature, ParamPattern, VarName};
|
|
||||||
use erg_parser::token::DOT;
|
use erg_parser::token::DOT;
|
||||||
use erg_parser::token::EQUAL;
|
use erg_parser::token::EQUAL;
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
@ -36,11 +34,12 @@ use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||||
use crate::error::CompileError;
|
use crate::error::CompileError;
|
||||||
use crate::hir::{
|
use crate::hir::{
|
||||||
Accessor, Args, Array, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, Identifier, Lambda,
|
Accessor, Args, Array, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, Identifier, Lambda,
|
||||||
Literal, Params, PatchDef, PosArg, ReDef, Record, Signature, SubrSignature, Tuple, UnaryOp,
|
Literal, NonDefaultParamSignature, Params, PatchDef, PosArg, ReDef, Record, Signature,
|
||||||
VarSignature, HIR,
|
SubrSignature, Tuple, UnaryOp, VarSignature, HIR,
|
||||||
};
|
};
|
||||||
use crate::ty::value::ValueObj;
|
use crate::ty::value::ValueObj;
|
||||||
use crate::ty::{HasType, Type, TypeCode, TypePair};
|
use crate::ty::{HasType, Type, TypeCode, TypePair};
|
||||||
|
use crate::varinfo::VarInfo;
|
||||||
use erg_common::fresh::fresh_varname;
|
use erg_common::fresh::fresh_varname;
|
||||||
use AccessKind::*;
|
use AccessKind::*;
|
||||||
use Type::*;
|
use Type::*;
|
||||||
|
@ -1850,46 +1849,9 @@ impl PyCodeGenerator {
|
||||||
) -> Vec<usize> {
|
) -> Vec<usize> {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
let mut pop_jump_points = vec![];
|
let mut pop_jump_points = vec![];
|
||||||
if let Some(t_spec) = param.t_spec.map(|spec| spec.t_spec) {
|
if let Some(t_spec) = param.t_spec_as_expr {
|
||||||
// If it's the last arm, there's no need to inspect it
|
// If it's the last arm, there's no need to inspect it
|
||||||
if !is_last_arm {
|
if !is_last_arm {
|
||||||
if self.py_version.minor >= Some(11) {
|
|
||||||
self.emit_match_guard_311(t_spec, &mut pop_jump_points);
|
|
||||||
} else {
|
|
||||||
self.emit_match_guard_310(t_spec, &mut pop_jump_points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match param.pat {
|
|
||||||
ParamPattern::VarName(name) => {
|
|
||||||
let ident = Identifier::bare(None, name);
|
|
||||||
self.emit_store_instr(ident, AccessKind::Name);
|
|
||||||
}
|
|
||||||
ParamPattern::Discard(_) => {
|
|
||||||
self.emit_pop_top();
|
|
||||||
}
|
|
||||||
_other => unreachable!(),
|
|
||||||
}
|
|
||||||
pop_jump_points
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_match_guard_311(&mut self, t_spec: TypeSpec, pop_jump_points: &mut Vec<usize>) {
|
|
||||||
log!(info "entered {} ({t_spec})", fn_name!());
|
|
||||||
match t_spec {
|
|
||||||
TypeSpec::Enum(enum_t) => {
|
|
||||||
let elems = ValueObj::vec_from_const_args(enum_t);
|
|
||||||
self.emit_load_const(elems);
|
|
||||||
self.write_instr(CONTAINS_OP);
|
|
||||||
self.write_arg(0);
|
|
||||||
self.stack_dec();
|
|
||||||
pop_jump_points.push(self.lasti());
|
|
||||||
// in 3.11, POP_JUMP_IF_FALSE is replaced with POP_JUMP_FORWARD_IF_FALSE
|
|
||||||
// but the numbers are the same, only the way the jumping points are calculated is different.
|
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE); // jump to the next case
|
|
||||||
self.write_arg(0);
|
|
||||||
// self.stack_dec();
|
|
||||||
}
|
|
||||||
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) if simple.args.is_empty() => {
|
|
||||||
// arg null
|
// arg null
|
||||||
// ↓ SWAP 1
|
// ↓ SWAP 1
|
||||||
// null arg
|
// null arg
|
||||||
|
@ -1906,15 +1868,7 @@ impl PyCodeGenerator {
|
||||||
}
|
}
|
||||||
self.emit_load_name_instr(Identifier::private("#in_operator"));
|
self.emit_load_name_instr(Identifier::private("#in_operator"));
|
||||||
self.rot2();
|
self.rot2();
|
||||||
// TODO: DOT/not
|
self.emit_expr(t_spec);
|
||||||
let mut typ = Identifier::bare(Some(DOT), simple.ident.name);
|
|
||||||
// TODO:
|
|
||||||
typ.vi.py_name = match &typ.name.inspect()[..] {
|
|
||||||
"Int" => Some("int".into()),
|
|
||||||
"Float" => Some("float".into()),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
self.emit_load_name_instr(typ);
|
|
||||||
self.emit_precall_and_call(2);
|
self.emit_precall_and_call(2);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
pop_jump_points.push(self.lasti());
|
pop_jump_points.push(self.lasti());
|
||||||
|
@ -1924,127 +1878,18 @@ impl PyCodeGenerator {
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
// _: (Int, Str)
|
|
||||||
TypeSpec::Tuple(tup) => {
|
|
||||||
let len = tup.tys.len();
|
|
||||||
for (i, t_spec) in tup.tys.into_iter().enumerate() {
|
|
||||||
if i != 0 && i != len - 1 {
|
|
||||||
self.dup_top();
|
|
||||||
}
|
}
|
||||||
self.emit_load_const(i);
|
match param.raw.pat {
|
||||||
self.write_instr(Opcode311::BINARY_SUBSCR);
|
ParamPattern::VarName(name) => {
|
||||||
self.write_arg(0);
|
let ident = Identifier::bare(None, name);
|
||||||
self.stack_dec();
|
self.emit_store_instr(ident, AccessKind::Name);
|
||||||
self.emit_match_guard_311(t_spec, pop_jump_points);
|
|
||||||
}
|
}
|
||||||
|
ParamPattern::Discard(_) => {
|
||||||
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
// TODO: consider ordering (e.g. both [1, 2] and [2, 1] is type of [{1, 2}; 2])
|
_other => unreachable!(),
|
||||||
TypeSpec::Array(arr) => {
|
|
||||||
let ValueObj::Nat(len) = ValueObj::from_const_expr(arr.len) else { todo!() };
|
|
||||||
for i in 0..=(len - 1) {
|
|
||||||
if i != 0 && i != len - 1 {
|
|
||||||
self.dup_top();
|
|
||||||
}
|
|
||||||
self.emit_load_const(i);
|
|
||||||
self.write_instr(Opcode311::BINARY_SUBSCR);
|
|
||||||
self.write_arg(0);
|
|
||||||
self.stack_dec();
|
|
||||||
self.emit_match_guard_311(*arr.ty.clone(), pop_jump_points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*TypeSpec::Interval { op, lhs, rhs } => {
|
|
||||||
let binop = BinOp::new(op, lhs.downcast(), rhs.downcast(), VarInfo::default());
|
|
||||||
self.emit_binop(binop);
|
|
||||||
}*/
|
|
||||||
// TODO:
|
|
||||||
TypeSpec::Infer(_) => unreachable!(),
|
|
||||||
// TODO:
|
|
||||||
other => log!(err "{other}"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_match_guard_310(&mut self, t_spec: TypeSpec, pop_jump_points: &mut Vec<usize>) {
|
|
||||||
log!(info "entered {} ({t_spec})", fn_name!());
|
|
||||||
match t_spec {
|
|
||||||
TypeSpec::Enum(enum_t) => {
|
|
||||||
let elems = ValueObj::vec_from_const_args(enum_t);
|
|
||||||
self.emit_load_const(elems);
|
|
||||||
self.write_instr(Opcode310::CONTAINS_OP);
|
|
||||||
self.write_arg(0);
|
|
||||||
self.stack_dec();
|
|
||||||
pop_jump_points.push(self.lasti());
|
|
||||||
// in 3.11, POP_JUMP_IF_FALSE is replaced with POP_JUMP_FORWARD_IF_FALSE
|
|
||||||
// but the numbers are the same, only the way the jumping points are calculated is different.
|
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE); // jump to the next case
|
|
||||||
self.write_arg(0);
|
|
||||||
// self.stack_dec();
|
|
||||||
}
|
|
||||||
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) if simple.args.is_empty() => {
|
|
||||||
// arg
|
|
||||||
// ↓ LOAD_NAME(in_operator)
|
|
||||||
// arg in_operator
|
|
||||||
// ↓ ROT 2
|
|
||||||
// in_operator arg
|
|
||||||
// ↓ LOAD_NAME(typ)
|
|
||||||
// in_operator arg typ
|
|
||||||
self.emit_load_name_instr(Identifier::private("#in_operator"));
|
|
||||||
self.rot2();
|
|
||||||
// TODO: DOT/not
|
|
||||||
let mut typ = Identifier::bare(Some(DOT), simple.ident.name);
|
|
||||||
// TODO:
|
|
||||||
typ.vi.py_name = match &typ.name.inspect()[..] {
|
|
||||||
"Int" => Some("int".into()),
|
|
||||||
"Float" => Some("float".into()),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
self.emit_load_name_instr(typ);
|
|
||||||
self.write_instr(Opcode310::CALL_FUNCTION);
|
|
||||||
self.write_arg(2);
|
|
||||||
self.stack_dec();
|
|
||||||
pop_jump_points.push(self.lasti());
|
|
||||||
// in 3.11, POP_JUMP_IF_FALSE is replaced with POP_JUMP_FORWARD_IF_FALSE
|
|
||||||
// but the numbers are the same, only the way the jumping points are calculated is different.
|
|
||||||
self.write_instr(Opcode310::POP_JUMP_IF_FALSE); // jump to the next case
|
|
||||||
self.write_arg(0);
|
|
||||||
self.stack_dec();
|
|
||||||
}
|
|
||||||
// _: (Int, Str)
|
|
||||||
TypeSpec::Tuple(tup) => {
|
|
||||||
let len = tup.tys.len();
|
|
||||||
for (i, t_spec) in tup.tys.into_iter().enumerate() {
|
|
||||||
if i != 0 && i != len - 1 {
|
|
||||||
self.dup_top();
|
|
||||||
}
|
|
||||||
self.emit_load_const(i);
|
|
||||||
self.write_instr(Opcode310::BINARY_SUBSCR);
|
|
||||||
self.write_arg(0);
|
|
||||||
self.stack_dec();
|
|
||||||
self.emit_match_guard_310(t_spec, pop_jump_points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: consider ordering (e.g. both [1, 2] and [2, 1] is type of [{1, 2}; 2])
|
|
||||||
TypeSpec::Array(arr) => {
|
|
||||||
let ValueObj::Nat(len) = ValueObj::from_const_expr(arr.len) else { todo!() };
|
|
||||||
for i in 0..=(len - 1) {
|
|
||||||
if i != 0 && i != len - 1 {
|
|
||||||
self.dup_top();
|
|
||||||
}
|
|
||||||
self.emit_load_const(i);
|
|
||||||
self.write_instr(Opcode310::BINARY_SUBSCR);
|
|
||||||
self.write_arg(0);
|
|
||||||
self.stack_dec();
|
|
||||||
self.emit_match_guard_310(*arr.ty.clone(), pop_jump_points);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*TypeSpec::Interval { op, lhs, rhs } => {
|
|
||||||
let binop = BinOp::new(op, lhs.downcast(), rhs.downcast(), VarInfo::default());
|
|
||||||
self.emit_binop(binop);
|
|
||||||
}*/
|
|
||||||
// TODO:
|
|
||||||
TypeSpec::Infer(_) => unreachable!(),
|
|
||||||
// TODO:
|
|
||||||
other => log!(err "{other}"),
|
|
||||||
}
|
}
|
||||||
|
pop_jump_points
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_with_instr_311(&mut self, mut args: Args) {
|
fn emit_with_instr_311(&mut self, mut args: Args) {
|
||||||
|
@ -2878,14 +2723,23 @@ impl PyCodeGenerator {
|
||||||
let mut ident = Identifier::public_with_line(DOT, Str::ever("__init__"), line);
|
let mut ident = Identifier::public_with_line(DOT, Str::ever("__init__"), line);
|
||||||
ident.vi.t = __new__.clone();
|
ident.vi.t = __new__.clone();
|
||||||
let self_param = VarName::from_str_and_line(Str::ever("self"), line);
|
let self_param = VarName::from_str_and_line(Str::ever("self"), line);
|
||||||
let self_param = NonDefaultParamSignature::new(ParamPattern::VarName(self_param), None);
|
let vi = VarInfo::parameter(
|
||||||
|
__new__.return_t().unwrap().clone(),
|
||||||
|
ident.vi.def_loc.clone(),
|
||||||
|
);
|
||||||
|
let raw =
|
||||||
|
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(self_param), None);
|
||||||
|
let self_param = NonDefaultParamSignature::new(raw, vi, None);
|
||||||
let (param_name, params) = if let Some(new_first_param) = new_first_param {
|
let (param_name, params) = if let Some(new_first_param) = new_first_param {
|
||||||
let param_name = new_first_param
|
let param_name = new_first_param
|
||||||
.name()
|
.name()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.unwrap_or_else(fresh_varname);
|
.unwrap_or_else(fresh_varname);
|
||||||
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
||||||
let param = NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
let raw =
|
||||||
|
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||||
|
let vi = VarInfo::parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
|
||||||
|
let param = NonDefaultParamSignature::new(raw, vi, None);
|
||||||
let params = Params::new(vec![self_param, param], None, vec![], None);
|
let params = Params::new(vec![self_param, param], None, vec![], None);
|
||||||
(param_name, params)
|
(param_name, params)
|
||||||
} else {
|
} else {
|
||||||
|
@ -2965,7 +2819,10 @@ impl PyCodeGenerator {
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.unwrap_or_else(fresh_varname);
|
.unwrap_or_else(fresh_varname);
|
||||||
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
||||||
let param = NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
let vi = VarInfo::parameter(new_first_param.typ().clone(), ident.vi.def_loc.clone());
|
||||||
|
let raw =
|
||||||
|
erg_parser::ast::NonDefaultParamSignature::new(ParamPattern::VarName(param), None);
|
||||||
|
let param = NonDefaultParamSignature::new(raw, vi, None);
|
||||||
let params = Params::new(vec![param], None, vec![], None);
|
let params = Params::new(vec![param], None, vec![], None);
|
||||||
let sig = SubrSignature::new(ident, params, sig.t_spec().cloned());
|
let sig = SubrSignature::new(ident, params, sig.t_spec().cloned());
|
||||||
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
|
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
|
||||||
|
|
|
@ -761,6 +761,26 @@ impl Context {
|
||||||
self.methods_list = methods_list;
|
self.methods_list = methods_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_params_t(&self, params: &mut hir::Params) -> TyCheckResult<()> {
|
||||||
|
for param in params.non_defaults.iter_mut() {
|
||||||
|
param.vi.t =
|
||||||
|
self.deref_tyvar(mem::take(&mut param.vi.t), Contravariant, param.loc())?;
|
||||||
|
}
|
||||||
|
if let Some(var_params) = &mut params.var_params {
|
||||||
|
var_params.vi.t = self.deref_tyvar(
|
||||||
|
mem::take(&mut var_params.vi.t),
|
||||||
|
Contravariant,
|
||||||
|
var_params.loc(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
for param in params.defaults.iter_mut() {
|
||||||
|
param.sig.vi.t =
|
||||||
|
self.deref_tyvar(mem::take(&mut param.sig.vi.t), Contravariant, param.loc())?;
|
||||||
|
self.resolve_expr_t(&mut param.default_val)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_expr_t(&self, expr: &mut hir::Expr) -> TyCheckResult<()> {
|
fn resolve_expr_t(&self, expr: &mut hir::Expr) -> TyCheckResult<()> {
|
||||||
match expr {
|
match expr {
|
||||||
hir::Expr::Lit(_) => Ok(()),
|
hir::Expr::Lit(_) => Ok(()),
|
||||||
|
@ -898,6 +918,9 @@ impl Context {
|
||||||
hir::Expr::Def(def) => {
|
hir::Expr::Def(def) => {
|
||||||
*def.sig.ref_mut_t() =
|
*def.sig.ref_mut_t() =
|
||||||
self.deref_tyvar(mem::take(def.sig.ref_mut_t()), Covariant, def.sig.loc())?;
|
self.deref_tyvar(mem::take(def.sig.ref_mut_t()), Covariant, def.sig.loc())?;
|
||||||
|
if let Some(params) = def.sig.params_mut() {
|
||||||
|
self.resolve_params_t(params)?;
|
||||||
|
}
|
||||||
for chunk in def.body.block.iter_mut() {
|
for chunk in def.body.block.iter_mut() {
|
||||||
self.resolve_expr_t(chunk)?;
|
self.resolve_expr_t(chunk)?;
|
||||||
}
|
}
|
||||||
|
@ -905,6 +928,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
hir::Expr::Lambda(lambda) => {
|
hir::Expr::Lambda(lambda) => {
|
||||||
lambda.t = self.deref_tyvar(mem::take(&mut lambda.t), Covariant, lambda.loc())?;
|
lambda.t = self.deref_tyvar(mem::take(&mut lambda.t), Covariant, lambda.loc())?;
|
||||||
|
self.resolve_params_t(&mut lambda.params)?;
|
||||||
for chunk in lambda.body.iter_mut() {
|
for chunk in lambda.body.iter_mut() {
|
||||||
self.resolve_expr_t(chunk)?;
|
self.resolve_expr_t(chunk)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,7 +271,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let rhs = self.instantiate_param_sig_t(
|
let rhs = self.instantiate_param_sig_t(
|
||||||
&lambda.params.non_defaults[0],
|
&lambda.params.non_defaults[0].raw,
|
||||||
None,
|
None,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
Normal,
|
Normal,
|
||||||
|
|
|
@ -379,8 +379,14 @@ impl Context {
|
||||||
mode: RegistrationMode,
|
mode: RegistrationMode,
|
||||||
kind: ParamKind,
|
kind: ParamKind,
|
||||||
) -> TyCheckResult<Type> {
|
) -> TyCheckResult<Type> {
|
||||||
let spec_t = if let Some(spec_with_op) = &sig.t_spec {
|
let spec_t = if let Some(t_spec_with_op) = &sig.t_spec {
|
||||||
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tmp_tv_cache, mode, false)?
|
self.instantiate_typespec(
|
||||||
|
&t_spec_with_op.t_spec,
|
||||||
|
opt_decl_t,
|
||||||
|
tmp_tv_cache,
|
||||||
|
mode,
|
||||||
|
false,
|
||||||
|
)?
|
||||||
} else {
|
} else {
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::ParamPattern::Lit(lit) => v_enum(set![self.eval_lit(lit)?]),
|
ast::ParamPattern::Lit(lit) => v_enum(set![self.eval_lit(lit)?]),
|
||||||
|
|
|
@ -242,10 +242,11 @@ impl Context {
|
||||||
Ok(vi)
|
Ok(vi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// TODO: sig should be immutable
|
||||||
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
||||||
fn assign_param(
|
fn assign_param(
|
||||||
&mut self,
|
&mut self,
|
||||||
sig: &ast::NonDefaultParamSignature,
|
sig: &mut hir::NonDefaultParamSignature,
|
||||||
opt_decl_t: Option<&ParamTy>,
|
opt_decl_t: Option<&ParamTy>,
|
||||||
kind: ParamKind,
|
kind: ParamKind,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
|
@ -256,12 +257,12 @@ impl Context {
|
||||||
};
|
};
|
||||||
let default = kind.default_info();
|
let default = kind.default_info();
|
||||||
let is_var_params = kind.is_var_params();
|
let is_var_params = kind.is_var_params();
|
||||||
match &sig.pat {
|
match &sig.raw.pat {
|
||||||
// Literal patterns will be desugared to discard patterns
|
// Literal patterns will be desugared to discard patterns
|
||||||
ast::ParamPattern::Lit(_) => unreachable!(),
|
ast::ParamPattern::Lit(_) => unreachable!(),
|
||||||
ast::ParamPattern::Discard(token) => {
|
ast::ParamPattern::Discard(token) => {
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let spec_t = self.instantiate_param_sig_t(
|
||||||
sig,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut TyVarCache::new(self.level, self),
|
&mut TyVarCache::new(self.level, self),
|
||||||
Normal,
|
Normal,
|
||||||
|
@ -279,6 +280,7 @@ impl Context {
|
||||||
None,
|
None,
|
||||||
self.absolutize(token.loc()),
|
self.absolutize(token.loc()),
|
||||||
);
|
);
|
||||||
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(VarName::from_static("_")), vi));
|
self.params.push((Some(VarName::from_static("_")), vi));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -298,7 +300,7 @@ impl Context {
|
||||||
// ok, not defined
|
// ok, not defined
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let spec_t = self.instantiate_param_sig_t(
|
||||||
sig,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
Normal,
|
Normal,
|
||||||
|
@ -332,6 +334,7 @@ impl Context {
|
||||||
if let Some(shared) = self.shared() {
|
if let Some(shared) = self.shared() {
|
||||||
shared.index.register(&vi);
|
shared.index.register(&vi);
|
||||||
}
|
}
|
||||||
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(name.clone()), vi));
|
self.params.push((Some(name.clone()), vi));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -352,7 +355,7 @@ impl Context {
|
||||||
// ok, not defined
|
// ok, not defined
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let spec_t = self.instantiate_param_sig_t(
|
||||||
sig,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
Normal,
|
Normal,
|
||||||
|
@ -377,6 +380,7 @@ impl Context {
|
||||||
None,
|
None,
|
||||||
self.absolutize(name.loc()),
|
self.absolutize(name.loc()),
|
||||||
);
|
);
|
||||||
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(name.clone()), vi));
|
self.params.push((Some(name.clone()), vi));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -397,7 +401,7 @@ impl Context {
|
||||||
// ok, not defined
|
// ok, not defined
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let spec_t = self.instantiate_param_sig_t(
|
let spec_t = self.instantiate_param_sig_t(
|
||||||
sig,
|
&sig.raw,
|
||||||
opt_decl_t,
|
opt_decl_t,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
Normal,
|
Normal,
|
||||||
|
@ -422,6 +426,7 @@ impl Context {
|
||||||
None,
|
None,
|
||||||
self.absolutize(name.loc()),
|
self.absolutize(name.loc()),
|
||||||
);
|
);
|
||||||
|
sig.vi = vi.clone();
|
||||||
self.params.push((Some(name.clone()), vi));
|
self.params.push((Some(name.clone()), vi));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -435,7 +440,7 @@ impl Context {
|
||||||
|
|
||||||
pub(crate) fn assign_params(
|
pub(crate) fn assign_params(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: &hir::Params,
|
params: &mut hir::Params,
|
||||||
opt_decl_subr_t: Option<SubrType>,
|
opt_decl_subr_t: Option<SubrType>,
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
let mut errs = TyCheckErrors::empty();
|
let mut errs = TyCheckErrors::empty();
|
||||||
|
@ -445,16 +450,16 @@ impl Context {
|
||||||
decl_subr_t.non_default_params.len()
|
decl_subr_t.non_default_params.len()
|
||||||
);
|
);
|
||||||
debug_assert_eq!(params.defaults.len(), decl_subr_t.default_params.len());
|
debug_assert_eq!(params.defaults.len(), decl_subr_t.default_params.len());
|
||||||
for (sig, pt) in params
|
for (non_default, pt) in params
|
||||||
.non_defaults
|
.non_defaults
|
||||||
.iter()
|
.iter_mut()
|
||||||
.zip(decl_subr_t.non_default_params.iter())
|
.zip(decl_subr_t.non_default_params.iter())
|
||||||
{
|
{
|
||||||
if let Err(es) = self.assign_param(sig, Some(pt), ParamKind::NonDefault) {
|
if let Err(es) = self.assign_param(non_default, Some(pt), ParamKind::NonDefault) {
|
||||||
errs.extend(es);
|
errs.extend(es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(var_params) = ¶ms.var_params {
|
if let Some(var_params) = &mut params.var_params {
|
||||||
if let Some(pt) = &decl_subr_t.var_params {
|
if let Some(pt) = &decl_subr_t.var_params {
|
||||||
let pt = pt.clone().map_type(unknown_len_array_t);
|
let pt = pt.clone().map_type(unknown_len_array_t);
|
||||||
if let Err(es) = self.assign_param(var_params, Some(&pt), ParamKind::VarParams)
|
if let Err(es) = self.assign_param(var_params, Some(&pt), ParamKind::VarParams)
|
||||||
|
@ -465,27 +470,31 @@ impl Context {
|
||||||
errs.extend(es);
|
errs.extend(es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (sig, pt) in params
|
for (default, pt) in params
|
||||||
.defaults
|
.defaults
|
||||||
.iter()
|
.iter_mut()
|
||||||
.zip(decl_subr_t.default_params.iter())
|
.zip(decl_subr_t.default_params.iter())
|
||||||
{
|
{
|
||||||
if let Err(es) =
|
if let Err(es) = self.assign_param(
|
||||||
self.assign_param(&sig.sig, Some(pt), ParamKind::Default(sig.default_val.t()))
|
&mut default.sig,
|
||||||
{
|
Some(pt),
|
||||||
|
ParamKind::Default(default.default_val.t()),
|
||||||
|
) {
|
||||||
errs.extend(es);
|
errs.extend(es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for sig in params.non_defaults.iter() {
|
for non_default in params.non_defaults.iter_mut() {
|
||||||
if let Err(es) = self.assign_param(sig, None, ParamKind::NonDefault) {
|
if let Err(es) = self.assign_param(non_default, None, ParamKind::NonDefault) {
|
||||||
errs.extend(es);
|
errs.extend(es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for sig in params.defaults.iter() {
|
for default in params.defaults.iter_mut() {
|
||||||
if let Err(es) =
|
if let Err(es) = self.assign_param(
|
||||||
self.assign_param(&sig.sig, None, ParamKind::Default(sig.default_val.t()))
|
&mut default.sig,
|
||||||
{
|
None,
|
||||||
|
ParamKind::Default(default.default_val.t()),
|
||||||
|
) {
|
||||||
errs.extend(es);
|
errs.extend(es);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::ty::free::HasLevel;
|
||||||
use crate::ty::value::{GenTypeObj, TypeObj};
|
use crate::ty::value::{GenTypeObj, TypeObj};
|
||||||
use crate::ty::{HasType, Type};
|
use crate::ty::{HasType, Type};
|
||||||
|
|
||||||
|
use crate::compile::AccessKind;
|
||||||
use crate::context::RegistrationMode;
|
use crate::context::RegistrationMode;
|
||||||
use crate::error::{LowerError, LowerErrors, LowerResult};
|
use crate::error::{LowerError, LowerErrors, LowerResult};
|
||||||
use crate::hir;
|
use crate::hir;
|
||||||
|
@ -119,16 +120,28 @@ impl ASTLowerer {
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fake_lower_obj(&self, obj: ast::Expr) -> LowerResult<hir::Expr> {
|
fn fake_lower_acc(&self, acc: ast::Accessor) -> LowerResult<hir::Accessor> {
|
||||||
match obj {
|
match acc {
|
||||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
ast::Accessor::Ident(ident) => {
|
||||||
let acc = hir::Accessor::Ident(hir::Identifier::bare(ident.dot, ident.name));
|
// to resolve `py_name`
|
||||||
Ok(hir::Expr::Accessor(acc))
|
let vi = self
|
||||||
|
.module
|
||||||
|
.context
|
||||||
|
.rec_get_var_info(
|
||||||
|
&ident,
|
||||||
|
AccessKind::Name,
|
||||||
|
self.input(),
|
||||||
|
&self.module.context.name,
|
||||||
|
)
|
||||||
|
.unwrap_or(VarInfo::default());
|
||||||
|
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
|
||||||
|
let acc = hir::Accessor::Ident(ident);
|
||||||
|
Ok(acc)
|
||||||
}
|
}
|
||||||
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
|
ast::Accessor::Attr(attr) => {
|
||||||
let obj = self.fake_lower_obj(*attr.obj)?;
|
let obj = self.fake_lower_expr(*attr.obj)?;
|
||||||
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
|
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
|
||||||
Ok(obj.attr_expr(ident))
|
Ok(obj.attr(ident))
|
||||||
}
|
}
|
||||||
other => Err(LowerErrors::from(LowerError::declare_error(
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
self.cfg().input.clone(),
|
self.cfg().input.clone(),
|
||||||
|
@ -139,6 +152,270 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fake_lower_args(&self, args: ast::Args) -> LowerResult<hir::Args> {
|
||||||
|
let (pos_args_, var_args_, kw_args_, paren) = args.deconstruct();
|
||||||
|
let mut pos_args = vec![];
|
||||||
|
for arg in pos_args_.into_iter() {
|
||||||
|
let arg = self.fake_lower_expr(arg.expr)?;
|
||||||
|
pos_args.push(hir::PosArg::new(arg));
|
||||||
|
}
|
||||||
|
let var_args = match var_args_ {
|
||||||
|
Some(var_args) => {
|
||||||
|
let var_args = self.fake_lower_expr(var_args.expr)?;
|
||||||
|
Some(hir::PosArg::new(var_args))
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
let mut kw_args = vec![];
|
||||||
|
for kw_arg in kw_args_.into_iter() {
|
||||||
|
let expr = self.fake_lower_expr(kw_arg.expr)?;
|
||||||
|
kw_args.push(hir::KwArg::new(kw_arg.keyword, expr));
|
||||||
|
}
|
||||||
|
let args = hir::Args::new(pos_args, var_args, kw_args, paren);
|
||||||
|
Ok(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_call(&self, call: ast::Call) -> LowerResult<hir::Call> {
|
||||||
|
let obj = self.fake_lower_expr(*call.obj)?;
|
||||||
|
let attr_name = call
|
||||||
|
.attr_name
|
||||||
|
.map(|ident| hir::Identifier::bare(ident.dot, ident.name));
|
||||||
|
let args = self.fake_lower_args(call.args)?;
|
||||||
|
Ok(hir::Call::new(obj, attr_name, args))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_binop(&self, binop: ast::BinOp) -> LowerResult<hir::BinOp> {
|
||||||
|
let mut args = binop.args.into_iter();
|
||||||
|
let lhs = self.fake_lower_expr(*args.next().unwrap())?;
|
||||||
|
let rhs = self.fake_lower_expr(*args.next().unwrap())?;
|
||||||
|
Ok(hir::BinOp::new(binop.op, lhs, rhs, VarInfo::default()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_array(&self, arr: ast::Array) -> LowerResult<hir::Array> {
|
||||||
|
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,
|
||||||
|
Type::Failure,
|
||||||
|
len,
|
||||||
|
elem,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
ast::Array::Normal(arr) => {
|
||||||
|
let mut elems = Vec::new();
|
||||||
|
let (elems_, ..) = arr.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);
|
||||||
|
Ok(hir::Array::Normal(hir::NormalArray::new(
|
||||||
|
arr.l_sqbr,
|
||||||
|
arr.r_sqbr,
|
||||||
|
Type::Failure,
|
||||||
|
elems,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
|
self.cfg().input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
other.loc(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_tuple(&self, tup: ast::Tuple) -> LowerResult<hir::Tuple> {
|
||||||
|
match tup {
|
||||||
|
ast::Tuple::Normal(tup) => {
|
||||||
|
let mut elems = Vec::new();
|
||||||
|
let (elems_, _, _, paren) = tup.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![], paren);
|
||||||
|
Ok(hir::Tuple::Normal(hir::NormalTuple::new(elems)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_signature(&self, sig: ast::Signature) -> LowerResult<hir::Signature> {
|
||||||
|
match sig {
|
||||||
|
ast::Signature::Var(var) => {
|
||||||
|
let ident = var.ident().unwrap().clone();
|
||||||
|
let ident = hir::Identifier::bare(ident.dot, ident.name);
|
||||||
|
let sig = hir::VarSignature::new(ident, var.t_spec);
|
||||||
|
Ok(hir::Signature::Var(sig))
|
||||||
|
}
|
||||||
|
ast::Signature::Subr(subr) => {
|
||||||
|
let ident = hir::Identifier::bare(subr.ident.dot, subr.ident.name);
|
||||||
|
let params = self.fake_lower_params(subr.params)?;
|
||||||
|
let sig = hir::SubrSignature::new(ident, params, subr.return_t_spec);
|
||||||
|
Ok(hir::Signature::Subr(sig))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_def(&self, def: ast::Def) -> LowerResult<hir::Def> {
|
||||||
|
let sig = self.fake_lower_signature(def.sig)?;
|
||||||
|
let block = self.fake_lower_block(def.body.block)?;
|
||||||
|
let body = hir::DefBody::new(def.body.op, block, def.body.id);
|
||||||
|
Ok(hir::Def::new(sig, body))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_record(&self, rec: ast::Record) -> LowerResult<hir::Record> {
|
||||||
|
match rec {
|
||||||
|
ast::Record::Normal(rec) => {
|
||||||
|
let mut elems = Vec::new();
|
||||||
|
for elem in rec.attrs.into_iter() {
|
||||||
|
let elem = self.fake_lower_def(elem)?;
|
||||||
|
elems.push(elem);
|
||||||
|
}
|
||||||
|
let attrs = hir::RecordAttrs::new(elems);
|
||||||
|
Ok(hir::Record::new(rec.l_brace, rec.r_brace, attrs))
|
||||||
|
}
|
||||||
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
|
self.cfg().input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
other.loc(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_set(&self, set: ast::Set) -> LowerResult<hir::Set> {
|
||||||
|
match set {
|
||||||
|
ast::Set::Normal(set) => {
|
||||||
|
let mut elems = Vec::new();
|
||||||
|
let (elems_, ..) = set.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);
|
||||||
|
Ok(hir::Set::Normal(hir::NormalSet::new(
|
||||||
|
set.l_brace,
|
||||||
|
set.r_brace,
|
||||||
|
Type::Failure,
|
||||||
|
elems,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
|
self.cfg().input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
other.loc(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_dict(&self, dict: ast::Dict) -> LowerResult<hir::Dict> {
|
||||||
|
match dict {
|
||||||
|
ast::Dict::Normal(dict) => {
|
||||||
|
let mut kvs = Vec::new();
|
||||||
|
for elem in dict.kvs.into_iter() {
|
||||||
|
let key = self.fake_lower_expr(elem.key)?;
|
||||||
|
let val = self.fake_lower_expr(elem.value)?;
|
||||||
|
kvs.push(hir::KeyValue::new(key, val));
|
||||||
|
}
|
||||||
|
let tys = erg_common::dict::Dict::new();
|
||||||
|
Ok(hir::Dict::Normal(hir::NormalDict::new(
|
||||||
|
dict.l_brace,
|
||||||
|
dict.r_brace,
|
||||||
|
tys,
|
||||||
|
kvs,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
|
self.cfg().input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
other.loc(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_params(&self, params: ast::Params) -> LowerResult<hir::Params> {
|
||||||
|
let (non_defaults_, var_params_, defaults_, parens) = params.deconstruct();
|
||||||
|
let mut non_defaults = vec![];
|
||||||
|
for non_default_ in non_defaults_.into_iter() {
|
||||||
|
let non_default =
|
||||||
|
hir::NonDefaultParamSignature::new(non_default_, VarInfo::default(), None);
|
||||||
|
non_defaults.push(non_default);
|
||||||
|
}
|
||||||
|
let var_args = var_params_.map(|var_args| {
|
||||||
|
Box::new(hir::NonDefaultParamSignature::new(
|
||||||
|
*var_args,
|
||||||
|
VarInfo::default(),
|
||||||
|
None,
|
||||||
|
))
|
||||||
|
});
|
||||||
|
let mut defaults = vec![];
|
||||||
|
for default_ in defaults_.into_iter() {
|
||||||
|
let default_val = self.fake_lower_expr(default_.default_val)?;
|
||||||
|
let sig = hir::NonDefaultParamSignature::new(default_.sig, VarInfo::default(), None);
|
||||||
|
let default = hir::DefaultParamSignature::new(sig, default_val);
|
||||||
|
defaults.push(default);
|
||||||
|
}
|
||||||
|
Ok(hir::Params::new(non_defaults, var_args, defaults, parens))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_block(&self, block: ast::Block) -> LowerResult<hir::Block> {
|
||||||
|
let mut chunks = vec![];
|
||||||
|
for chunk in block.into_iter() {
|
||||||
|
let chunk = self.fake_lower_expr(chunk)?;
|
||||||
|
chunks.push(chunk);
|
||||||
|
}
|
||||||
|
Ok(hir::Block::new(chunks))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_lambda(&self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
||||||
|
let params = self.fake_lower_params(lambda.sig.params)?;
|
||||||
|
let body = self.fake_lower_block(lambda.body)?;
|
||||||
|
Ok(hir::Lambda::new(
|
||||||
|
lambda.id.0,
|
||||||
|
params,
|
||||||
|
lambda.op,
|
||||||
|
body,
|
||||||
|
Type::Failure,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fake_lower_dummy(&self, dummy: ast::Dummy) -> LowerResult<hir::Dummy> {
|
||||||
|
let mut dummy_ = vec![];
|
||||||
|
for elem in dummy.into_iter() {
|
||||||
|
let elem = self.fake_lower_expr(elem)?;
|
||||||
|
dummy_.push(elem);
|
||||||
|
}
|
||||||
|
Ok(hir::Dummy::new(dummy_))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn fake_lower_expr(&self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||||
|
match expr {
|
||||||
|
ast::Expr::Literal(lit) => Ok(hir::Expr::Lit(self.lower_literal(lit)?)),
|
||||||
|
ast::Expr::BinOp(binop) => Ok(hir::Expr::BinOp(self.fake_lower_binop(binop)?)),
|
||||||
|
ast::Expr::Array(arr) => Ok(hir::Expr::Array(self.fake_lower_array(arr)?)),
|
||||||
|
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)?)),
|
||||||
|
ast::Expr::Dict(dict) => Ok(hir::Expr::Dict(self.fake_lower_dict(dict)?)),
|
||||||
|
ast::Expr::Accessor(acc) => Ok(hir::Expr::Accessor(self.fake_lower_acc(acc)?)),
|
||||||
|
ast::Expr::Call(call) => Ok(hir::Expr::Call(self.fake_lower_call(call)?)),
|
||||||
|
ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.fake_lower_lambda(lambda)?)),
|
||||||
|
ast::Expr::Dummy(dummy) => Ok(hir::Expr::Dummy(self.fake_lower_dummy(dummy)?)),
|
||||||
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
|
self.cfg().input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
other.loc(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn declare_ident(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
fn declare_ident(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||||
log!(info "entered {}({})", fn_name!(), tasc);
|
log!(info "entered {}({})", fn_name!(), tasc);
|
||||||
let is_instance_ascription = tasc.is_instance_ascription();
|
let is_instance_ascription = tasc.is_instance_ascription();
|
||||||
|
@ -150,7 +427,7 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
|
let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
|
||||||
let t = self.module.context.instantiate_typespec(
|
let t = self.module.context.instantiate_typespec(
|
||||||
&tasc.t_spec,
|
&tasc.t_spec.t_spec,
|
||||||
None,
|
None,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
RegistrationMode::Normal,
|
RegistrationMode::Normal,
|
||||||
|
@ -177,7 +454,10 @@ impl ASTLowerer {
|
||||||
self.module.context.absolutize(ident.loc()),
|
self.module.context.absolutize(ident.loc()),
|
||||||
);
|
);
|
||||||
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
|
let ident = hir::Identifier::new(ident.dot, ident.name, None, vi);
|
||||||
Ok(hir::Expr::Accessor(hir::Accessor::Ident(ident)).type_asc(tasc.t_spec))
|
let t_spec_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr)?;
|
||||||
|
let t_spec =
|
||||||
|
hir::TypeSpecWithOp::new(tasc.t_spec.op, tasc.t_spec.t_spec, t_spec_expr);
|
||||||
|
Ok(hir::Expr::Accessor(hir::Accessor::Ident(ident)).type_asc(t_spec))
|
||||||
}
|
}
|
||||||
ast::Expr::Accessor(ast::Accessor::Attr(mut attr)) => {
|
ast::Expr::Accessor(ast::Accessor::Attr(mut attr)) => {
|
||||||
if cfg!(feature = "py_compatible") {
|
if cfg!(feature = "py_compatible") {
|
||||||
|
@ -185,7 +465,7 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
|
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
|
||||||
let t = self.module.context.instantiate_typespec(
|
let t = self.module.context.instantiate_typespec(
|
||||||
&tasc.t_spec,
|
&tasc.t_spec.t_spec,
|
||||||
None,
|
None,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
RegistrationMode::Normal,
|
RegistrationMode::Normal,
|
||||||
|
@ -202,7 +482,7 @@ impl ASTLowerer {
|
||||||
ast::DefId(0),
|
ast::DefId(0),
|
||||||
Some(py_name),
|
Some(py_name),
|
||||||
)?;
|
)?;
|
||||||
let obj = self.fake_lower_obj(*attr.obj)?;
|
let obj = self.fake_lower_expr(*attr.obj)?;
|
||||||
let muty = Mutability::from(&attr.ident.inspect()[..]);
|
let muty = Mutability::from(&attr.ident.inspect()[..]);
|
||||||
let vis = attr.ident.vis();
|
let vis = attr.ident.vis();
|
||||||
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
|
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
|
||||||
|
@ -218,7 +498,10 @@ impl ASTLowerer {
|
||||||
);
|
);
|
||||||
let ident = hir::Identifier::new(attr.ident.dot, attr.ident.name, None, vi);
|
let ident = hir::Identifier::new(attr.ident.dot, attr.ident.name, None, vi);
|
||||||
let attr = obj.attr_expr(ident);
|
let attr = obj.attr_expr(ident);
|
||||||
Ok(attr.type_asc(tasc.t_spec))
|
let t_spec_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr)?;
|
||||||
|
let t_spec =
|
||||||
|
hir::TypeSpecWithOp::new(tasc.t_spec.op, tasc.t_spec.t_spec, t_spec_expr);
|
||||||
|
Ok(attr.type_asc(t_spec))
|
||||||
}
|
}
|
||||||
other => Err(LowerErrors::from(LowerError::declare_error(
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
self.cfg().input.clone(),
|
self.cfg().input.clone(),
|
||||||
|
|
|
@ -250,7 +250,7 @@ impl SideEffectChecker {
|
||||||
self.errs.push(EffectError::proc_assign_error(
|
self.errs.push(EffectError::proc_assign_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
nd_param.pat.loc(),
|
nd_param.raw.pat.loc(),
|
||||||
self.full_path(),
|
self.full_path(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ impl SideEffectChecker {
|
||||||
self.errs.push(EffectError::proc_assign_error(
|
self.errs.push(EffectError::proc_assign_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
var_arg.pat.loc(),
|
var_arg.raw.pat.loc(),
|
||||||
self.full_path(),
|
self.full_path(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -270,7 +270,7 @@ impl SideEffectChecker {
|
||||||
self.errs.push(EffectError::proc_assign_error(
|
self.errs.push(EffectError::proc_assign_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
d_param.sig.pat.loc(),
|
d_param.sig.raw.pat.loc(),
|
||||||
self.full_path(),
|
self.full_path(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,8 @@ use erg_common::{
|
||||||
impl_nested_display_for_enum, impl_no_type_display_for_enum, impl_stream,
|
impl_nested_display_for_enum, impl_no_type_display_for_enum, impl_stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
use erg_parser::ast::{
|
use erg_parser::ast;
|
||||||
fmt_lines, DefId, DefKind, NonDefaultParamSignature, OperationKind, TypeSpec, VarName,
|
use erg_parser::ast::{fmt_lines, DefId, DefKind, OperationKind, TypeSpec, VarName};
|
||||||
};
|
|
||||||
use erg_parser::token::{Token, TokenKind, DOT};
|
use erg_parser::token::{Token, TokenKind, DOT};
|
||||||
|
|
||||||
use crate::ty::constructors::{array_t, dict_t, set_t, tuple_t};
|
use crate::ty::constructors::{array_t, dict_t, set_t, tuple_t};
|
||||||
|
@ -1593,6 +1592,50 @@ impl VarSignature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Once the default_value is set to Some, all subsequent values must be Some
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct NonDefaultParamSignature {
|
||||||
|
pub raw: ast::NonDefaultParamSignature,
|
||||||
|
pub vi: VarInfo,
|
||||||
|
pub t_spec_as_expr: Option<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for NonDefaultParamSignature {
|
||||||
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.raw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(NonDefaultParamSignature);
|
||||||
|
|
||||||
|
impl Locational for NonDefaultParamSignature {
|
||||||
|
fn loc(&self) -> Location {
|
||||||
|
self.raw.loc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NonDefaultParamSignature {
|
||||||
|
pub const fn new(
|
||||||
|
sig: ast::NonDefaultParamSignature,
|
||||||
|
vi: VarInfo,
|
||||||
|
t_spec_as_expr: Option<Expr>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
raw: sig,
|
||||||
|
vi,
|
||||||
|
t_spec_as_expr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
|
self.raw.pat.inspect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn name(&self) -> Option<&VarName> {
|
||||||
|
self.raw.pat.name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Once the default_value is set to Some, all subsequent values must be Some
|
/// Once the default_value is set to Some, all subsequent values must be Some
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct DefaultParamSignature {
|
pub struct DefaultParamSignature {
|
||||||
|
@ -1626,7 +1669,7 @@ impl DefaultParamSignature {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn inspect(&self) -> Option<&Str> {
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
self.sig.pat.inspect()
|
self.sig.inspect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn name(&self) -> Option<&VarName> {
|
pub const fn name(&self) -> Option<&VarName> {
|
||||||
|
@ -1930,6 +1973,13 @@ impl Signature {
|
||||||
Self::Subr(s) => s.return_t_spec.as_ref(),
|
Self::Subr(s) => s.return_t_spec.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn params_mut(&mut self) -> Option<&mut Params> {
|
||||||
|
match self {
|
||||||
|
Self::Var(_) => None,
|
||||||
|
Self::Subr(s) => Some(&mut s.params),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
@ -2259,21 +2309,47 @@ impl ReDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct TypeSpecWithOp {
|
||||||
|
pub op: Token,
|
||||||
|
pub t_spec: TypeSpec,
|
||||||
|
pub t_spec_as_expr: Box<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for TypeSpecWithOp {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
|
write!(f, "{} {}", self.op.content, self.t_spec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(TypeSpecWithOp);
|
||||||
|
impl_locational!(TypeSpecWithOp, lossy op, t_spec);
|
||||||
|
|
||||||
|
impl TypeSpecWithOp {
|
||||||
|
pub fn new(op: Token, t_spec: TypeSpec, t_spec_as_expr: Expr) -> Self {
|
||||||
|
Self {
|
||||||
|
op,
|
||||||
|
t_spec,
|
||||||
|
t_spec_as_expr: Box::new(t_spec_as_expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct TypeAscription {
|
pub struct TypeAscription {
|
||||||
pub expr: Box<Expr>,
|
pub expr: Box<Expr>,
|
||||||
pub spec: TypeSpec,
|
pub spec: TypeSpecWithOp,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for TypeAscription {
|
impl NestedDisplay for TypeAscription {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
writeln!(f, "{}: {}", self.expr, self.spec)
|
writeln!(f, "{}{}", self.expr, self.spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NoTypeDisplay for TypeAscription {
|
impl NoTypeDisplay for TypeAscription {
|
||||||
fn to_string_notype(&self) -> String {
|
fn to_string_notype(&self) -> String {
|
||||||
format!("{}: {}", self.expr.to_string_notype(), self.spec)
|
format!("{}{}", self.expr.to_string_notype(), self.spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2300,7 +2376,7 @@ impl HasType for TypeAscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeAscription {
|
impl TypeAscription {
|
||||||
pub fn new(expr: Expr, spec: TypeSpec) -> Self {
|
pub fn new(expr: Expr, spec: TypeSpecWithOp) -> Self {
|
||||||
Self {
|
Self {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
spec,
|
spec,
|
||||||
|
@ -2412,11 +2488,11 @@ impl Expr {
|
||||||
Self::Accessor(self.attr(ident))
|
Self::Accessor(self.attr(ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_asc(self, t_spec: TypeSpec) -> TypeAscription {
|
pub fn type_asc(self, t_spec: TypeSpecWithOp) -> TypeAscription {
|
||||||
TypeAscription::new(self, t_spec)
|
TypeAscription::new(self, t_spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_asc_expr(self, t_spec: TypeSpec) -> Self {
|
pub fn type_asc_expr(self, t_spec: TypeSpecWithOp) -> Self {
|
||||||
Self::TypeAsc(self.type_asc(t_spec))
|
Self::TypeAsc(self.type_asc(t_spec))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ class BoolMut(NatMut):
|
||||||
self.value = b
|
self.value = b
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.value.__repr__()
|
return self.value.__repr__()
|
||||||
|
def __hash__(self):
|
||||||
|
return self.value.__hash__()
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, bool):
|
if isinstance(other, bool):
|
||||||
return self.value == other
|
return self.value == other
|
||||||
|
|
|
@ -41,6 +41,8 @@ class FloatMut(): # inherits Float
|
||||||
self.value = Float(i)
|
self.value = Float(i)
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.value.__repr__()
|
return self.value.__repr__()
|
||||||
|
def __hash__(self):
|
||||||
|
return self.value.__hash__()
|
||||||
def __deref__(self):
|
def __deref__(self):
|
||||||
return self.value
|
return self.value
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
from _erg_result import is_ok
|
from _erg_result import is_ok
|
||||||
from _erg_range import Range
|
from _erg_range import Range
|
||||||
|
|
||||||
def in_operator(x, y):
|
def in_operator(elem, y):
|
||||||
if type(y) == type:
|
if type(y) == type:
|
||||||
if isinstance(x, y):
|
if isinstance(elem, y):
|
||||||
return True
|
return True
|
||||||
elif is_ok(y.try_new(x)):
|
elif is_ok(y.try_new(elem)):
|
||||||
return True
|
return True
|
||||||
# TODO: trait check
|
# TODO: trait check
|
||||||
return False
|
return False
|
||||||
elif (issubclass(type(y), list) or issubclass(type(y), set)) \
|
elif issubclass(type(y), list) \
|
||||||
and (type(y[0]) == type or issubclass(type(y[0]), Range)):
|
and (type(y[0]) == type or issubclass(type(y[0]), Range)):
|
||||||
# FIXME:
|
# FIXME:
|
||||||
type_check = in_operator(x[0], y[0])
|
type_check = in_operator(elem[0], y[0])
|
||||||
len_check = len(x) == len(y)
|
len_check = len(elem) == len(y)
|
||||||
return type_check and len_check
|
return type_check and len_check
|
||||||
elif issubclass(type(y), dict) and issubclass(type(next(iter(y.keys()))), type):
|
elif issubclass(type(y), dict) and issubclass(type(next(iter(y.keys()))), type):
|
||||||
# TODO:
|
# TODO:
|
||||||
type_check = True # in_operator(x[next(iter(x.keys()))], next(iter(y.keys())))
|
type_check = True # in_operator(x[next(iter(x.keys()))], next(iter(y.keys())))
|
||||||
len_check = len(x) >= len(y)
|
len_check = len(elem) >= len(y)
|
||||||
return type_check and len_check
|
return type_check and len_check
|
||||||
else:
|
else:
|
||||||
return x in y
|
return elem in y
|
||||||
|
|
|
@ -45,6 +45,8 @@ class IntMut(): # inherits Int
|
||||||
self.value = Int(i)
|
self.value = Int(i)
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.value.__repr__()
|
return self.value.__repr__()
|
||||||
|
def __hash__(self):
|
||||||
|
return self.value.__hash__()
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, Int):
|
if isinstance(other, Int):
|
||||||
return self.value == other
|
return self.value == other
|
||||||
|
|
|
@ -33,6 +33,8 @@ class NatMut(IntMut): # and Nat
|
||||||
self.value = n
|
self.value = n
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.value.__repr__()
|
return self.value.__repr__()
|
||||||
|
def __hash__(self):
|
||||||
|
return self.value.__hash__()
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, int):
|
if isinstance(other, int):
|
||||||
return self.value == other
|
return self.value == other
|
||||||
|
|
|
@ -37,6 +37,8 @@ class StrMut(): # Inherits Str
|
||||||
self.value = s
|
self.value = s
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return self.value.__repr__()
|
return self.value.__repr__()
|
||||||
|
def __hash__(self):
|
||||||
|
return self.value.__hash__()
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, Str):
|
if isinstance(other, Str):
|
||||||
return self.value == other
|
return self.value == other
|
||||||
|
|
|
@ -701,38 +701,8 @@ impl ASTLowerer {
|
||||||
Ok(hir::UnaryOp::new(unary.op, expr, t))
|
Ok(hir::UnaryOp::new(unary.op, expr, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
|
fn lower_args(&mut self, args: ast::Args, errs: &mut LowerErrors) -> hir::Args {
|
||||||
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.attr_name));
|
let (pos_args, var_args, kw_args, paren) = args.deconstruct();
|
||||||
if let Some(name) = call.obj.get_name() {
|
|
||||||
self.module.context.higher_order_caller.push(name.clone());
|
|
||||||
}
|
|
||||||
let mut errs = LowerErrors::empty();
|
|
||||||
let opt_cast_to = if call.is_assert_cast() {
|
|
||||||
if let Some(typ) = call.assert_cast_target_type() {
|
|
||||||
Some(Parser::expr_to_type_spec(typ.clone()).map_err(|e| {
|
|
||||||
self.module.context.higher_order_caller.pop();
|
|
||||||
let e = LowerError::new(
|
|
||||||
e.into(),
|
|
||||||
self.input().clone(),
|
|
||||||
self.module.context.caused_by(),
|
|
||||||
);
|
|
||||||
LowerErrors::from(e)
|
|
||||||
})?)
|
|
||||||
} else {
|
|
||||||
self.module.context.higher_order_caller.pop();
|
|
||||||
return Err(LowerErrors::from(LowerError::syntax_error(
|
|
||||||
self.input().clone(),
|
|
||||||
line!() as usize,
|
|
||||||
call.args.loc(),
|
|
||||||
self.module.context.caused_by(),
|
|
||||||
"invalid assert casting type".to_owned(),
|
|
||||||
None,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let (pos_args, var_args, kw_args, paren) = call.args.deconstruct();
|
|
||||||
let mut hir_args = hir::Args::new(
|
let mut hir_args = hir::Args::new(
|
||||||
Vec::with_capacity(pos_args.len()),
|
Vec::with_capacity(pos_args.len()),
|
||||||
None,
|
None,
|
||||||
|
@ -770,6 +740,41 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hir_args
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
|
||||||
|
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.attr_name));
|
||||||
|
if let Some(name) = call.obj.get_name() {
|
||||||
|
self.module.context.higher_order_caller.push(name.clone());
|
||||||
|
}
|
||||||
|
let mut errs = LowerErrors::empty();
|
||||||
|
let opt_cast_to = if call.is_assert_cast() {
|
||||||
|
if let Some(typ) = call.assert_cast_target_type() {
|
||||||
|
Some(Parser::expr_to_type_spec(typ.clone()).map_err(|e| {
|
||||||
|
self.module.context.higher_order_caller.pop();
|
||||||
|
let e = LowerError::new(
|
||||||
|
e.into(),
|
||||||
|
self.input().clone(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
);
|
||||||
|
LowerErrors::from(e)
|
||||||
|
})?)
|
||||||
|
} else {
|
||||||
|
self.module.context.higher_order_caller.pop();
|
||||||
|
return Err(LowerErrors::from(LowerError::syntax_error(
|
||||||
|
self.input().clone(),
|
||||||
|
line!() as usize,
|
||||||
|
call.args.loc(),
|
||||||
|
self.module.context.caused_by(),
|
||||||
|
"invalid assert casting type".to_owned(),
|
||||||
|
None,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let hir_args = self.lower_args(call.args, &mut errs);
|
||||||
let mut obj = match self.lower_expr(*call.obj) {
|
let mut obj = match self.lower_expr(*call.obj) {
|
||||||
Ok(obj) => obj,
|
Ok(obj) => obj,
|
||||||
Err(es) => {
|
Err(es) => {
|
||||||
|
@ -895,14 +900,59 @@ impl ASTLowerer {
|
||||||
Ok(hir::Call::new(class, Some(attr_name), args))
|
Ok(hir::Call::new(class, Some(attr_name), args))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_non_default_param(
|
||||||
|
&mut self,
|
||||||
|
non_default: ast::NonDefaultParamSignature,
|
||||||
|
) -> LowerResult<hir::NonDefaultParamSignature> {
|
||||||
|
let t_spec_as_expr = non_default
|
||||||
|
.t_spec
|
||||||
|
.as_ref()
|
||||||
|
.map(|t_spec_op| self.fake_lower_expr(*t_spec_op.t_spec_as_expr.clone()))
|
||||||
|
.transpose()?;
|
||||||
|
// TODO: define here (not assign_params)
|
||||||
|
let vi = VarInfo::default();
|
||||||
|
let sig = hir::NonDefaultParamSignature::new(non_default, vi, t_spec_as_expr);
|
||||||
|
Ok(sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lower_type_spec_with_op(
|
||||||
|
&mut self,
|
||||||
|
type_spec_with_op: ast::TypeSpecWithOp,
|
||||||
|
) -> LowerResult<hir::TypeSpecWithOp> {
|
||||||
|
let expr = self.fake_lower_expr(*type_spec_with_op.t_spec_as_expr)?;
|
||||||
|
Ok(hir::TypeSpecWithOp::new(
|
||||||
|
type_spec_with_op.op,
|
||||||
|
type_spec_with_op.t_spec,
|
||||||
|
expr,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_params(&mut self, params: ast::Params) -> LowerResult<hir::Params> {
|
fn lower_params(&mut self, params: ast::Params) -> LowerResult<hir::Params> {
|
||||||
log!(info "entered {}({})", fn_name!(), params);
|
log!(info "entered {}({})", fn_name!(), params);
|
||||||
let mut errs = LowerErrors::empty();
|
let mut errs = LowerErrors::empty();
|
||||||
|
let mut hir_non_defaults = vec![];
|
||||||
|
for non_default in params.non_defaults.into_iter() {
|
||||||
|
match self.lower_non_default_param(non_default) {
|
||||||
|
Ok(sig) => hir_non_defaults.push(sig),
|
||||||
|
Err(es) => errs.extend(es),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let hir_var_params = match params.var_params {
|
||||||
|
Some(var_params) => match self.lower_non_default_param(*var_params) {
|
||||||
|
Ok(sig) => Some(Box::new(sig)),
|
||||||
|
Err(es) => {
|
||||||
|
errs.extend(es);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
let mut hir_defaults = vec![];
|
let mut hir_defaults = vec![];
|
||||||
for default in params.defaults.into_iter() {
|
for default in params.defaults.into_iter() {
|
||||||
match self.lower_expr(default.default_val) {
|
match self.lower_expr(default.default_val) {
|
||||||
Ok(default_val) => {
|
Ok(default_val) => {
|
||||||
hir_defaults.push(hir::DefaultParamSignature::new(default.sig, default_val));
|
let sig = self.lower_non_default_param(default.sig)?;
|
||||||
|
hir_defaults.push(hir::DefaultParamSignature::new(sig, default_val));
|
||||||
}
|
}
|
||||||
Err(es) => errs.extend(es),
|
Err(es) => errs.extend(es),
|
||||||
}
|
}
|
||||||
|
@ -911,8 +961,8 @@ impl ASTLowerer {
|
||||||
Err(errs)
|
Err(errs)
|
||||||
} else {
|
} else {
|
||||||
let hir_params = hir::Params::new(
|
let hir_params = hir::Params::new(
|
||||||
params.non_defaults,
|
hir_non_defaults,
|
||||||
params.var_params,
|
hir_var_params,
|
||||||
hir_defaults,
|
hir_defaults,
|
||||||
params.parens,
|
params.parens,
|
||||||
);
|
);
|
||||||
|
@ -949,13 +999,13 @@ impl ASTLowerer {
|
||||||
.context
|
.context
|
||||||
.grow(&name, kind, Private, Some(tv_cache));
|
.grow(&name, kind, Private, Some(tv_cache));
|
||||||
}
|
}
|
||||||
let params = self.lower_params(lambda.sig.params).map_err(|errs| {
|
let mut params = self.lower_params(lambda.sig.params).map_err(|errs| {
|
||||||
if !in_statement {
|
if !in_statement {
|
||||||
self.pop_append_errs();
|
self.pop_append_errs();
|
||||||
}
|
}
|
||||||
errs
|
errs
|
||||||
})?;
|
})?;
|
||||||
if let Err(errs) = self.module.context.assign_params(¶ms, None) {
|
if let Err(errs) = self.module.context.assign_params(&mut params, None) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.module.context.preregister(&lambda.body) {
|
if let Err(errs) = self.module.context.preregister(&lambda.body) {
|
||||||
|
@ -1011,12 +1061,12 @@ impl ASTLowerer {
|
||||||
} else {
|
} else {
|
||||||
self.pop_append_errs();
|
self.pop_append_errs();
|
||||||
}
|
}
|
||||||
let t = if is_procedural {
|
let ty = if is_procedural {
|
||||||
proc(non_default_params, None, default_params, body.t())
|
proc(non_default_params, None, default_params, body.t())
|
||||||
} else {
|
} else {
|
||||||
func(non_default_params, None, default_params, body.t())
|
func(non_default_params, None, default_params, body.t())
|
||||||
};
|
};
|
||||||
let t = if t.has_qvar() { t.quantify() } else { t };
|
let t = if ty.has_qvar() { ty.quantify() } else { ty };
|
||||||
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1184,8 +1234,8 @@ impl ASTLowerer {
|
||||||
.unwrap_or(Type::Failure);
|
.unwrap_or(Type::Failure);
|
||||||
match registered_t {
|
match registered_t {
|
||||||
Type::Subr(subr_t) => {
|
Type::Subr(subr_t) => {
|
||||||
let params = self.lower_params(sig.params.clone())?;
|
let mut params = self.lower_params(sig.params.clone())?;
|
||||||
if let Err(errs) = self.module.context.assign_params(¶ms, Some(subr_t)) {
|
if let Err(errs) = self.module.context.assign_params(&mut params, Some(subr_t)) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.module.context.preregister(&body.block) {
|
if let Err(errs) = self.module.context.preregister(&body.block) {
|
||||||
|
@ -1241,8 +1291,8 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Failure => {
|
Type::Failure => {
|
||||||
let params = self.lower_params(sig.params)?;
|
let mut params = self.lower_params(sig.params)?;
|
||||||
if let Err(errs) = self.module.context.assign_params(¶ms, None) {
|
if let Err(errs) = self.module.context.assign_params(&mut params, None) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.module.context.preregister(&body.block) {
|
if let Err(errs) = self.module.context.preregister(&body.block) {
|
||||||
|
@ -1276,7 +1326,7 @@ impl ASTLowerer {
|
||||||
// TODO: check `tasc.op`
|
// TODO: check `tasc.op`
|
||||||
ast::Expr::TypeAscription(tasc) => (
|
ast::Expr::TypeAscription(tasc) => (
|
||||||
self.module.context.instantiate_typespec(
|
self.module.context.instantiate_typespec(
|
||||||
&tasc.t_spec,
|
&tasc.t_spec.t_spec,
|
||||||
None,
|
None,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
RegistrationMode::Normal,
|
RegistrationMode::Normal,
|
||||||
|
@ -1891,7 +1941,7 @@ impl ASTLowerer {
|
||||||
let is_instance_ascription = tasc.is_instance_ascription();
|
let is_instance_ascription = tasc.is_instance_ascription();
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.module.context.level, &self.module.context);
|
let mut dummy_tv_cache = TyVarCache::new(self.module.context.level, &self.module.context);
|
||||||
let spec_t = self.module.context.instantiate_typespec(
|
let spec_t = self.module.context.instantiate_typespec(
|
||||||
&tasc.t_spec,
|
&tasc.t_spec.t_spec,
|
||||||
None,
|
None,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
RegistrationMode::Normal,
|
RegistrationMode::Normal,
|
||||||
|
@ -1926,7 +1976,8 @@ impl ASTLowerer {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(expr.type_asc(tasc.t_spec))
|
let t_spec = self.lower_type_spec_with_op(tasc.t_spec)?;
|
||||||
|
Ok(expr.type_asc(t_spec))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_decl(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
fn lower_decl(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||||
|
@ -1934,7 +1985,7 @@ impl ASTLowerer {
|
||||||
let is_instance_ascription = tasc.is_instance_ascription();
|
let is_instance_ascription = tasc.is_instance_ascription();
|
||||||
let mut dummy_tv_cache = TyVarCache::new(self.module.context.level, &self.module.context);
|
let mut dummy_tv_cache = TyVarCache::new(self.module.context.level, &self.module.context);
|
||||||
let spec_t = self.module.context.instantiate_typespec(
|
let spec_t = self.module.context.instantiate_typespec(
|
||||||
&tasc.t_spec,
|
&tasc.t_spec.t_spec,
|
||||||
None,
|
None,
|
||||||
&mut dummy_tv_cache,
|
&mut dummy_tv_cache,
|
||||||
RegistrationMode::Normal,
|
RegistrationMode::Normal,
|
||||||
|
@ -2005,7 +2056,8 @@ impl ASTLowerer {
|
||||||
.map(|ctx| ctx.name.clone());
|
.map(|ctx| ctx.name.clone());
|
||||||
let ident = hir::Identifier::new(ident.dot, ident.name, qual_name, ident_vi);
|
let ident = hir::Identifier::new(ident.dot, ident.name, qual_name, ident_vi);
|
||||||
let expr = hir::Expr::Accessor(hir::Accessor::Ident(ident));
|
let expr = hir::Expr::Accessor(hir::Accessor::Ident(ident));
|
||||||
Ok(expr.type_asc(tasc.t_spec))
|
let t_spec = self.lower_type_spec_with_op(tasc.t_spec)?;
|
||||||
|
Ok(expr.type_asc(t_spec))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
|
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
|
||||||
|
|
|
@ -112,17 +112,17 @@ impl OwnershipChecker {
|
||||||
if let Signature::Subr(subr) = &def.sig {
|
if let Signature::Subr(subr) = &def.sig {
|
||||||
let (nd_params, var_params, d_params, _) = subr.params.ref_deconstruct();
|
let (nd_params, var_params, d_params, _) = subr.params.ref_deconstruct();
|
||||||
for param in nd_params {
|
for param in nd_params {
|
||||||
if let ParamPattern::VarName(name) = ¶m.pat {
|
if let ParamPattern::VarName(name) = ¶m.raw.pat {
|
||||||
self.define_param(name);
|
self.define_param(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(var) = var_params {
|
if let Some(var) = var_params {
|
||||||
if let ParamPattern::VarName(name) = &var.pat {
|
if let ParamPattern::VarName(name) = &var.raw.pat {
|
||||||
self.define_param(name);
|
self.define_param(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for param in d_params {
|
for param in d_params {
|
||||||
if let ParamPattern::VarName(name) = ¶m.sig.pat {
|
if let ParamPattern::VarName(name) = ¶m.sig.raw.pat {
|
||||||
self.define_param(name);
|
self.define_param(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -616,8 +616,8 @@ impl ScriptGenerator {
|
||||||
let mut code = "for ".to_string();
|
let mut code = "for ".to_string();
|
||||||
let iter = call.args.remove(0);
|
let iter = call.args.remove(0);
|
||||||
let Expr::Lambda(block) = call.args.remove(0) else { todo!() };
|
let Expr::Lambda(block) = call.args.remove(0) else { todo!() };
|
||||||
let sig = block.params.non_defaults.get(0).unwrap();
|
let non_default = block.params.non_defaults.get(0).unwrap();
|
||||||
let ParamPattern::VarName(param) = &sig.pat else { todo!() };
|
let ParamPattern::VarName(param) = &non_default.raw.pat else { todo!() };
|
||||||
code += &format!("{}__ ", ¶m.token().content);
|
code += &format!("{}__ ", ¶m.token().content);
|
||||||
code += &format!("in {}:\n", self.transpile_expr(iter));
|
code += &format!("in {}:\n", self.transpile_expr(iter));
|
||||||
code += &self.transpile_block(block.body, Discard);
|
code += &self.transpile_block(block.body, Discard);
|
||||||
|
@ -703,14 +703,14 @@ impl ScriptGenerator {
|
||||||
self.level += 1;
|
self.level += 1;
|
||||||
code += &" ".repeat(self.level);
|
code += &" ".repeat(self.level);
|
||||||
let target = arm.params.non_defaults.get(0).unwrap();
|
let target = arm.params.non_defaults.get(0).unwrap();
|
||||||
match &target.pat {
|
match &target.raw.pat {
|
||||||
ParamPattern::VarName(param) => {
|
ParamPattern::VarName(param) => {
|
||||||
code += &format!("case {}__:\n", ¶m.token().content);
|
code += &format!("case {}__:\n", ¶m.token().content);
|
||||||
code += &self.transpile_block(arm.body, StoreTmp(tmp.clone()));
|
code += &self.transpile_block(arm.body, StoreTmp(tmp.clone()));
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
}
|
}
|
||||||
ParamPattern::Discard(_) => {
|
ParamPattern::Discard(_) => {
|
||||||
match target.t_spec.as_ref().map(|t| &t.t_spec) {
|
match target.raw.t_spec.as_ref().map(|t| &t.t_spec) {
|
||||||
Some(TypeSpec::Enum(enum_t)) => {
|
Some(TypeSpec::Enum(enum_t)) => {
|
||||||
let values = ValueObj::vec_from_const_args(enum_t.clone());
|
let values = ValueObj::vec_from_const_args(enum_t.clone());
|
||||||
if values.len() == 1 {
|
if values.len() == 1 {
|
||||||
|
@ -799,7 +799,7 @@ impl ScriptGenerator {
|
||||||
fn transpile_params(&mut self, params: Params) -> String {
|
fn transpile_params(&mut self, params: Params) -> String {
|
||||||
let mut code = String::new();
|
let mut code = String::new();
|
||||||
for non_default in params.non_defaults {
|
for non_default in params.non_defaults {
|
||||||
match non_default.pat {
|
match non_default.raw.pat {
|
||||||
ParamPattern::VarName(param) => {
|
ParamPattern::VarName(param) => {
|
||||||
code += &format!("{}__,", param.into_token().content);
|
code += &format!("{}__,", param.into_token().content);
|
||||||
}
|
}
|
||||||
|
@ -811,7 +811,7 @@ impl ScriptGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for default in params.defaults {
|
for default in params.defaults {
|
||||||
let ParamPattern::VarName(param) = default.sig.pat else { todo!() };
|
let ParamPattern::VarName(param) = default.sig.raw.pat else { todo!() };
|
||||||
code += &format!(
|
code += &format!(
|
||||||
"{}__ = {},",
|
"{}__ = {},",
|
||||||
param.into_token().content,
|
param.into_token().content,
|
||||||
|
|
|
@ -218,4 +218,12 @@ impl VarInfo {
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parameter(t: Type, def_loc: AbsLocation) -> Self {
|
||||||
|
let kind = VarKind::Parameter {
|
||||||
|
def_id: DefId(0),
|
||||||
|
default: DefaultInfo::NonDefault,
|
||||||
|
};
|
||||||
|
Self::new(t, Immutable, Private, kind, None, None, None, def_loc)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1210,12 +1210,15 @@ impl Locational for Block {
|
||||||
impl_stream!(Block, Expr);
|
impl_stream!(Block, Expr);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Dummy(Vec<Expr>);
|
pub struct Dummy {
|
||||||
|
pub loc: Option<Location>,
|
||||||
|
exprs: Vec<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
impl NestedDisplay for Dummy {
|
impl NestedDisplay for Dummy {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
writeln!(f, "Dummy:")?;
|
writeln!(f, "Dummy:")?;
|
||||||
fmt_lines(self.0.iter(), f, level)
|
fmt_lines(self.exprs.iter(), f, level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1223,15 +1226,23 @@ impl_display_from_nested!(Dummy);
|
||||||
|
|
||||||
impl Locational for Dummy {
|
impl Locational for Dummy {
|
||||||
fn loc(&self) -> Location {
|
fn loc(&self) -> Location {
|
||||||
if self.0.is_empty() {
|
if self.loc.is_some() {
|
||||||
|
self.loc.unwrap_or(Location::Unknown)
|
||||||
|
} else if self.exprs.is_empty() {
|
||||||
Location::Unknown
|
Location::Unknown
|
||||||
} else {
|
} else {
|
||||||
Location::concat(self.0.first().unwrap(), self.0.last().unwrap())
|
Location::concat(self.exprs.first().unwrap(), self.exprs.last().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stream!(Dummy, Expr);
|
impl_stream!(Dummy, Expr, exprs);
|
||||||
|
|
||||||
|
impl Dummy {
|
||||||
|
pub const fn new(loc: Option<Location>, exprs: Vec<Expr>) -> Self {
|
||||||
|
Self { loc, exprs }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type ConstIdentifier = Identifier;
|
pub type ConstIdentifier = Identifier;
|
||||||
|
|
||||||
|
@ -2218,6 +2229,7 @@ impl TypeSpec {
|
||||||
pub struct TypeSpecWithOp {
|
pub struct TypeSpecWithOp {
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
pub t_spec: TypeSpec,
|
pub t_spec: TypeSpec,
|
||||||
|
pub t_spec_as_expr: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for TypeSpecWithOp {
|
impl NestedDisplay for TypeSpecWithOp {
|
||||||
|
@ -2230,8 +2242,12 @@ impl_display_from_nested!(TypeSpecWithOp);
|
||||||
impl_locational!(TypeSpecWithOp, lossy op, t_spec);
|
impl_locational!(TypeSpecWithOp, lossy op, t_spec);
|
||||||
|
|
||||||
impl TypeSpecWithOp {
|
impl TypeSpecWithOp {
|
||||||
pub const fn new(op: Token, t_spec: TypeSpec) -> Self {
|
pub fn new(op: Token, t_spec: TypeSpec, t_spec_as_expr: Expr) -> Self {
|
||||||
Self { op, t_spec }
|
Self {
|
||||||
|
op,
|
||||||
|
t_spec,
|
||||||
|
t_spec_as_expr: Box::new(t_spec_as_expr),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3447,13 +3463,12 @@ impl Signature {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct TypeAscription {
|
pub struct TypeAscription {
|
||||||
pub expr: Box<Expr>,
|
pub expr: Box<Expr>,
|
||||||
pub op: Token,
|
pub t_spec: TypeSpecWithOp,
|
||||||
pub t_spec: TypeSpec,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for TypeAscription {
|
impl NestedDisplay for TypeAscription {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
writeln!(f, "{}{} {}", self.expr, self.op.content, self.t_spec)
|
writeln!(f, "{}{}", self.expr, self.t_spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3461,20 +3476,19 @@ impl_display_from_nested!(TypeAscription);
|
||||||
impl_locational!(TypeAscription, expr, t_spec);
|
impl_locational!(TypeAscription, expr, t_spec);
|
||||||
|
|
||||||
impl TypeAscription {
|
impl TypeAscription {
|
||||||
pub fn new(expr: Expr, op: Token, t_spec: TypeSpec) -> Self {
|
pub fn new(expr: Expr, t_spec: TypeSpecWithOp) -> Self {
|
||||||
Self {
|
Self {
|
||||||
expr: Box::new(expr),
|
expr: Box::new(expr),
|
||||||
op,
|
|
||||||
t_spec,
|
t_spec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_instance_ascription(&self) -> bool {
|
pub fn is_instance_ascription(&self) -> bool {
|
||||||
self.op.is(TokenKind::Colon)
|
self.t_spec.op.is(TokenKind::Colon)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_subtype_ascription(&self) -> bool {
|
pub fn is_subtype_ascription(&self) -> bool {
|
||||||
self.op.is(TokenKind::SubtypeOf)
|
self.t_spec.op.is(TokenKind::SubtypeOf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3826,12 +3840,16 @@ impl Expr {
|
||||||
Self::Call(self.call(args))
|
Self::Call(self.call(args))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_asc(self, op: Token, t_spec: TypeSpec) -> TypeAscription {
|
pub fn type_asc(self, t_spec: TypeSpecWithOp) -> TypeAscription {
|
||||||
TypeAscription::new(self, op, t_spec)
|
TypeAscription::new(self, t_spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_asc_expr(self, op: Token, t_spec: TypeSpec) -> Self {
|
pub fn type_asc_expr(self, t_spec: TypeSpecWithOp) -> Self {
|
||||||
Self::TypeAscription(self.type_asc(op, t_spec))
|
Self::TypeAscription(self.type_asc(t_spec))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dummy(loc: Location) -> Self {
|
||||||
|
Self::Dummy(Dummy::new(Some(loc), vec![]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ impl Parser {
|
||||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||||
let sig = match sig {
|
let sig = match sig {
|
||||||
Signature::Var(var) => {
|
Signature::Var(var) => {
|
||||||
let var = VarSignature::new(var.pat, Some(tasc.t_spec));
|
let var = VarSignature::new(var.pat, Some(tasc.t_spec.t_spec));
|
||||||
Signature::Var(var)
|
Signature::Var(var)
|
||||||
}
|
}
|
||||||
Signature::Subr(subr) => {
|
Signature::Subr(subr) => {
|
||||||
|
@ -245,7 +245,7 @@ impl Parser {
|
||||||
subr.ident,
|
subr.ident,
|
||||||
subr.bounds,
|
subr.bounds,
|
||||||
subr.params,
|
subr.params,
|
||||||
Some(tasc.t_spec),
|
Some(tasc.t_spec.t_spec),
|
||||||
);
|
);
|
||||||
Signature::Subr(subr)
|
Signature::Subr(subr)
|
||||||
}
|
}
|
||||||
|
@ -334,8 +334,7 @@ impl Parser {
|
||||||
.unwrap_or_else(|| todo!())
|
.unwrap_or_else(|| todo!())
|
||||||
.pat;
|
.pat;
|
||||||
let lhs = option_enum_unwrap!(lhs, VarPattern::Ident).unwrap_or_else(|| todo!());
|
let lhs = option_enum_unwrap!(lhs, VarPattern::Ident).unwrap_or_else(|| todo!());
|
||||||
let spec_with_op = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
let bound = TypeBoundSpec::non_default(lhs.name.into_token(), tasc.t_spec);
|
||||||
let bound = TypeBoundSpec::non_default(lhs.name.into_token(), spec_with_op);
|
|
||||||
Ok(bound)
|
Ok(bound)
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
|
@ -598,8 +597,7 @@ impl Parser {
|
||||||
let param = self
|
let param = self
|
||||||
.convert_rhs_to_param(*tasc.expr, allow_self)
|
.convert_rhs_to_param(*tasc.expr, allow_self)
|
||||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||||
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
let param = NonDefaultParamSignature::new(param.pat, Some(tasc.t_spec));
|
||||||
let param = NonDefaultParamSignature::new(param.pat, Some(t_spec));
|
|
||||||
debug_exit_info!(self);
|
debug_exit_info!(self);
|
||||||
Ok(param)
|
Ok(param)
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,10 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
Expr::TypeAscription(tasc) => {
|
Expr::TypeAscription(tasc) => {
|
||||||
let expr = desugar(*tasc.expr);
|
let expr = desugar(*tasc.expr);
|
||||||
expr.type_asc_expr(tasc.op, tasc.t_spec)
|
let t_spec_as_expr = desugar(*tasc.t_spec.t_spec_as_expr);
|
||||||
|
let t_spec =
|
||||||
|
TypeSpecWithOp::new(tasc.t_spec.op, tasc.t_spec.t_spec, t_spec_as_expr);
|
||||||
|
expr.type_asc_expr(t_spec)
|
||||||
}
|
}
|
||||||
Expr::Methods(method_defs) => {
|
Expr::Methods(method_defs) => {
|
||||||
let mut new_attrs = vec![];
|
let mut new_attrs = vec![];
|
||||||
|
@ -286,7 +289,13 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
ClassAttr::Decl(decl) => {
|
ClassAttr::Decl(decl) => {
|
||||||
let expr = desugar(*decl.expr);
|
let expr = desugar(*decl.expr);
|
||||||
new_attrs.push(ClassAttr::Decl(expr.type_asc(decl.op, decl.t_spec)));
|
let t_spec_as_expr = desugar(*decl.t_spec.t_spec_as_expr);
|
||||||
|
let t_spec = TypeSpecWithOp::new(
|
||||||
|
decl.t_spec.op,
|
||||||
|
decl.t_spec.t_spec,
|
||||||
|
t_spec_as_expr,
|
||||||
|
);
|
||||||
|
new_attrs.push(ClassAttr::Decl(expr.type_asc(t_spec)));
|
||||||
}
|
}
|
||||||
ClassAttr::Doc(doc) => {
|
ClassAttr::Doc(doc) => {
|
||||||
new_attrs.push(ClassAttr::Doc(doc));
|
new_attrs.push(ClassAttr::Doc(doc));
|
||||||
|
@ -298,11 +307,12 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
Expr::Accessor(acc) => Expr::Accessor(Self::perform_desugar_acc(desugar, acc)),
|
Expr::Accessor(acc) => Expr::Accessor(Self::perform_desugar_acc(desugar, acc)),
|
||||||
Expr::Dummy(exprs) => {
|
Expr::Dummy(exprs) => {
|
||||||
|
let loc = exprs.loc;
|
||||||
let mut chunks = vec![];
|
let mut chunks = vec![];
|
||||||
for chunk in exprs.into_iter() {
|
for chunk in exprs.into_iter() {
|
||||||
chunks.push(desugar(chunk));
|
chunks.push(desugar(chunk));
|
||||||
}
|
}
|
||||||
Expr::Dummy(Dummy::new(chunks))
|
Expr::Dummy(Dummy::new(loc, chunks))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -773,7 +783,22 @@ impl Desugarer {
|
||||||
l.ln_begin().unwrap(),
|
l.ln_begin().unwrap(),
|
||||||
l.col_begin().unwrap(),
|
l.col_begin().unwrap(),
|
||||||
));
|
));
|
||||||
param.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::enum_t_spec(vec![lit])));
|
let l_brace = Token {
|
||||||
|
content: "{".into(),
|
||||||
|
kind: TokenKind::LBrace,
|
||||||
|
..lit.token
|
||||||
|
};
|
||||||
|
let r_brace = Token {
|
||||||
|
content: "}".into(),
|
||||||
|
kind: TokenKind::RBrace,
|
||||||
|
..lit.token
|
||||||
|
};
|
||||||
|
let t_spec = TypeSpec::enum_t_spec(vec![lit.clone()]);
|
||||||
|
let args = Args::pos_only(vec![PosArg::new(Expr::Literal(lit))], None);
|
||||||
|
let set = astSet::Normal(NormalSet::new(l_brace, r_brace, args));
|
||||||
|
let t_spec_as_expr = Expr::Set(set);
|
||||||
|
let t_spec = TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr);
|
||||||
|
param.t_spec = Some(t_spec);
|
||||||
}
|
}
|
||||||
ParamPattern::Tuple(tup) => {
|
ParamPattern::Tuple(tup) => {
|
||||||
let (buf_name, buf_param) = self.gen_buf_nd_param(line);
|
let (buf_name, buf_param) = self.gen_buf_nd_param(line);
|
||||||
|
@ -797,7 +822,8 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
if param.t_spec.is_none() {
|
if param.t_spec.is_none() {
|
||||||
let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys));
|
let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys));
|
||||||
param.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec));
|
let t_spec_as_expr = Expr::dummy(t_spec.loc());
|
||||||
|
param.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
}
|
}
|
||||||
param.pat = buf_param;
|
param.pat = buf_param;
|
||||||
}
|
}
|
||||||
|
@ -817,9 +843,11 @@ impl Desugarer {
|
||||||
let len = Literal::new(Token::new(TokenKind::NatLit, len.to_string(), line, 0));
|
let len = Literal::new(Token::new(TokenKind::NatLit, len.to_string(), line, 0));
|
||||||
let infer = Token::new(TokenKind::Try, "?", line, 0);
|
let infer = Token::new(TokenKind::Try, "?", line, 0);
|
||||||
let t_spec = ArrayTypeSpec::new(TypeSpec::Infer(infer), ConstExpr::Lit(len));
|
let t_spec = ArrayTypeSpec::new(TypeSpec::Infer(infer), ConstExpr::Lit(len));
|
||||||
|
let t_spec_as_expr = Expr::dummy(t_spec.loc());
|
||||||
param.t_spec = Some(TypeSpecWithOp::new(
|
param.t_spec = Some(TypeSpecWithOp::new(
|
||||||
Token::dummy(TokenKind::Colon, ":"),
|
Token::dummy(TokenKind::Colon, ":"),
|
||||||
TypeSpec::Array(t_spec),
|
TypeSpec::Array(t_spec),
|
||||||
|
t_spec_as_expr,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
param.pat = buf_param;
|
param.pat = buf_param;
|
||||||
|
@ -848,7 +876,9 @@ impl Desugarer {
|
||||||
.clone(),
|
.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
param.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Record(tys)));
|
let t_spec = TypeSpec::Record(tys);
|
||||||
|
let t_spec_as_expr = Expr::dummy(t_spec.loc());
|
||||||
|
param.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
}
|
}
|
||||||
param.pat = buf_param;
|
param.pat = buf_param;
|
||||||
}
|
}
|
||||||
|
@ -937,7 +967,8 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
if sig.t_spec.is_none() {
|
if sig.t_spec.is_none() {
|
||||||
let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys));
|
let t_spec = TypeSpec::Tuple(TupleTypeSpec::new(tup.elems.parens.clone(), tys));
|
||||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec));
|
let t_spec_as_expr = Expr::dummy(t_spec.loc());
|
||||||
|
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
}
|
}
|
||||||
sig.pat = buf_sig;
|
sig.pat = buf_sig;
|
||||||
insertion_idx
|
insertion_idx
|
||||||
|
@ -968,8 +999,31 @@ impl Desugarer {
|
||||||
let len = arr.elems.non_defaults.len();
|
let len = arr.elems.non_defaults.len();
|
||||||
let len = Literal::new(Token::new(TokenKind::NatLit, len.to_string(), line, 0));
|
let len = Literal::new(Token::new(TokenKind::NatLit, len.to_string(), line, 0));
|
||||||
let infer = Token::new(TokenKind::Try, "?", line, 0);
|
let infer = Token::new(TokenKind::Try, "?", line, 0);
|
||||||
let t_spec = ArrayTypeSpec::new(TypeSpec::Infer(infer), ConstExpr::Lit(len));
|
let t_spec =
|
||||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Array(t_spec)));
|
ArrayTypeSpec::new(TypeSpec::Infer(infer), ConstExpr::Lit(len.clone()));
|
||||||
|
let l_sqbr = Token {
|
||||||
|
content: "[".into(),
|
||||||
|
kind: TokenKind::LSqBr,
|
||||||
|
..len.token
|
||||||
|
};
|
||||||
|
let r_sqbr = Token {
|
||||||
|
content: "]".into(),
|
||||||
|
kind: TokenKind::RSqBr,
|
||||||
|
..len.token
|
||||||
|
};
|
||||||
|
let elem = Expr::local("Obj", l_sqbr.lineno, l_sqbr.col_begin);
|
||||||
|
let array = Array::WithLength(ArrayWithLength::new(
|
||||||
|
l_sqbr,
|
||||||
|
r_sqbr,
|
||||||
|
PosArg::new(elem),
|
||||||
|
Expr::Literal(len),
|
||||||
|
));
|
||||||
|
let t_spec_as_expr = Expr::Array(array);
|
||||||
|
sig.t_spec = Some(TypeSpecWithOp::new(
|
||||||
|
COLON,
|
||||||
|
TypeSpec::Array(t_spec),
|
||||||
|
t_spec_as_expr,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
sig.pat = buf_sig;
|
sig.pat = buf_sig;
|
||||||
insertion_idx
|
insertion_idx
|
||||||
|
@ -1007,7 +1061,9 @@ impl Desugarer {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if sig.t_spec.is_none() {
|
if sig.t_spec.is_none() {
|
||||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Record(tys)));
|
let t_spec = TypeSpec::Record(tys);
|
||||||
|
let t_spec_as_expr = Expr::dummy(t_spec.loc());
|
||||||
|
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
}
|
}
|
||||||
sig.pat = buf_sig;
|
sig.pat = buf_sig;
|
||||||
insertion_idx
|
insertion_idx
|
||||||
|
@ -1047,7 +1103,21 @@ impl Desugarer {
|
||||||
l.ln_begin().unwrap(),
|
l.ln_begin().unwrap(),
|
||||||
l.col_begin().unwrap(),
|
l.col_begin().unwrap(),
|
||||||
));
|
));
|
||||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::enum_t_spec(vec![lit])));
|
let l_brace = Token {
|
||||||
|
content: "{".into(),
|
||||||
|
kind: TokenKind::LBrace,
|
||||||
|
..lit.token
|
||||||
|
};
|
||||||
|
let r_brace = Token {
|
||||||
|
content: "}".into(),
|
||||||
|
kind: TokenKind::RBrace,
|
||||||
|
..lit.token
|
||||||
|
};
|
||||||
|
let t_spec = TypeSpec::enum_t_spec(vec![lit.clone()]);
|
||||||
|
let args = Args::pos_only(vec![PosArg::new(Expr::Literal(lit))], None);
|
||||||
|
let set = astSet::Normal(NormalSet::new(l_brace, r_brace, args));
|
||||||
|
let t_spec_as_expr = Expr::Set(set);
|
||||||
|
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
insertion_idx
|
insertion_idx
|
||||||
}
|
}
|
||||||
_ => insertion_idx,
|
_ => insertion_idx,
|
||||||
|
|
|
@ -716,10 +716,10 @@ impl Parser {
|
||||||
Args::new(vec![], Some(pos_args), vec![], None)
|
Args::new(vec![], Some(pos_args), vec![], None)
|
||||||
}
|
}
|
||||||
PosOrKwArg::Pos(PosArg {
|
PosOrKwArg::Pos(PosArg {
|
||||||
expr: Expr::TypeAscription(TypeAscription { expr, op, t_spec }),
|
expr: Expr::TypeAscription(TypeAscription { expr, t_spec }),
|
||||||
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
|
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
|
||||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||||
let var_args = PosArg::new(unary.deconstruct().1.type_asc_expr(op, t_spec));
|
let var_args = PosArg::new(unary.deconstruct().1.type_asc_expr(t_spec));
|
||||||
Args::new(vec![], Some(var_args), vec![], None)
|
Args::new(vec![], Some(var_args), vec![], None)
|
||||||
}
|
}
|
||||||
PosOrKwArg::Pos(arg) => Args::pos_only(vec![arg], None),
|
PosOrKwArg::Pos(arg) => Args::pos_only(vec![arg], None),
|
||||||
|
@ -786,12 +786,12 @@ impl Parser {
|
||||||
args.set_var_args(PosArg::new(unary.deconstruct().1));
|
args.set_var_args(PosArg::new(unary.deconstruct().1));
|
||||||
}
|
}
|
||||||
PosOrKwArg::Pos(PosArg {
|
PosOrKwArg::Pos(PosArg {
|
||||||
expr: Expr::TypeAscription(TypeAscription { expr, op, t_spec }),
|
expr: Expr::TypeAscription(TypeAscription { expr, t_spec }),
|
||||||
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) =>
|
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) =>
|
||||||
{
|
{
|
||||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||||
args.set_var_args(PosArg::new(
|
args.set_var_args(PosArg::new(
|
||||||
unary.deconstruct().1.type_asc_expr(op, t_spec),
|
unary.deconstruct().1.type_asc_expr(t_spec),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
PosOrKwArg::Pos(arg) => {
|
PosOrKwArg::Pos(arg) => {
|
||||||
|
@ -908,8 +908,7 @@ impl Parser {
|
||||||
Expr::Accessor(Accessor::Ident(n)) => (n.name.into_token(), None),
|
Expr::Accessor(Accessor::Ident(n)) => (n.name.into_token(), None),
|
||||||
Expr::TypeAscription(tasc) => {
|
Expr::TypeAscription(tasc) => {
|
||||||
if let Expr::Accessor(Accessor::Ident(n)) = *tasc.expr {
|
if let Expr::Accessor(Accessor::Ident(n)) = *tasc.expr {
|
||||||
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
(n.name.into_token(), Some(tasc.t_spec))
|
||||||
(n.name.into_token(), Some(t_spec))
|
|
||||||
} else {
|
} else {
|
||||||
let err = ParseError::simple_syntax_error(0, tasc.loc());
|
let err = ParseError::simple_syntax_error(0, tasc.loc());
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
|
@ -1165,11 +1164,13 @@ impl Parser {
|
||||||
}
|
}
|
||||||
let op = self.lpop();
|
let op = self.lpop();
|
||||||
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
let t_spec = self
|
let t_spec_as_expr = self
|
||||||
.try_reduce_expr(false, false, false, false)
|
.try_reduce_expr(false, false, false, false)
|
||||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||||
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
let t_spec = Self::expr_to_type_spec(t_spec_as_expr.clone())
|
||||||
let expr = lhs.type_asc_expr(op, t_spec);
|
.map_err(|e| self.errs.push(e))?;
|
||||||
|
let t_spec_op = TypeSpecWithOp::new(op, t_spec, t_spec_as_expr);
|
||||||
|
let expr = lhs.type_asc_expr(t_spec_op);
|
||||||
stack.push(ExprOrOp::Expr(expr));
|
stack.push(ExprOrOp::Expr(expr));
|
||||||
}
|
}
|
||||||
Some(op) if op.category_is(TC::BinOp) => {
|
Some(op) if op.category_is(TC::BinOp) => {
|
||||||
|
@ -1434,11 +1435,13 @@ impl Parser {
|
||||||
}
|
}
|
||||||
let op = self.lpop();
|
let op = self.lpop();
|
||||||
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
let lhs = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||||
let t_spec = self
|
let t_spec_as_expr = self
|
||||||
.try_reduce_expr(false, in_type_args, in_brace, false)
|
.try_reduce_expr(false, in_type_args, in_brace, false)
|
||||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||||
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
let t_spec = Self::expr_to_type_spec(t_spec_as_expr.clone())
|
||||||
let expr = lhs.type_asc_expr(op, t_spec);
|
.map_err(|e| self.errs.push(e))?;
|
||||||
|
let t_spec_op = TypeSpecWithOp::new(op, t_spec, t_spec_as_expr);
|
||||||
|
let expr = lhs.type_asc_expr(t_spec_op);
|
||||||
stack.push(ExprOrOp::Expr(expr));
|
stack.push(ExprOrOp::Expr(expr));
|
||||||
}
|
}
|
||||||
Some(op) if op.category_is(TC::BinOp) => {
|
Some(op) if op.category_is(TC::BinOp) => {
|
||||||
|
@ -1596,10 +1599,7 @@ impl Parser {
|
||||||
Expr::Accessor(Accessor::Ident(ident)) => (ident.name.into_token(), None),
|
Expr::Accessor(Accessor::Ident(ident)) => (ident.name.into_token(), None),
|
||||||
Expr::TypeAscription(tasc) => {
|
Expr::TypeAscription(tasc) => {
|
||||||
if let Expr::Accessor(Accessor::Ident(ident)) = *tasc.expr {
|
if let Expr::Accessor(Accessor::Ident(ident)) = *tasc.expr {
|
||||||
(
|
(ident.name.into_token(), Some(tasc.t_spec))
|
||||||
ident.name.into_token(),
|
|
||||||
Some(TypeSpecWithOp::new(tasc.op, tasc.t_spec)),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, tasc.loc());
|
let err = ParseError::simple_syntax_error(line!() as usize, tasc.loc());
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
|
@ -2367,11 +2367,11 @@ impl Parser {
|
||||||
Args::new(vec![], var_args, vec![], None)
|
Args::new(vec![], var_args, vec![], None)
|
||||||
}
|
}
|
||||||
PosOrKwArg::Pos(PosArg {
|
PosOrKwArg::Pos(PosArg {
|
||||||
expr: Expr::TypeAscription(TypeAscription { expr, op, t_spec }),
|
expr: Expr::TypeAscription(TypeAscription { expr, t_spec }),
|
||||||
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
|
}) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) => {
|
||||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||||
let expr = unary.deconstruct().1;
|
let expr = unary.deconstruct().1;
|
||||||
let var_args = Some(PosArg::new(expr.type_asc_expr(op, t_spec)));
|
let var_args = Some(PosArg::new(expr.type_asc_expr(t_spec)));
|
||||||
Args::new(vec![], var_args, vec![], None)
|
Args::new(vec![], var_args, vec![], None)
|
||||||
}
|
}
|
||||||
PosOrKwArg::Pos(pos) => Args::pos_only(vec![pos], None),
|
PosOrKwArg::Pos(pos) => Args::pos_only(vec![pos], None),
|
||||||
|
@ -2402,11 +2402,11 @@ impl Parser {
|
||||||
Expr::UnaryOp(unary) if unary.op.is(PreStar) => {
|
Expr::UnaryOp(unary) if unary.op.is(PreStar) => {
|
||||||
args.set_var_args(PosArg::new(unary.deconstruct().1));
|
args.set_var_args(PosArg::new(unary.deconstruct().1));
|
||||||
}
|
}
|
||||||
Expr::TypeAscription(TypeAscription { expr, op, t_spec }) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) =>
|
Expr::TypeAscription(TypeAscription { expr, t_spec }) if matches!(expr.as_ref(), Expr::UnaryOp(unary) if unary.op.is(PreStar)) =>
|
||||||
{
|
{
|
||||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||||
let expr = unary.deconstruct().1;
|
let expr = unary.deconstruct().1;
|
||||||
args.set_var_args(PosArg::new(expr.type_asc_expr(op, t_spec)));
|
args.set_var_args(PosArg::new(expr.type_asc_expr(t_spec)));
|
||||||
}
|
}
|
||||||
Expr::Tuple(Tuple::Normal(tup)) if tup.elems.paren.is_none() => {
|
Expr::Tuple(Tuple::Normal(tup)) if tup.elems.paren.is_none() => {
|
||||||
args.extend_pos(tup.elems.into_iters().0);
|
args.extend_pos(tup.elems.into_iters().0);
|
||||||
|
|
|
@ -3,7 +3,7 @@ use erg_common::traits::{Locational, Stream};
|
||||||
|
|
||||||
use crate::ast::*;
|
use crate::ast::*;
|
||||||
use crate::error::ParseError;
|
use crate::error::ParseError;
|
||||||
use crate::token::{Token, TokenKind};
|
use crate::token::TokenKind;
|
||||||
use crate::Parser;
|
use crate::Parser;
|
||||||
|
|
||||||
// The APIs defined below are also used by `ASTLowerer` to interpret expressions as types.
|
// The APIs defined below are also used by `ASTLowerer` to interpret expressions as types.
|
||||||
|
@ -412,77 +412,4 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_type_spec_to_ident(simple: SimpleTypeSpec) -> Result<Identifier, ParseError> {
|
|
||||||
Ok(simple.ident)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn simple_type_spec_to_call(simple: SimpleTypeSpec) -> Result<Call, ParseError> {
|
|
||||||
let (pos_args_, var_args_, kw_args_, paren) = simple.args.deconstruct();
|
|
||||||
let pos_args = pos_args_
|
|
||||||
.into_iter()
|
|
||||||
.map(|arg| PosArg::new(arg.expr.downcast()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let var_args = var_args_.map(|arg| PosArg::new(arg.expr.downcast()));
|
|
||||||
let kw_args = kw_args_
|
|
||||||
.into_iter()
|
|
||||||
.map(|arg| KwArg::new(arg.keyword, None, arg.expr.downcast()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let args = Args::new(pos_args, var_args, kw_args, paren);
|
|
||||||
let call = Call::new(simple.ident.into(), None, args);
|
|
||||||
Ok(call)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn predecl_type_spec_to_expr(predecl: PreDeclTypeSpec) -> Result<Expr, ParseError> {
|
|
||||||
match predecl {
|
|
||||||
PreDeclTypeSpec::Simple(simple) if simple.args.is_empty() => {
|
|
||||||
Ok(Self::simple_type_spec_to_ident(simple)?.into())
|
|
||||||
}
|
|
||||||
PreDeclTypeSpec::Simple(simple) => Ok(Self::simple_type_spec_to_call(simple)?.into()),
|
|
||||||
PreDeclTypeSpec::Attr { namespace, t } => {
|
|
||||||
let ident = Self::simple_type_spec_to_ident(t)?;
|
|
||||||
Ok(namespace.attr_expr(ident))
|
|
||||||
}
|
|
||||||
other => Err(ParseError::feature_error(
|
|
||||||
line!() as usize,
|
|
||||||
other.loc(),
|
|
||||||
"compound predecl type spec to call conversion",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_spec_to_expr(t_spec: TypeSpec) -> Result<Expr, ParseError> {
|
|
||||||
match t_spec {
|
|
||||||
TypeSpec::PreDeclTy(predecl) => Self::predecl_type_spec_to_expr(predecl),
|
|
||||||
TypeSpec::Or(lhs, rhs) => {
|
|
||||||
let lhs = Self::type_spec_to_expr(*lhs)?;
|
|
||||||
let rhs = Self::type_spec_to_expr(*rhs)?;
|
|
||||||
let op = Token::new(
|
|
||||||
TokenKind::OrOp,
|
|
||||||
"or",
|
|
||||||
lhs.ln_begin().unwrap(),
|
|
||||||
lhs.col_end().unwrap(),
|
|
||||||
);
|
|
||||||
let bin = BinOp::new(op, lhs, rhs);
|
|
||||||
Ok(Expr::BinOp(bin))
|
|
||||||
}
|
|
||||||
TypeSpec::And(lhs, rhs) => {
|
|
||||||
let lhs = Self::type_spec_to_expr(*lhs)?;
|
|
||||||
let rhs = Self::type_spec_to_expr(*rhs)?;
|
|
||||||
let op = Token::new(
|
|
||||||
TokenKind::AndOp,
|
|
||||||
"and",
|
|
||||||
lhs.ln_begin().unwrap(),
|
|
||||||
lhs.col_end().unwrap(),
|
|
||||||
);
|
|
||||||
let bin = BinOp::new(op, lhs, rhs);
|
|
||||||
Ok(Expr::BinOp(bin))
|
|
||||||
}
|
|
||||||
other => Err(ParseError::feature_error(
|
|
||||||
line!() as usize,
|
|
||||||
other.loc(),
|
|
||||||
"compound type spec to expr conversion",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue