Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

breaking change: Remove unused type parameters from enum case #514

Merged
merged 6 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion builtin/error.sk
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ class Error
# def backtrace

def to_s -> String
"#<Error: #{@msg}>"
"#<Error \{@msg}>"
end
end
2 changes: 1 addition & 1 deletion builtin/file.sk
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class File : Readable
#file.close
Ok.new(v)
when Fail(e)
Fail<V>.new(e)
Fail.new(e)
end
end

Expand Down
6 changes: 3 additions & 3 deletions builtin/readable.sk
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module Readable
end
end
when Fail(e)
return Fail<Maybe<String>>.new(e)
return Fail.new(e)
end
break if done
end
Expand All @@ -44,7 +44,7 @@ module Readable
when Ok(None)
break
when Fail(e)
return Fail<Array<String>>.new(e)
return Fail.new(e)
end
end
Ok.new(a)
Expand All @@ -62,7 +62,7 @@ module Readable
consume(s.bytesize)
end
when Fail(e)
return Fail<String>.new(e)
return Fail.new(e)
end
end
Ok.new(acc._unsafe_to_s)
Expand Down
4 changes: 2 additions & 2 deletions builtin/result.sk
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ enum Result<V>
case Ok(value: V)
case Fail(err: Error)

def self.fail<V>(msg: String) -> Fail<V>
Fail<V>.new(Error.new(msg))
def self.fail(msg: String) -> Fail
Fail.new(Error.new(msg))
end

def fail? -> Bool
Expand Down
13 changes: 13 additions & 0 deletions lib/shiika_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ pub struct EnumCase {
pub params: Vec<Param>,
}

impl EnumCase {
/// Returns true if the typaram name `name` appears in the type definition of any of `params`.
pub fn appears(&self, name: &str) -> bool {
self.params.iter().any(|param| param.typ.appears(name))
}
}

#[derive(Debug, PartialEq)]
pub struct AstMethodSignature {
pub name: MethodFirstname,
Expand Down Expand Up @@ -146,6 +153,12 @@ pub struct UnresolvedTypeName {
pub locs: LocationSpan,
}

impl UnresolvedTypeName {
pub fn appears(&self, name: &str) -> bool {
self.names.join("::") == name || self.args.iter().any(|arg| arg.appears(name))
}
}

#[derive(Debug, PartialEq, Clone)]
pub struct AstExpression {
pub body: AstExpressionBody,
Expand Down
44 changes: 19 additions & 25 deletions lib/skc_ast2hir/src/class_dict/indexing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,20 +306,15 @@ impl<'hir_maker> ClassDict<'hir_maker> {
) -> Result<()> {
let ivar_list = self._enum_case_ivars(namespace, typarams, case)?;
let fullname = case.name.add_namespace(&enum_fullname.0);
let superclass = enum_case_superclass(enum_fullname, typarams, case);
let (new_sig, initialize_sig) = enum_case_new_sig(&ivar_list, typarams, &fullname);
let (superclass, case_typarams) = enum_case_superclass(enum_fullname, typarams, case);
let (new_sig, initialize_sig) = enum_case_new_sig(&ivar_list, &case_typarams, &fullname);

let mut instance_methods = enum_case_getters(&fullname, &ivar_list);
instance_methods.insert(initialize_sig);

let case_typarams = if case.params.is_empty() {
Default::default()
} else {
typarams
};
self.add_new_class(
&fullname,
case_typarams,
&case_typarams,
superclass,
Default::default(),
Some(new_sig),
Expand Down Expand Up @@ -707,23 +702,22 @@ fn enum_case_superclass(
enum_fullname: &ClassFullname,
typarams: &[ty::TyParam],
case: &shiika_ast::EnumCase,
) -> Supertype {
if case.params.is_empty() {
// eg. Maybe::None : Maybe<Never>
let tyargs = typarams
.iter()
.map(|_| ty::raw("Never"))
.collect::<Vec<_>>();
Supertype::from_ty(LitTy::new(enum_fullname.0.clone(), tyargs, false))
} else {
// eg. Maybe::Some<out V> : Maybe<V>
let tyargs = typarams
.iter()
.enumerate()
.map(|(i, t)| ty::typaram_ref(&t.name, TyParamKind::Class, i).into_term_ty())
.collect::<Vec<_>>();
Supertype::from_ty(LitTy::new(enum_fullname.0.clone(), tyargs, false))
}
) -> (Supertype, Vec<ty::TyParam>) {
let mut case_typarams = vec![];
let tyargs = typarams
.iter()
.enumerate()
.map(|(i, t)| {
if case.appears(&t.name) {
case_typarams.push(t.clone());
ty::typaram_ref(&t.name, TyParamKind::Class, i).into_term_ty()
} else {
ty::raw("Never")
}
})
.collect::<Vec<_>>();
let supertype = Supertype::from_ty(LitTy::new(enum_fullname.0.clone(), tyargs, false));
(supertype, case_typarams)
}

/// Returns signature of `.new` and `#initialize` of an enum case
Expand Down
14 changes: 13 additions & 1 deletion lib/skc_ast2hir/src/class_dict/type_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,22 @@ fn index_enum(
let inner_namespace = namespace.add(firstname.0.clone());
for case in cases {
let case_fullname = inner_namespace.type_fullname(&case.name.0);
insert_class_and_metaclass(cindex, case_fullname, typarams.clone());
let case_typarams = enum_case_typarams(case, &typarams);
insert_class_and_metaclass(cindex, case_fullname, case_typarams);
}
}

fn enum_case_typarams(
case: &shiika_ast::EnumCase,
base_typarams: &[ty::TyParam],
) -> Vec<ty::TyParam> {
base_typarams
.iter()
.filter(|t| case.appears(&t.name))
.map(|t| t.clone())
.collect::<Vec<_>>()
}

fn insert_class_and_metaclass(
cindex: &mut TypeIndex,
name: TypeFullname,
Expand Down
2 changes: 1 addition & 1 deletion tests/sk/enum.sk
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ f(b)
unless a.value == 1; puts "ng Some#value"; end

let o = Ok<Int>.new(0)
let e = Fail<Int>.new(Error.new("fail"))
let e = Fail.new(Error.new("fail"))

# Class method of enum
enum EnumWithClassMethod
Expand Down
Loading