Files
mercury/compiler/mlds_to_cs_class.m
Zoltan Somogyi 304daa2057 Delete the mlds_class_kind type.
compiler/mlds.m:
    Delete the mlds_class_kind type, because

    - after the simplification of mlds_interface_ids, its mlds_interface
      function symbol became unused, and

    - after the deleting of that function symbol, it would have become
      a dummy type anyway.

    Delete mlds_class_kind fields from the mlds_class_defn and mlds_class_id
    types.

compiler/mlds_to_cs_class.m:
    Conform to the changes above.

    Inline two predicates, and simplify the resulting code.

compiler/ml_code_util.m:
compiler/ml_rename_classes.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_util.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_class.m:
compiler/mlds_to_c_type.m:
compiler/mlds_to_cs_type.m:
compiler/mlds_to_java_class.m:
compiler/mlds_to_java_type.m:
compiler/mlds_to_java_wrap.m:
compiler/mlds_to_target_util.m:
    Conform to the changes above.
2023-07-16 17:40:48 +02:00

349 lines
13 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2010-2012 The University of Melbourne.
% Copyright (C) 2013-2018 The Mercury team.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% Output class declarations and definitions in C#.
%
%---------------------------------------------------------------------------%
:- module ml_backend.mlds_to_cs_class.
:- interface.
:- import_module libs.
:- import_module libs.indent.
:- import_module ml_backend.mlds.
:- import_module ml_backend.mlds_to_cs_util.
:- import_module io.
%---------------------------------------------------------------------------%
:- pred output_class_defn_for_csharp(csharp_out_info::in,
io.text_output_stream::in, indent::in, mlds_class_defn::in,
io::di, io::uo) is det.
:- pred output_enum_class_defn_for_csharp(csharp_out_info::in,
io.text_output_stream::in, indent::in, mlds_enum_class_defn::in,
io::di, io::uo) is det.
:- pred output_env_defn_for_csharp(csharp_out_info::in,
io.text_output_stream::in, indent::in, mlds_env_defn::in,
io::di, io::uo) is det.
:- pred output_struct_defn_for_csharp(csharp_out_info::in,
io.text_output_stream::in, indent::in, mlds_struct_defn::in,
io::di, io::uo) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module hlds.
:- import_module hlds.hlds_module.
:- import_module libs.globals.
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module ml_backend.mlds_to_cs_data.
:- import_module ml_backend.mlds_to_cs_func.
:- import_module ml_backend.mlds_to_cs_name.
:- import_module ml_backend.mlds_to_cs_type.
:- import_module ml_backend.mlds_to_target_util.
:- import_module parse_tree.
:- import_module parse_tree.java_names.
:- import_module parse_tree.prog_data.
:- import_module bool.
:- import_module int.
:- import_module list.
:- import_module maybe.
:- import_module require.
:- import_module string.
:- import_module term.
%---------------------------------------------------------------------------%
output_class_defn_for_csharp(Info0, Stream, Indent, ClassDefn, !IO) :-
ClassDefn = mlds_class_defn(ClassName, ClassArity, _Context, Flags,
_Imports, Inherits, Implements, TypeParams,
MemberFields, MemberClasses, MemberMethods, Ctors),
expect(unify(MemberMethods, []), $pred, "MemberMethods != []"),
Info = Info0 ^ csoi_univ_tvars := TypeParams,
IndentStr = indent2_string(Indent),
Flags = mlds_class_decl_flags(Access, Overridability, Constness),
AccessPrefix = access_prefix_for_csharp(Access),
OverridePrefix = overrideability_prefix_for_csharp(Overridability),
ConstnessPrefix = constness_prefix_for_csharp(Constness),
ClassNameStr =
unqual_class_name_to_ll_string_for_csharp(ClassName, ClassArity),
OutputGenerics = Info ^ csoi_output_generics,
(
OutputGenerics = do_output_generics,
GenericTypeParamsStr = generic_tvars_to_string(TypeParams)
;
OutputGenerics = do_not_output_generics,
GenericTypeParamsStr = ""
),
io.format(Stream, "%s[System.Serializable]\n", [s(IndentStr)], !IO),
io.format(Stream, "%s%s%s%sclass %s%s\n",
[s(IndentStr), s(AccessPrefix),
s(OverridePrefix), s(ConstnessPrefix),
s(ClassNameStr), s(GenericTypeParamsStr)], !IO),
SuperClassNames = get_superclass_names(Info, Inherits, Implements),
(
SuperClassNames = []
;
SuperClassNames = [_ | _],
SuperClassesStr = string.join_list(", ", SuperClassNames),
io.format(Stream, "%s : %s\n",
[s(IndentStr), s(SuperClassesStr)], !IO)
),
io.format(Stream, "%s{\n", [s(IndentStr)], !IO),
Indent1 = Indent + 1,
list.foldl(
output_field_var_defn_for_csharp(Info, Stream, Indent1),
MemberFields, !IO),
list.foldl(
output_class_defn_for_csharp(Info, Stream, Indent1),
MemberClasses, !IO),
io.nl(Stream, !IO),
CtorsAux = oa_cname(ClassName, ClassArity),
list.foldl(
output_function_defn_for_csharp(Info, Stream, Indent1, CtorsAux),
Ctors, !IO),
io.format(Stream, "%s}\n\n", [s(IndentStr)], !IO).
output_enum_class_defn_for_csharp(Info0, Stream, Indent, EnumDefn, !IO) :-
EnumDefn = mlds_enum_class_defn(ClassName, ClassArity, _Context,
Inherits, Implements, TypeParams, _ValueField, EnumConsts, Ctors),
Info = Info0 ^ csoi_univ_tvars := TypeParams,
IndentStr = indent2_string(Indent),
AccessPrefix = access_prefix_for_csharp(class_public),
PerInstancePrefix = per_instance_prefix_for_csharp(per_instance),
OverridePrefix = overrideability_prefix_for_csharp(overridable),
ConstnessPrefix = constness_prefix_for_csharp(modifiable),
ClassNameStr =
unqual_class_name_to_ll_string_for_csharp(ClassName, ClassArity),
OutputGenerics = Info ^ csoi_output_generics,
(
OutputGenerics = do_output_generics,
GenericTypeParamsStr = generic_tvars_to_string(TypeParams)
;
OutputGenerics = do_not_output_generics,
GenericTypeParamsStr = ""
),
io.format(Stream, "%s[System.Serializable]\n", [s(IndentStr)], !IO),
io.format(Stream, "%s%s%s%s%senum %s%s\n",
[s(IndentStr), s(AccessPrefix), s(PerInstancePrefix),
s(OverridePrefix), s(ConstnessPrefix),
s(ClassNameStr), s(GenericTypeParamsStr)], !IO),
expect(unify(Inherits, inherits_nothing), $pred,
"Inherits != inherits_nothing"),
expect(unify(Implements, no), $pred, "Implements != no"),
io.format(Stream, "%s{\n", [s(IndentStr)], !IO),
Indent1 = Indent + 1,
Indent2Str = indent2_string(Indent1),
list.foldl(output_enum_constant_for_csharp(Info, Stream, Indent2Str),
EnumConsts, !IO),
CtorsAux = oa_cname(ClassName, ClassArity),
list.foldl(
output_function_defn_for_csharp(Info, Stream, Indent1, CtorsAux),
Ctors, !IO),
io.format(Stream, "%s}\n\n", [s(IndentStr)], !IO).
output_env_defn_for_csharp(Info, Stream, Indent, EnvDefn, !IO) :-
EnvDefn = mlds_env_defn(EnvName, _Context, MemberFields),
IndentStr = indent2_string(Indent),
Indent1 = Indent + 1,
Indent1Str = indent2_string(Indent1),
EnvNameStr = unqual_class_name_to_ll_string_for_csharp(EnvName, 0),
EnvTypeStr = type_to_string_for_csharp(Info, mlds_generic_env_ptr_type),
io.format(Stream, "%s[System.Serializable]\n", [s(IndentStr)], !IO),
io.format(Stream, "%sprivate class %s\n",
[s(IndentStr), s(EnvNameStr)], !IO),
io.format(Stream, "%s: %s\n", [s(Indent1Str), s(EnvTypeStr)], !IO),
io.format(Stream, "%s{\n", [s(IndentStr)], !IO),
list.foldl(
output_field_var_defn_for_csharp(Info, Stream, Indent1),
MemberFields, !IO),
io.format(Stream, "%s}\n\n", [s(IndentStr)], !IO).
output_struct_defn_for_csharp(Info, Stream, Indent, StructDefn, !IO) :-
StructDefn = mlds_struct_defn(StructName, _Context,
MemberFields, MaybeCtor),
(
MaybeCtor = no,
unexpected($pred, "MaybeCtor = no")
;
MaybeCtor = yes(Ctor)
),
Indent1 = Indent + 1,
IndentStr = indent2_string(Indent),
StructNameStr = unqual_class_name_to_ll_string_for_csharp(StructName, 0),
io.format(Stream, "%sprivate struct %s\n",
[s(IndentStr), s(StructNameStr)], !IO),
io.format(Stream, "%s{\n", [s(IndentStr)], !IO),
list.foldl(
output_field_var_defn_for_csharp(Info, Stream, Indent1),
MemberFields, !IO),
io.nl(Stream, !IO),
output_function_defn_for_csharp(Info, Stream, Indent1,
oa_cname(StructName, 0), Ctor, !IO),
io.format(Stream, "%s}\n\n", [s(IndentStr)], !IO).
%---------------------------------------------------------------------------%
% Output superclass that this class extends and interfaces implemented.
% C# does not support multiple inheritance, so more than one superclass
% is an error.
% XXX This predicate does not output anything.
%
:- func get_superclass_names(csharp_out_info,
mlds_class_inherits, list(mlds_interface_id)) = list(string).
get_superclass_names(Info, Inherits, Interfaces) = Supers :-
Supers0 = list.map(interface_to_string_for_csharp, Interfaces),
(
Inherits = inherits_nothing,
Supers = Supers0
;
Inherits = inherits_class(BaseClassId),
BaseClassType = mlds_class_type(BaseClassId),
BaseClassTypeName = type_to_string_for_csharp(Info, BaseClassType),
Supers = [BaseClassTypeName | Supers0]
).
:- func interface_to_string_for_csharp(mlds_interface_id) = string.
interface_to_string_for_csharp(InterfaceId) = String :-
InterfaceId = mlds_interface_id(ModuleName, ClassName),
SymName = mlds_module_name_to_sym_name(ModuleName),
mangle_sym_name_for_csharp(SymName, module_qual, ".", ModuleNameStr),
% Check if the interface is one of the ones in the runtime system.
% If it is, we don't need to output the arity.
( if interface_is_special_for_csharp(ClassName) then
String = string.format("%s.%s", [s(ModuleNameStr), s(ClassName)])
else
Arity = 0,
String = string.format("%s.%s%d",
[s(ModuleNameStr), s(ClassName), i(Arity)])
).
% Succeeds iff a given string matches the unqualified interface name
% of a interface in Mercury's C# runtime system.
%
:- pred interface_is_special_for_csharp(string::in) is semidet.
interface_is_special_for_csharp("MercuryType").
%---------------------------------------------------------------------------%
:- pred output_field_var_defn_for_csharp(csharp_out_info::in,
io.text_output_stream::in, indent::in, mlds_field_var_defn::in,
io::di, io::uo) is det.
output_field_var_defn_for_csharp(Info, Stream, Indent, FieldVarDefn, !IO) :-
FieldVarDefn = mlds_field_var_defn(FieldVarName, _Context, Flags,
Type, Initializer, _),
IndentStr = indent2_string(Indent),
Flags = mlds_field_var_decl_flags(PerInstance, Constness),
AccessPrefix = "public ",
PerInstancePrefix = per_instance_prefix_for_csharp(PerInstance),
ConstnessPrefix = constness_prefix_for_csharp(Constness),
TypeStr = type_to_string_for_csharp(Info, Type),
FieldVarNameStr = field_var_name_to_ll_string_for_csharp(FieldVarName),
io.format(Stream, "%s%s%s%s%s %s",
[s(IndentStr), s(AccessPrefix), s(PerInstancePrefix),
s(ConstnessPrefix), s(TypeStr), s(FieldVarNameStr)], !IO),
output_initializer_for_csharp(Info, Stream, oa_none, Indent + 1,
Type, Initializer, ";", !IO).
%---------------------------------------------------------------------------%
:- pred output_enum_constant_for_csharp(csharp_out_info::in,
io.text_output_stream::in, string::in, mlds_enum_const_defn::in,
io::di, io::uo) is det.
output_enum_constant_for_csharp(Info, Stream, IndentStr, EnumConstDefn, !IO) :-
EnumConstDefn = mlds_enum_const_defn(VarName, _Context, EnumConst),
VarNameStr = field_var_name_to_ll_string_for_csharp(VarName),
(
EnumConst = mlds_enum_const_uint(EnumUInt),
io.format(Stream, "%s%s = %u,\n",
[s(IndentStr), s(VarNameStr), u(EnumUInt)], !IO)
;
EnumConst = mlds_enum_const_foreign(Lang, EnumNameStr, Type),
% The name might require mangling.
expect(unify(Lang, lang_csharp), $pred, "Lang != lang_csharp"),
TypeStr = type_to_string_for_csharp(Info, Type),
io.format(Stream, "%s%s = (%s) %s,\n",
[s(IndentStr), s(VarNameStr), s(TypeStr), s(EnumNameStr)], !IO)
).
%---------------------------------------------------------------------------%
%
% Every prefix string that is not empty should end with a space.
%
:- func access_prefix_for_csharp(class_access) = string.
access_prefix_for_csharp(Access) = AccessPrefix :-
(
Access = class_public,
AccessPrefix = "public "
;
Access = class_private,
AccessPrefix = "private "
).
:- func per_instance_prefix_for_csharp(per_instance) = string.
per_instance_prefix_for_csharp(PerInstance) = PerInstancePrefix :-
(
PerInstance = per_instance,
PerInstancePrefix = ""
;
PerInstance = one_copy,
PerInstancePrefix = "static "
).
:- func overrideability_prefix_for_csharp(overridability) = string.
overrideability_prefix_for_csharp(Overridability) = OverridePrefix :-
(
Overridability = sealed,
OverridePrefix = "sealed "
;
Overridability = overridable,
OverridePrefix = ""
).
:- func constness_prefix_for_csharp(constness) = string.
constness_prefix_for_csharp(Constness) = ConstnessPrefix :-
(
Constness = const,
ConstnessPrefix = "readonly "
;
Constness = modifiable,
ConstnessPrefix = ""
).
%---------------------------------------------------------------------------%
:- end_module ml_backend.mlds_to_cs_class.
%---------------------------------------------------------------------------%