mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 04:09:05 +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
|
||||
}
|
||||
|
||||
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> {
|
||||
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))
|
||||
}
|
||||
|
||||
|
@ -490,13 +522,7 @@ impl<'a> HIRVisitor<'a> {
|
|||
.require_or_sup
|
||||
.as_ref()
|
||||
.and_then(|req_sup| self.get_expr_info(req_sup, token))
|
||||
.or_else(|| {
|
||||
self.return_var_info_if_same(
|
||||
class_def.sig.ident(),
|
||||
class_def.sig.ident().name.token(),
|
||||
token,
|
||||
)
|
||||
})
|
||||
.or_else(|| self.get_sig_info(&class_def.sig, token))
|
||||
.or_else(|| self.get_block_info(&class_def.methods, token))
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
return result;
|
||||
};
|
||||
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;
|
||||
}
|
||||
let hint = type_anot(
|
||||
|
@ -125,7 +125,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
result.push(hint);
|
||||
}
|
||||
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;
|
||||
}
|
||||
let hint = type_anot(
|
||||
|
@ -185,7 +185,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
return result;
|
||||
};
|
||||
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;
|
||||
}
|
||||
let hint = type_anot(
|
||||
|
@ -197,7 +197,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
|
|||
result.push(hint);
|
||||
}
|
||||
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;
|
||||
}
|
||||
let hint = type_anot(
|
||||
|
|
|
@ -25,9 +25,7 @@ use erg_common::{
|
|||
use erg_parser::ast::{DefId, DefKind};
|
||||
use CommonOpcode::*;
|
||||
|
||||
use erg_parser::ast::PreDeclTypeSpec;
|
||||
use erg_parser::ast::TypeSpec;
|
||||
use erg_parser::ast::{NonDefaultParamSignature, ParamPattern, VarName};
|
||||
use erg_parser::ast::{ParamPattern, VarName};
|
||||
use erg_parser::token::DOT;
|
||||
use erg_parser::token::EQUAL;
|
||||
use erg_parser::token::{Token, TokenKind};
|
||||
|
@ -36,11 +34,12 @@ use crate::compile::{AccessKind, Name, StoreLoadKind};
|
|||
use crate::error::CompileError;
|
||||
use crate::hir::{
|
||||
Accessor, Args, Array, BinOp, Block, Call, ClassDef, Def, DefBody, Expr, Identifier, Lambda,
|
||||
Literal, Params, PatchDef, PosArg, ReDef, Record, Signature, SubrSignature, Tuple, UnaryOp,
|
||||
VarSignature, HIR,
|
||||
Literal, NonDefaultParamSignature, Params, PatchDef, PosArg, ReDef, Record, Signature,
|
||||
SubrSignature, Tuple, UnaryOp, VarSignature, HIR,
|
||||
};
|
||||
use crate::ty::value::ValueObj;
|
||||
use crate::ty::{HasType, Type, TypeCode, TypePair};
|
||||
use crate::varinfo::VarInfo;
|
||||
use erg_common::fresh::fresh_varname;
|
||||
use AccessKind::*;
|
||||
use Type::*;
|
||||
|
@ -1850,46 +1849,9 @@ impl PyCodeGenerator {
|
|||
) -> Vec<usize> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
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 !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
|
||||
// ↓ SWAP 1
|
||||
// null arg
|
||||
|
@ -1906,15 +1868,7 @@ impl PyCodeGenerator {
|
|||
}
|
||||
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.emit_expr(t_spec);
|
||||
self.emit_precall_and_call(2);
|
||||
self.stack_dec();
|
||||
pop_jump_points.push(self.lasti());
|
||||
|
@ -1924,127 +1878,18 @@ impl PyCodeGenerator {
|
|||
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(Opcode311::BINARY_SUBSCR);
|
||||
self.write_arg(0);
|
||||
self.stack_dec();
|
||||
self.emit_match_guard_311(t_spec, pop_jump_points);
|
||||
match param.raw.pat {
|
||||
ParamPattern::VarName(name) => {
|
||||
let ident = Identifier::bare(None, name);
|
||||
self.emit_store_instr(ident, AccessKind::Name);
|
||||
}
|
||||
ParamPattern::Discard(_) => {
|
||||
self.emit_pop_top();
|
||||
}
|
||||
// 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(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}"),
|
||||
_other => unreachable!(),
|
||||
}
|
||||
pop_jump_points
|
||||
}
|
||||
|
||||
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);
|
||||
ident.vi.t = __new__.clone();
|
||||
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 = new_first_param
|
||||
.name()
|
||||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(fresh_varname);
|
||||
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);
|
||||
(param_name, params)
|
||||
} else {
|
||||
|
@ -2965,7 +2819,10 @@ impl PyCodeGenerator {
|
|||
.map(|s| s.to_string())
|
||||
.unwrap_or_else(fresh_varname);
|
||||
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 sig = SubrSignature::new(ident, params, sig.t_spec().cloned());
|
||||
let arg = PosArg::new(Expr::Accessor(Accessor::private_with_line(
|
||||
|
|
|
@ -761,6 +761,26 @@ impl Context {
|
|||
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<()> {
|
||||
match expr {
|
||||
hir::Expr::Lit(_) => Ok(()),
|
||||
|
@ -898,6 +918,9 @@ impl Context {
|
|||
hir::Expr::Def(def) => {
|
||||
*def.sig.ref_mut_t() =
|
||||
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() {
|
||||
self.resolve_expr_t(chunk)?;
|
||||
}
|
||||
|
@ -905,6 +928,7 @@ impl Context {
|
|||
}
|
||||
hir::Expr::Lambda(lambda) => {
|
||||
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() {
|
||||
self.resolve_expr_t(chunk)?;
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ impl Context {
|
|||
}
|
||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||
let rhs = self.instantiate_param_sig_t(
|
||||
&lambda.params.non_defaults[0],
|
||||
&lambda.params.non_defaults[0].raw,
|
||||
None,
|
||||
&mut dummy_tv_cache,
|
||||
Normal,
|
||||
|
|
|
@ -379,8 +379,14 @@ impl Context {
|
|||
mode: RegistrationMode,
|
||||
kind: ParamKind,
|
||||
) -> TyCheckResult<Type> {
|
||||
let spec_t = if let Some(spec_with_op) = &sig.t_spec {
|
||||
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tmp_tv_cache, mode, false)?
|
||||
let spec_t = if let Some(t_spec_with_op) = &sig.t_spec {
|
||||
self.instantiate_typespec(
|
||||
&t_spec_with_op.t_spec,
|
||||
opt_decl_t,
|
||||
tmp_tv_cache,
|
||||
mode,
|
||||
false,
|
||||
)?
|
||||
} else {
|
||||
match &sig.pat {
|
||||
ast::ParamPattern::Lit(lit) => v_enum(set![self.eval_lit(lit)?]),
|
||||
|
|
|
@ -242,10 +242,11 @@ impl Context {
|
|||
Ok(vi)
|
||||
}
|
||||
|
||||
/// TODO: sig should be immutable
|
||||
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
||||
fn assign_param(
|
||||
&mut self,
|
||||
sig: &ast::NonDefaultParamSignature,
|
||||
sig: &mut hir::NonDefaultParamSignature,
|
||||
opt_decl_t: Option<&ParamTy>,
|
||||
kind: ParamKind,
|
||||
) -> TyCheckResult<()> {
|
||||
|
@ -256,12 +257,12 @@ impl Context {
|
|||
};
|
||||
let default = kind.default_info();
|
||||
let is_var_params = kind.is_var_params();
|
||||
match &sig.pat {
|
||||
match &sig.raw.pat {
|
||||
// Literal patterns will be desugared to discard patterns
|
||||
ast::ParamPattern::Lit(_) => unreachable!(),
|
||||
ast::ParamPattern::Discard(token) => {
|
||||
let spec_t = self.instantiate_param_sig_t(
|
||||
sig,
|
||||
&sig.raw,
|
||||
opt_decl_t,
|
||||
&mut TyVarCache::new(self.level, self),
|
||||
Normal,
|
||||
|
@ -279,6 +280,7 @@ impl Context {
|
|||
None,
|
||||
self.absolutize(token.loc()),
|
||||
);
|
||||
sig.vi = vi.clone();
|
||||
self.params.push((Some(VarName::from_static("_")), vi));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -298,7 +300,7 @@ impl Context {
|
|||
// ok, not defined
|
||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||
let spec_t = self.instantiate_param_sig_t(
|
||||
sig,
|
||||
&sig.raw,
|
||||
opt_decl_t,
|
||||
&mut dummy_tv_cache,
|
||||
Normal,
|
||||
|
@ -332,6 +334,7 @@ impl Context {
|
|||
if let Some(shared) = self.shared() {
|
||||
shared.index.register(&vi);
|
||||
}
|
||||
sig.vi = vi.clone();
|
||||
self.params.push((Some(name.clone()), vi));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -352,7 +355,7 @@ impl Context {
|
|||
// ok, not defined
|
||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||
let spec_t = self.instantiate_param_sig_t(
|
||||
sig,
|
||||
&sig.raw,
|
||||
opt_decl_t,
|
||||
&mut dummy_tv_cache,
|
||||
Normal,
|
||||
|
@ -377,6 +380,7 @@ impl Context {
|
|||
None,
|
||||
self.absolutize(name.loc()),
|
||||
);
|
||||
sig.vi = vi.clone();
|
||||
self.params.push((Some(name.clone()), vi));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -397,7 +401,7 @@ impl Context {
|
|||
// ok, not defined
|
||||
let mut dummy_tv_cache = TyVarCache::new(self.level, self);
|
||||
let spec_t = self.instantiate_param_sig_t(
|
||||
sig,
|
||||
&sig.raw,
|
||||
opt_decl_t,
|
||||
&mut dummy_tv_cache,
|
||||
Normal,
|
||||
|
@ -422,6 +426,7 @@ impl Context {
|
|||
None,
|
||||
self.absolutize(name.loc()),
|
||||
);
|
||||
sig.vi = vi.clone();
|
||||
self.params.push((Some(name.clone()), vi));
|
||||
Ok(())
|
||||
}
|
||||
|
@ -435,7 +440,7 @@ impl Context {
|
|||
|
||||
pub(crate) fn assign_params(
|
||||
&mut self,
|
||||
params: &hir::Params,
|
||||
params: &mut hir::Params,
|
||||
opt_decl_subr_t: Option<SubrType>,
|
||||
) -> TyCheckResult<()> {
|
||||
let mut errs = TyCheckErrors::empty();
|
||||
|
@ -445,16 +450,16 @@ impl Context {
|
|||
decl_subr_t.non_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
|
||||
.iter()
|
||||
.iter_mut()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
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 {
|
||||
let pt = pt.clone().map_type(unknown_len_array_t);
|
||||
if let Err(es) = self.assign_param(var_params, Some(&pt), ParamKind::VarParams)
|
||||
|
@ -465,27 +470,31 @@ impl Context {
|
|||
errs.extend(es);
|
||||
}
|
||||
}
|
||||
for (sig, pt) in params
|
||||
for (default, pt) in params
|
||||
.defaults
|
||||
.iter()
|
||||
.iter_mut()
|
||||
.zip(decl_subr_t.default_params.iter())
|
||||
{
|
||||
if let Err(es) =
|
||||
self.assign_param(&sig.sig, Some(pt), ParamKind::Default(sig.default_val.t()))
|
||||
{
|
||||
if let Err(es) = self.assign_param(
|
||||
&mut default.sig,
|
||||
Some(pt),
|
||||
ParamKind::Default(default.default_val.t()),
|
||||
) {
|
||||
errs.extend(es);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for sig in params.non_defaults.iter() {
|
||||
if let Err(es) = self.assign_param(sig, None, ParamKind::NonDefault) {
|
||||
for non_default in params.non_defaults.iter_mut() {
|
||||
if let Err(es) = self.assign_param(non_default, None, ParamKind::NonDefault) {
|
||||
errs.extend(es);
|
||||
}
|
||||
}
|
||||
for sig in params.defaults.iter() {
|
||||
if let Err(es) =
|
||||
self.assign_param(&sig.sig, None, ParamKind::Default(sig.default_val.t()))
|
||||
{
|
||||
for default in params.defaults.iter_mut() {
|
||||
if let Err(es) = self.assign_param(
|
||||
&mut default.sig,
|
||||
None,
|
||||
ParamKind::Default(default.default_val.t()),
|
||||
) {
|
||||
errs.extend(es);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::ty::free::HasLevel;
|
|||
use crate::ty::value::{GenTypeObj, TypeObj};
|
||||
use crate::ty::{HasType, Type};
|
||||
|
||||
use crate::compile::AccessKind;
|
||||
use crate::context::RegistrationMode;
|
||||
use crate::error::{LowerError, LowerErrors, LowerResult};
|
||||
use crate::hir;
|
||||
|
@ -119,16 +120,28 @@ impl ASTLowerer {
|
|||
res
|
||||
}
|
||||
|
||||
fn fake_lower_obj(&self, obj: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
match obj {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||
let acc = hir::Accessor::Ident(hir::Identifier::bare(ident.dot, ident.name));
|
||||
Ok(hir::Expr::Accessor(acc))
|
||||
fn fake_lower_acc(&self, acc: ast::Accessor) -> LowerResult<hir::Accessor> {
|
||||
match acc {
|
||||
ast::Accessor::Ident(ident) => {
|
||||
// to resolve `py_name`
|
||||
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)) => {
|
||||
let obj = self.fake_lower_obj(*attr.obj)?;
|
||||
ast::Accessor::Attr(attr) => {
|
||||
let obj = self.fake_lower_expr(*attr.obj)?;
|
||||
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(
|
||||
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> {
|
||||
log!(info "entered {}({})", fn_name!(), tasc);
|
||||
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 t = self.module.context.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
&tasc.t_spec.t_spec,
|
||||
None,
|
||||
&mut dummy_tv_cache,
|
||||
RegistrationMode::Normal,
|
||||
|
@ -177,7 +454,10 @@ impl ASTLowerer {
|
|||
self.module.context.absolutize(ident.loc()),
|
||||
);
|
||||
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)) => {
|
||||
if cfg!(feature = "py_compatible") {
|
||||
|
@ -185,7 +465,7 @@ impl ASTLowerer {
|
|||
}
|
||||
let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
|
||||
let t = self.module.context.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
&tasc.t_spec.t_spec,
|
||||
None,
|
||||
&mut dummy_tv_cache,
|
||||
RegistrationMode::Normal,
|
||||
|
@ -202,7 +482,7 @@ impl ASTLowerer {
|
|||
ast::DefId(0),
|
||||
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 vis = attr.ident.vis();
|
||||
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 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(
|
||||
self.cfg().input.clone(),
|
||||
|
|
|
@ -250,7 +250,7 @@ impl SideEffectChecker {
|
|||
self.errs.push(EffectError::proc_assign_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
nd_param.pat.loc(),
|
||||
nd_param.raw.pat.loc(),
|
||||
self.full_path(),
|
||||
));
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ impl SideEffectChecker {
|
|||
self.errs.push(EffectError::proc_assign_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
var_arg.pat.loc(),
|
||||
var_arg.raw.pat.loc(),
|
||||
self.full_path(),
|
||||
));
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ impl SideEffectChecker {
|
|||
self.errs.push(EffectError::proc_assign_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
d_param.sig.pat.loc(),
|
||||
d_param.sig.raw.pat.loc(),
|
||||
self.full_path(),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -14,9 +14,8 @@ use erg_common::{
|
|||
impl_nested_display_for_enum, impl_no_type_display_for_enum, impl_stream,
|
||||
};
|
||||
|
||||
use erg_parser::ast::{
|
||||
fmt_lines, DefId, DefKind, NonDefaultParamSignature, OperationKind, TypeSpec, VarName,
|
||||
};
|
||||
use erg_parser::ast;
|
||||
use erg_parser::ast::{fmt_lines, DefId, DefKind, OperationKind, TypeSpec, VarName};
|
||||
use erg_parser::token::{Token, TokenKind, DOT};
|
||||
|
||||
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
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct DefaultParamSignature {
|
||||
|
@ -1626,7 +1669,7 @@ impl DefaultParamSignature {
|
|||
}
|
||||
|
||||
pub const fn inspect(&self) -> Option<&Str> {
|
||||
self.sig.pat.inspect()
|
||||
self.sig.inspect()
|
||||
}
|
||||
|
||||
pub const fn name(&self) -> Option<&VarName> {
|
||||
|
@ -1930,6 +1973,13 @@ impl Signature {
|
|||
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)]
|
||||
|
@ -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)]
|
||||
pub struct TypeAscription {
|
||||
pub expr: Box<Expr>,
|
||||
pub spec: TypeSpec,
|
||||
pub spec: TypeSpecWithOp,
|
||||
}
|
||||
|
||||
impl NestedDisplay for TypeAscription {
|
||||
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 {
|
||||
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 {
|
||||
pub fn new(expr: Expr, spec: TypeSpec) -> Self {
|
||||
pub fn new(expr: Expr, spec: TypeSpecWithOp) -> Self {
|
||||
Self {
|
||||
expr: Box::new(expr),
|
||||
spec,
|
||||
|
@ -2412,11 +2488,11 @@ impl Expr {
|
|||
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)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ class BoolMut(NatMut):
|
|||
self.value = b
|
||||
def __repr__(self):
|
||||
return self.value.__repr__()
|
||||
def __hash__(self):
|
||||
return self.value.__hash__()
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, bool):
|
||||
return self.value == other
|
||||
|
|
|
@ -41,6 +41,8 @@ class FloatMut(): # inherits Float
|
|||
self.value = Float(i)
|
||||
def __repr__(self):
|
||||
return self.value.__repr__()
|
||||
def __hash__(self):
|
||||
return self.value.__hash__()
|
||||
def __deref__(self):
|
||||
return self.value
|
||||
def __eq__(self, other):
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
from _erg_result import is_ok
|
||||
from _erg_range import Range
|
||||
|
||||
def in_operator(x, y):
|
||||
def in_operator(elem, y):
|
||||
if type(y) == type:
|
||||
if isinstance(x, y):
|
||||
if isinstance(elem, y):
|
||||
return True
|
||||
elif is_ok(y.try_new(x)):
|
||||
elif is_ok(y.try_new(elem)):
|
||||
return True
|
||||
# TODO: trait check
|
||||
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)):
|
||||
# FIXME:
|
||||
type_check = in_operator(x[0], y[0])
|
||||
len_check = len(x) == len(y)
|
||||
type_check = in_operator(elem[0], y[0])
|
||||
len_check = len(elem) == len(y)
|
||||
return type_check and len_check
|
||||
elif issubclass(type(y), dict) and issubclass(type(next(iter(y.keys()))), type):
|
||||
# TODO:
|
||||
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
|
||||
else:
|
||||
return x in y
|
||||
return elem in y
|
||||
|
|
|
@ -45,6 +45,8 @@ class IntMut(): # inherits Int
|
|||
self.value = Int(i)
|
||||
def __repr__(self):
|
||||
return self.value.__repr__()
|
||||
def __hash__(self):
|
||||
return self.value.__hash__()
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Int):
|
||||
return self.value == other
|
||||
|
|
|
@ -33,6 +33,8 @@ class NatMut(IntMut): # and Nat
|
|||
self.value = n
|
||||
def __repr__(self):
|
||||
return self.value.__repr__()
|
||||
def __hash__(self):
|
||||
return self.value.__hash__()
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, int):
|
||||
return self.value == other
|
||||
|
|
|
@ -37,6 +37,8 @@ class StrMut(): # Inherits Str
|
|||
self.value = s
|
||||
def __repr__(self):
|
||||
return self.value.__repr__()
|
||||
def __hash__(self):
|
||||
return self.value.__hash__()
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Str):
|
||||
return self.value == other
|
||||
|
|
|
@ -701,38 +701,8 @@ impl ASTLowerer {
|
|||
Ok(hir::UnaryOp::new(unary.op, expr, t))
|
||||
}
|
||||
|
||||
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 (pos_args, var_args, kw_args, paren) = call.args.deconstruct();
|
||||
fn lower_args(&mut self, args: ast::Args, errs: &mut LowerErrors) -> hir::Args {
|
||||
let (pos_args, var_args, kw_args, paren) = args.deconstruct();
|
||||
let mut hir_args = hir::Args::new(
|
||||
Vec::with_capacity(pos_args.len()),
|
||||
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) {
|
||||
Ok(obj) => obj,
|
||||
Err(es) => {
|
||||
|
@ -895,14 +900,59 @@ impl ASTLowerer {
|
|||
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> {
|
||||
log!(info "entered {}({})", fn_name!(), params);
|
||||
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![];
|
||||
for default in params.defaults.into_iter() {
|
||||
match self.lower_expr(default.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),
|
||||
}
|
||||
|
@ -911,8 +961,8 @@ impl ASTLowerer {
|
|||
Err(errs)
|
||||
} else {
|
||||
let hir_params = hir::Params::new(
|
||||
params.non_defaults,
|
||||
params.var_params,
|
||||
hir_non_defaults,
|
||||
hir_var_params,
|
||||
hir_defaults,
|
||||
params.parens,
|
||||
);
|
||||
|
@ -949,13 +999,13 @@ impl ASTLowerer {
|
|||
.context
|
||||
.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 {
|
||||
self.pop_append_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);
|
||||
}
|
||||
if let Err(errs) = self.module.context.preregister(&lambda.body) {
|
||||
|
@ -1011,12 +1061,12 @@ impl ASTLowerer {
|
|||
} else {
|
||||
self.pop_append_errs();
|
||||
}
|
||||
let t = if is_procedural {
|
||||
let ty = if is_procedural {
|
||||
proc(non_default_params, None, default_params, body.t())
|
||||
} else {
|
||||
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))
|
||||
}
|
||||
|
||||
|
@ -1184,8 +1234,8 @@ impl ASTLowerer {
|
|||
.unwrap_or(Type::Failure);
|
||||
match registered_t {
|
||||
Type::Subr(subr_t) => {
|
||||
let params = self.lower_params(sig.params.clone())?;
|
||||
if let Err(errs) = self.module.context.assign_params(¶ms, Some(subr_t)) {
|
||||
let mut params = self.lower_params(sig.params.clone())?;
|
||||
if let Err(errs) = self.module.context.assign_params(&mut params, Some(subr_t)) {
|
||||
self.errs.extend(errs);
|
||||
}
|
||||
if let Err(errs) = self.module.context.preregister(&body.block) {
|
||||
|
@ -1241,8 +1291,8 @@ impl ASTLowerer {
|
|||
}
|
||||
}
|
||||
Type::Failure => {
|
||||
let params = self.lower_params(sig.params)?;
|
||||
if let Err(errs) = self.module.context.assign_params(¶ms, None) {
|
||||
let mut params = self.lower_params(sig.params)?;
|
||||
if let Err(errs) = self.module.context.assign_params(&mut params, None) {
|
||||
self.errs.extend(errs);
|
||||
}
|
||||
if let Err(errs) = self.module.context.preregister(&body.block) {
|
||||
|
@ -1276,7 +1326,7 @@ impl ASTLowerer {
|
|||
// TODO: check `tasc.op`
|
||||
ast::Expr::TypeAscription(tasc) => (
|
||||
self.module.context.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
&tasc.t_spec.t_spec,
|
||||
None,
|
||||
&mut dummy_tv_cache,
|
||||
RegistrationMode::Normal,
|
||||
|
@ -1891,7 +1941,7 @@ impl ASTLowerer {
|
|||
let is_instance_ascription = tasc.is_instance_ascription();
|
||||
let mut dummy_tv_cache = TyVarCache::new(self.module.context.level, &self.module.context);
|
||||
let spec_t = self.module.context.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
&tasc.t_spec.t_spec,
|
||||
None,
|
||||
&mut dummy_tv_cache,
|
||||
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> {
|
||||
|
@ -1934,7 +1985,7 @@ impl ASTLowerer {
|
|||
let is_instance_ascription = tasc.is_instance_ascription();
|
||||
let mut dummy_tv_cache = TyVarCache::new(self.module.context.level, &self.module.context);
|
||||
let spec_t = self.module.context.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
&tasc.t_spec.t_spec,
|
||||
None,
|
||||
&mut dummy_tv_cache,
|
||||
RegistrationMode::Normal,
|
||||
|
@ -2005,7 +2056,8 @@ impl ASTLowerer {
|
|||
.map(|ctx| ctx.name.clone());
|
||||
let ident = hir::Identifier::new(ident.dot, ident.name, qual_name, ident_vi);
|
||||
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)
|
||||
|
|
|
@ -112,17 +112,17 @@ impl OwnershipChecker {
|
|||
if let Signature::Subr(subr) = &def.sig {
|
||||
let (nd_params, var_params, d_params, _) = subr.params.ref_deconstruct();
|
||||
for param in nd_params {
|
||||
if let ParamPattern::VarName(name) = ¶m.pat {
|
||||
if let ParamPattern::VarName(name) = ¶m.raw.pat {
|
||||
self.define_param(name);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -616,8 +616,8 @@ impl ScriptGenerator {
|
|||
let mut code = "for ".to_string();
|
||||
let iter = call.args.remove(0);
|
||||
let Expr::Lambda(block) = call.args.remove(0) else { todo!() };
|
||||
let sig = block.params.non_defaults.get(0).unwrap();
|
||||
let ParamPattern::VarName(param) = &sig.pat else { todo!() };
|
||||
let non_default = block.params.non_defaults.get(0).unwrap();
|
||||
let ParamPattern::VarName(param) = &non_default.raw.pat else { todo!() };
|
||||
code += &format!("{}__ ", ¶m.token().content);
|
||||
code += &format!("in {}:\n", self.transpile_expr(iter));
|
||||
code += &self.transpile_block(block.body, Discard);
|
||||
|
@ -703,14 +703,14 @@ impl ScriptGenerator {
|
|||
self.level += 1;
|
||||
code += &" ".repeat(self.level);
|
||||
let target = arm.params.non_defaults.get(0).unwrap();
|
||||
match &target.pat {
|
||||
match &target.raw.pat {
|
||||
ParamPattern::VarName(param) => {
|
||||
code += &format!("case {}__:\n", ¶m.token().content);
|
||||
code += &self.transpile_block(arm.body, StoreTmp(tmp.clone()));
|
||||
self.level -= 1;
|
||||
}
|
||||
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)) => {
|
||||
let values = ValueObj::vec_from_const_args(enum_t.clone());
|
||||
if values.len() == 1 {
|
||||
|
@ -799,7 +799,7 @@ impl ScriptGenerator {
|
|||
fn transpile_params(&mut self, params: Params) -> String {
|
||||
let mut code = String::new();
|
||||
for non_default in params.non_defaults {
|
||||
match non_default.pat {
|
||||
match non_default.raw.pat {
|
||||
ParamPattern::VarName(param) => {
|
||||
code += &format!("{}__,", param.into_token().content);
|
||||
}
|
||||
|
@ -811,7 +811,7 @@ impl ScriptGenerator {
|
|||
}
|
||||
}
|
||||
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!(
|
||||
"{}__ = {},",
|
||||
param.into_token().content,
|
||||
|
|
|
@ -218,4 +218,12 @@ impl VarInfo {
|
|||
_ => 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);
|
||||
|
||||
#[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 {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
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 {
|
||||
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
|
||||
} 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;
|
||||
|
||||
|
@ -2218,6 +2229,7 @@ impl TypeSpec {
|
|||
pub struct TypeSpecWithOp {
|
||||
pub op: Token,
|
||||
pub t_spec: TypeSpec,
|
||||
pub t_spec_as_expr: Box<Expr>,
|
||||
}
|
||||
|
||||
impl NestedDisplay for TypeSpecWithOp {
|
||||
|
@ -2230,8 +2242,12 @@ impl_display_from_nested!(TypeSpecWithOp);
|
|||
impl_locational!(TypeSpecWithOp, lossy op, t_spec);
|
||||
|
||||
impl TypeSpecWithOp {
|
||||
pub const fn new(op: Token, t_spec: TypeSpec) -> Self {
|
||||
Self { op, t_spec }
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3447,13 +3463,12 @@ impl Signature {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct TypeAscription {
|
||||
pub expr: Box<Expr>,
|
||||
pub op: Token,
|
||||
pub t_spec: TypeSpec,
|
||||
pub t_spec: TypeSpecWithOp,
|
||||
}
|
||||
|
||||
impl NestedDisplay for TypeAscription {
|
||||
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 TypeAscription {
|
||||
pub fn new(expr: Expr, op: Token, t_spec: TypeSpec) -> Self {
|
||||
pub fn new(expr: Expr, t_spec: TypeSpecWithOp) -> Self {
|
||||
Self {
|
||||
expr: Box::new(expr),
|
||||
op,
|
||||
t_spec,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
self.op.is(TokenKind::SubtypeOf)
|
||||
self.t_spec.op.is(TokenKind::SubtypeOf)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3826,12 +3840,16 @@ impl Expr {
|
|||
Self::Call(self.call(args))
|
||||
}
|
||||
|
||||
pub fn type_asc(self, op: Token, t_spec: TypeSpec) -> TypeAscription {
|
||||
TypeAscription::new(self, op, t_spec)
|
||||
pub fn type_asc(self, t_spec: TypeSpecWithOp) -> TypeAscription {
|
||||
TypeAscription::new(self, t_spec)
|
||||
}
|
||||
|
||||
pub fn type_asc_expr(self, op: Token, t_spec: TypeSpec) -> Self {
|
||||
Self::TypeAscription(self.type_asc(op, t_spec))
|
||||
pub fn type_asc_expr(self, t_spec: TypeSpecWithOp) -> Self {
|
||||
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!()))?;
|
||||
let sig = match sig {
|
||||
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::Subr(subr) => {
|
||||
|
@ -245,7 +245,7 @@ impl Parser {
|
|||
subr.ident,
|
||||
subr.bounds,
|
||||
subr.params,
|
||||
Some(tasc.t_spec),
|
||||
Some(tasc.t_spec.t_spec),
|
||||
);
|
||||
Signature::Subr(subr)
|
||||
}
|
||||
|
@ -334,8 +334,7 @@ impl Parser {
|
|||
.unwrap_or_else(|| todo!())
|
||||
.pat;
|
||||
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(), spec_with_op);
|
||||
let bound = TypeBoundSpec::non_default(lhs.name.into_token(), tasc.t_spec);
|
||||
Ok(bound)
|
||||
}
|
||||
other => {
|
||||
|
@ -598,8 +597,7 @@ impl Parser {
|
|||
let param = self
|
||||
.convert_rhs_to_param(*tasc.expr, allow_self)
|
||||
.map_err(|_| self.stack_dec(fn_name!()))?;
|
||||
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
||||
let param = NonDefaultParamSignature::new(param.pat, Some(t_spec));
|
||||
let param = NonDefaultParamSignature::new(param.pat, Some(tasc.t_spec));
|
||||
debug_exit_info!(self);
|
||||
Ok(param)
|
||||
}
|
||||
|
|
|
@ -270,7 +270,10 @@ impl Desugarer {
|
|||
}
|
||||
Expr::TypeAscription(tasc) => {
|
||||
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) => {
|
||||
let mut new_attrs = vec![];
|
||||
|
@ -286,7 +289,13 @@ impl Desugarer {
|
|||
}
|
||||
ClassAttr::Decl(decl) => {
|
||||
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) => {
|
||||
new_attrs.push(ClassAttr::Doc(doc));
|
||||
|
@ -298,11 +307,12 @@ impl Desugarer {
|
|||
}
|
||||
Expr::Accessor(acc) => Expr::Accessor(Self::perform_desugar_acc(desugar, acc)),
|
||||
Expr::Dummy(exprs) => {
|
||||
let loc = exprs.loc;
|
||||
let mut chunks = vec![];
|
||||
for chunk in exprs.into_iter() {
|
||||
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.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) => {
|
||||
let (buf_name, buf_param) = self.gen_buf_nd_param(line);
|
||||
|
@ -797,7 +822,8 @@ impl Desugarer {
|
|||
}
|
||||
if param.t_spec.is_none() {
|
||||
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;
|
||||
}
|
||||
|
@ -817,9 +843,11 @@ impl Desugarer {
|
|||
let len = Literal::new(Token::new(TokenKind::NatLit, len.to_string(), line, 0));
|
||||
let infer = Token::new(TokenKind::Try, "?", line, 0);
|
||||
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(
|
||||
Token::dummy(TokenKind::Colon, ":"),
|
||||
TypeSpec::Array(t_spec),
|
||||
t_spec_as_expr,
|
||||
));
|
||||
}
|
||||
param.pat = buf_param;
|
||||
|
@ -848,7 +876,9 @@ impl Desugarer {
|
|||
.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;
|
||||
}
|
||||
|
@ -937,7 +967,8 @@ impl Desugarer {
|
|||
}
|
||||
if sig.t_spec.is_none() {
|
||||
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;
|
||||
insertion_idx
|
||||
|
@ -968,8 +999,31 @@ impl Desugarer {
|
|||
let len = arr.elems.non_defaults.len();
|
||||
let len = Literal::new(Token::new(TokenKind::NatLit, len.to_string(), line, 0));
|
||||
let infer = Token::new(TokenKind::Try, "?", line, 0);
|
||||
let t_spec = ArrayTypeSpec::new(TypeSpec::Infer(infer), ConstExpr::Lit(len));
|
||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, TypeSpec::Array(t_spec)));
|
||||
let 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;
|
||||
insertion_idx
|
||||
|
@ -1007,7 +1061,9 @@ impl Desugarer {
|
|||
));
|
||||
}
|
||||
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;
|
||||
insertion_idx
|
||||
|
@ -1047,7 +1103,21 @@ impl Desugarer {
|
|||
l.ln_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,
|
||||
|
|
|
@ -716,10 +716,10 @@ impl Parser {
|
|||
Args::new(vec![], Some(pos_args), vec![], None)
|
||||
}
|
||||
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)) => {
|
||||
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)
|
||||
}
|
||||
PosOrKwArg::Pos(arg) => Args::pos_only(vec![arg], None),
|
||||
|
@ -786,12 +786,12 @@ impl Parser {
|
|||
args.set_var_args(PosArg::new(unary.deconstruct().1));
|
||||
}
|
||||
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)) =>
|
||||
{
|
||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
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) => {
|
||||
|
@ -908,8 +908,7 @@ impl Parser {
|
|||
Expr::Accessor(Accessor::Ident(n)) => (n.name.into_token(), None),
|
||||
Expr::TypeAscription(tasc) => {
|
||||
if let Expr::Accessor(Accessor::Ident(n)) = *tasc.expr {
|
||||
let t_spec = TypeSpecWithOp::new(tasc.op, tasc.t_spec);
|
||||
(n.name.into_token(), Some(t_spec))
|
||||
(n.name.into_token(), Some(tasc.t_spec))
|
||||
} else {
|
||||
let err = ParseError::simple_syntax_error(0, tasc.loc());
|
||||
self.errs.push(err);
|
||||
|
@ -1165,11 +1164,13 @@ impl Parser {
|
|||
}
|
||||
let op = self.lpop();
|
||||
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)
|
||||
.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 expr = lhs.type_asc_expr(op, t_spec);
|
||||
let t_spec = Self::expr_to_type_spec(t_spec_as_expr.clone())
|
||||
.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));
|
||||
}
|
||||
Some(op) if op.category_is(TC::BinOp) => {
|
||||
|
@ -1434,11 +1435,13 @@ impl Parser {
|
|||
}
|
||||
let op = self.lpop();
|
||||
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)
|
||||
.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 expr = lhs.type_asc_expr(op, t_spec);
|
||||
let t_spec = Self::expr_to_type_spec(t_spec_as_expr.clone())
|
||||
.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));
|
||||
}
|
||||
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::TypeAscription(tasc) => {
|
||||
if let Expr::Accessor(Accessor::Ident(ident)) = *tasc.expr {
|
||||
(
|
||||
ident.name.into_token(),
|
||||
Some(TypeSpecWithOp::new(tasc.op, tasc.t_spec)),
|
||||
)
|
||||
(ident.name.into_token(), Some(tasc.t_spec))
|
||||
} else {
|
||||
let err = ParseError::simple_syntax_error(line!() as usize, tasc.loc());
|
||||
self.errs.push(err);
|
||||
|
@ -2367,11 +2367,11 @@ impl Parser {
|
|||
Args::new(vec![], var_args, vec![], None)
|
||||
}
|
||||
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)) => {
|
||||
let Expr::UnaryOp(unary) = *expr else { unreachable!() };
|
||||
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)
|
||||
}
|
||||
PosOrKwArg::Pos(pos) => Args::pos_only(vec![pos], None),
|
||||
|
@ -2402,11 +2402,11 @@ impl Parser {
|
|||
Expr::UnaryOp(unary) if unary.op.is(PreStar) => {
|
||||
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 = 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() => {
|
||||
args.extend_pos(tup.elems.into_iters().0);
|
||||
|
|
|
@ -3,7 +3,7 @@ use erg_common::traits::{Locational, Stream};
|
|||
|
||||
use crate::ast::*;
|
||||
use crate::error::ParseError;
|
||||
use crate::token::{Token, TokenKind};
|
||||
use crate::token::TokenKind;
|
||||
use crate::Parser;
|
||||
|
||||
// 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