mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-15 13:55:07 +00:00
Estimated hours taken: 2.5 Branches: main Various fixes for --grade il. compiler/mlds_to_il.m: Only add "mercury_code" suffixes to a module name if it is necessary. This allows us to omit "mercury_code" when generating field references correctly for classes that are generated for user-defined types when using --high-level-data. Generate code for new_object using the class-based approach (as opposed to the low-level data array based approach). Fix the code for generating fieldrefs so that we use the module name in the named_field to generate a classname. compiler/mlds_to_csharp.m: compiler/mlds_to_mcpp.m: Minor changes to handle the new interface to mlds_module_name_to_class_name.
641 lines
21 KiB
Mathematica
641 lines
21 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2001 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% mlds_to_mcpp - Generate Managed C++ code for the foreign language
|
|
% interface.
|
|
% Main author: trd.
|
|
%
|
|
% To-do:
|
|
%
|
|
% [ ] Fix the output of contexts so that the context gets reset after the
|
|
% user code.
|
|
% [ ] Output contexts in more places, currently we don't do all of them.
|
|
%
|
|
% This code converts the MLDS representation of foreign language code into MC++
|
|
|
|
:- module mlds_to_mcpp.
|
|
:- interface.
|
|
|
|
:- import_module mlds.
|
|
:- import_module io.
|
|
|
|
% Convert the MLDS to MC++ and write it to a file.
|
|
:- pred mlds_to_mcpp__output_mcpp_code(mlds, io__state, io__state).
|
|
:- mode mlds_to_mcpp__output_mcpp_code(in, di, uo) is det.
|
|
|
|
% Print the header comments of the output module
|
|
:- pred output_src_start(mercury_module_name, io__state, io__state).
|
|
:- mode output_src_start(in, di, uo) is det.
|
|
|
|
% Print the footer commments of the output module
|
|
:- pred output_src_end(mercury_module_name, io__state, io__state).
|
|
:- mode output_src_end(in, di, uo) is det.
|
|
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module globals, options, passes_aux.
|
|
:- import_module builtin_ops, c_util, modules, tree.
|
|
:- import_module hlds_pred. % for `pred_proc_id'.
|
|
:- import_module prog_data, prog_out, llds_out.
|
|
:- import_module rtti, type_util, error_util.
|
|
|
|
:- import_module ilds, ilasm, il_peephole.
|
|
:- import_module ml_util, ml_code_util.
|
|
:- import_module mlds_to_c. /* to output C code for .cpp files */
|
|
:- use_module llds. /* for user_c_code */
|
|
|
|
:- import_module bool, int, map, string, list, assoc_list, term, std_util.
|
|
:- import_module library, require, counter.
|
|
|
|
:- import_module mlds_to_il.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
output_mcpp_code(MLDS) -->
|
|
{ MLDS = mlds(ModuleName, _ForeignCode, _Imports, _Defns) },
|
|
output_src_start(ModuleName),
|
|
io__nl,
|
|
|
|
generate_mcplusplus_code(MLDS),
|
|
|
|
output_src_end(ModuleName).
|
|
|
|
output_src_start(ModuleName) -->
|
|
{ library__version(Version) },
|
|
{ prog_out__sym_name_to_string(ModuleName, ModuleNameStr) },
|
|
io__write_strings(
|
|
["//\n// Automatically generated from `",
|
|
ModuleNameStr,
|
|
".m' by the\n",
|
|
"// Mercury compiler, version ",
|
|
Version,
|
|
".\n",
|
|
"// Do not edit.\n",
|
|
"\n\n"]).
|
|
|
|
output_src_end(ModuleName) -->
|
|
io__write_string("// End of module: "),
|
|
prog_out__write_sym_name(ModuleName),
|
|
io__write_string(". \n").
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- pred generate_mcplusplus_code(mlds, io__state, io__state).
|
|
:- mode generate_mcplusplus_code(in, di, uo) is det.
|
|
generate_mcplusplus_code(MLDS) -->
|
|
|
|
{ MLDS = mlds(ModuleName, ForeignCode, _Imports, Defns) },
|
|
{ prog_out__sym_name_to_string(ModuleName, ModuleNameStr) },
|
|
{ ClassName = mlds_module_name_to_class_name(
|
|
mercury_module_name_to_mlds(ModuleName), yes) },
|
|
|
|
io__nl,
|
|
io__write_strings([
|
|
"#using <mscorlib.dll>\n",
|
|
"#include ""mercury_mcpp.h""\n",
|
|
"#using ""mercury_mcpp.dll""\n",
|
|
"#using ""mercury_il.dll""\n",
|
|
"#using """, ModuleNameStr, ".dll""\n",
|
|
|
|
% XXX We have to use the mercury namespace, as
|
|
% llds_out still generates some of the code used in the
|
|
% MC++ interface, and so it doesn't have "mercury::"
|
|
% namespace qualifiers.
|
|
"using namespace mercury;\n",
|
|
|
|
% XXX this supresses problems caused by references to
|
|
% float. If you don't do this, you'll get link errors.
|
|
% Revisit this when the .NET implementation has matured.
|
|
"extern ""C"" int _fltused=0;\n",
|
|
"\n"]),
|
|
|
|
{ Namespace0 = get_class_namespace(ClassName) },
|
|
{ list__reverse(Namespace0) = [Head | Tail] ->
|
|
Namespace = list__reverse([Head ++ "__cpp_code" | Tail])
|
|
;
|
|
Namespace = Namespace0
|
|
},
|
|
|
|
io__write_list(Namespace, "\n",
|
|
(pred(N::in, di, uo) is det -->
|
|
io__format("namespace %s {", [s(N)])
|
|
)),
|
|
|
|
generate_foreign_header_code(mercury_module_name_to_mlds(ModuleName),
|
|
ForeignCode),
|
|
|
|
io__write_strings([
|
|
"\n__gc public class mercury_code",
|
|
"{\n",
|
|
"public:\n"]),
|
|
|
|
|
|
% Output the contents of foreign_code declarations.
|
|
generate_foreign_code(mercury_module_name_to_mlds(ModuleName),
|
|
ForeignCode),
|
|
|
|
% Output the contents of foreign_proc declarations.
|
|
% Put each one inside a method.
|
|
list__foldl(generate_method_mcpp_code(
|
|
mercury_module_name_to_mlds(ModuleName)), Defns),
|
|
|
|
io__write_string("};\n"),
|
|
|
|
% Close the namespace braces.
|
|
io__write_list(Namespace, "\n",
|
|
(pred(_N::in, di, uo) is det -->
|
|
io__write_string("}")
|
|
)),
|
|
|
|
|
|
io__nl.
|
|
|
|
|
|
% XXX we don't handle export decls.
|
|
:- pred generate_foreign_code(mlds_module_name, mlds__foreign_code,
|
|
io__state, io__state).
|
|
:- mode generate_foreign_code(in, in, di, uo) is det.
|
|
generate_foreign_code(_ModuleName,
|
|
mlds__foreign_code(_RevHeaderCode, RevBodyCode,
|
|
_ExportDefns)) -->
|
|
{ BodyCode = list__reverse(RevBodyCode) },
|
|
io__write_list(BodyCode, "\n",
|
|
(pred(llds__user_foreign_code(Lang, Code, Context)::in,
|
|
di, uo) is det -->
|
|
( { Lang = managed_cplusplus } ->
|
|
mlds_to_c__output_context(mlds__make_context(
|
|
Context)),
|
|
io__write_string(Code)
|
|
;
|
|
% ignore it if it isn't MC++
|
|
[]
|
|
)
|
|
)).
|
|
|
|
% XXX we don't handle export decls.
|
|
:- pred generate_foreign_header_code(mlds_module_name, mlds__foreign_code,
|
|
io__state, io__state).
|
|
:- mode generate_foreign_header_code(in, in, di, uo) is det.
|
|
generate_foreign_header_code(_ModuleName,
|
|
mlds__foreign_code(RevHeaderCode, _RevBodyCode,
|
|
_ExportDefns)) -->
|
|
{ HeaderCode = list__reverse(RevHeaderCode) },
|
|
io__write_list(HeaderCode, "\n",
|
|
(pred(llds__foreign_decl_code(Lang, Code, _Context)::in,
|
|
di, uo) is det -->
|
|
( { Lang = managed_cplusplus } ->
|
|
io__write_string(Code)
|
|
;
|
|
% ignore it if it isn't MC++
|
|
[]
|
|
)
|
|
)).
|
|
|
|
:- pred generate_method_mcpp_code(mlds_module_name, mlds__defn,
|
|
io__state, io__state).
|
|
:- mode generate_method_mcpp_code(in, in, di, uo) is det.
|
|
|
|
% XXX we don't handle export
|
|
generate_method_mcpp_code(_, defn(export(_), _, _, _)) --> [].
|
|
generate_method_mcpp_code(_, defn(data(_), _, _, _)) --> [].
|
|
generate_method_mcpp_code(_, defn(type(_, _), _, _, _)) --> [].
|
|
generate_method_mcpp_code(ModuleName,
|
|
defn(function(PredLabel, ProcId, MaybeSeqNum, _PredId),
|
|
_Context, _DeclFlags, Entity)) -->
|
|
(
|
|
{ Entity = mlds__function(_, Params, yes(Statement)) },
|
|
(
|
|
{ has_inline_target_code_statement(Statement) }
|
|
;
|
|
{ has_foreign_languages(Statement, Langs) },
|
|
{ list__member(managed_cplusplus, Langs) }
|
|
)
|
|
->
|
|
globals__io_lookup_bool_option(highlevel_data, HighLevelData),
|
|
{ DataRep = il_data_rep(HighLevelData) },
|
|
{ ILSignature = params_to_il_signature(DataRep, ModuleName,
|
|
Params) },
|
|
{ predlabel_to_id(PredLabel, ProcId, MaybeSeqNum, Id) },
|
|
io__write_string("static "),
|
|
{ ILSignature = signature(_CallConv, ReturnType, ILArgs) },
|
|
write_il_ret_type_as_managed_cpp_type(ReturnType),
|
|
|
|
io__write_string(" "),
|
|
|
|
io__write_string(Id),
|
|
io__write_string("("),
|
|
io__write_list(ILArgs, ", ", write_il_arg_as_managed_cpp_type),
|
|
io__write_string(")"),
|
|
io__nl,
|
|
|
|
io__write_string("{\n"),
|
|
write_managed_cpp_statement(Statement),
|
|
io__write_string("}\n")
|
|
;
|
|
[]
|
|
).
|
|
|
|
% In order to implement the C interface, you need to
|
|
% implement:
|
|
% call/6 (for calling continuations)
|
|
% return/1 (for returning succeeded)
|
|
% block/2 (because the code is wrapped in a block, and
|
|
% because local variables are declared for
|
|
% "succeeded")
|
|
% target_code/2 (where the actual code is put)
|
|
% assign/2 (to assign to the environment)
|
|
% newobj/7 (to create an environment)
|
|
%
|
|
% Unfortunately currently some of the "raw_target_code" is
|
|
% C specific and won't translate well into managed C++.
|
|
% Probably the best solution to this is to introduce some new
|
|
% code components.
|
|
%
|
|
% Note that for the managed C++ backend there is a problem.
|
|
% #import doesn't import classes in namespaces properly (yet), so we
|
|
% can't #import .dlls that define environments. So even if we
|
|
% implement newobj/7, we will get errors.
|
|
% The work-around for this is to make sure ml_elim_nested
|
|
% doesn't introduce environments where they aren't needed,
|
|
% so we don't generally have to allocate anything but the local
|
|
% environment (which is defined locally).
|
|
|
|
:- pred write_managed_cpp_statement(mlds__statement,
|
|
io__state, io__state).
|
|
:- mode write_managed_cpp_statement(in, di, uo) is det.
|
|
write_managed_cpp_statement(Statement) -->
|
|
globals__io_lookup_bool_option(highlevel_data, HighLevelData),
|
|
(
|
|
% XXX this ignores the language target.
|
|
{ Statement = statement(atomic(inline_target_code(
|
|
_Lang, CodeComponents)), _) }
|
|
->
|
|
io__write_list(CodeComponents, "\n",
|
|
write_managed_cpp_code_component)
|
|
;
|
|
{ Statement = statement(block(Defns, Statements), _) }
|
|
->
|
|
io__write_list(Defns, "", write_managed_cpp_defn_decl),
|
|
io__write_string("{\n"),
|
|
io__write_list(Statements, "", write_managed_cpp_statement),
|
|
io__write_string("}\n")
|
|
;
|
|
{ Statement = statement(
|
|
call(_Sig, Function, _This, Args, Results, _IsTail),
|
|
_Context) }
|
|
->
|
|
% XXX this doesn't work for continuations because
|
|
% a) I don't know how to call a function pointer in
|
|
% managed C++.
|
|
% b) Function pointers are represented as integers,
|
|
% and we don't do any casting for them.
|
|
% The nondet interface might need to be reworked in
|
|
% this case.
|
|
% The workaround at the moment is to make sure we don't
|
|
% actually generate calls to continuations in managed
|
|
% C++, instead we generate a nested function that is
|
|
% implemented in IL that does the continuation call, and
|
|
% just call the nested function instead. Sneaky, eh?
|
|
( { Results = [] } ->
|
|
[]
|
|
; { Results = [Lval] } ->
|
|
write_managed_cpp_lval(Lval),
|
|
io__write_string(" = ")
|
|
;
|
|
{ sorry(this_file, "multiple return values") }
|
|
),
|
|
write_managed_cpp_rval(Function),
|
|
io__write_string("("),
|
|
io__write_list(Args, ", ", write_managed_cpp_rval),
|
|
io__write_string(");\n")
|
|
;
|
|
{ Statement = statement(return(Rvals), _) }
|
|
->
|
|
( { Rvals = [Rval] } ->
|
|
io__write_string("return "),
|
|
write_managed_cpp_rval(Rval),
|
|
io__write_string(";\n")
|
|
;
|
|
{ sorry(this_file, "multiple return values") }
|
|
)
|
|
;
|
|
{ Statement = statement(atomic(assign(Lval, Rval)), _) }
|
|
->
|
|
write_managed_cpp_lval(Lval),
|
|
io__write_string(" = "),
|
|
write_managed_cpp_rval(Rval),
|
|
io__write_string(";\n")
|
|
;
|
|
|
|
% XXX This is not fully implemented
|
|
{ Statement = statement(atomic(
|
|
new_object(Target, _MaybeTag, Type, _MaybeSize,
|
|
_MaybeCtorName, _Args, _ArgTypes)), _) },
|
|
{ ClassName = mlds_type_to_ilds_class_name(
|
|
il_data_rep(HighLevelData), Type) }
|
|
->
|
|
write_managed_cpp_lval(Target),
|
|
io__write_string(" = new "),
|
|
write_managed_cpp_class_name(ClassName),
|
|
io__write_string("();\n")
|
|
;
|
|
{ Statement = statement(atomic(Atomic), _) }
|
|
->
|
|
{ functor(Atomic, AtomicFunctor, Arity) },
|
|
io__write_string("// unimplemented: atomic "),
|
|
io__write_string(AtomicFunctor),
|
|
io__write_string("/"),
|
|
io__write(Arity),
|
|
io__nl
|
|
|
|
;
|
|
{ Statement = statement(S, _) },
|
|
{ functor(S, SFunctor, Arity) },
|
|
io__write_string("// unimplemented: "),
|
|
io__write_string(SFunctor),
|
|
io__write_string("/"),
|
|
io__write(Arity),
|
|
io__nl
|
|
).
|
|
|
|
% XXX we ignore contexts
|
|
:- pred write_managed_cpp_code_component(mlds__target_code_component,
|
|
io__state, io__state).
|
|
:- mode write_managed_cpp_code_component(in, di, uo) is det.
|
|
write_managed_cpp_code_component(user_target_code(Code, _MaybeContext)) -->
|
|
io__write_string(Code).
|
|
write_managed_cpp_code_component(raw_target_code(Code)) -->
|
|
io__write_string(Code).
|
|
% XXX we don't handle name yet.
|
|
write_managed_cpp_code_component(name(_)) --> [].
|
|
write_managed_cpp_code_component(target_code_input(Rval)) -->
|
|
write_managed_cpp_rval(Rval).
|
|
write_managed_cpp_code_component(target_code_output(Lval)) -->
|
|
write_managed_cpp_lval(Lval).
|
|
|
|
:- pred write_managed_cpp_rval(mlds__rval, io__state, io__state).
|
|
:- mode write_managed_cpp_rval(in, di, uo) is det.
|
|
write_managed_cpp_rval(lval(Lval)) -->
|
|
write_managed_cpp_lval(Lval).
|
|
write_managed_cpp_rval(mkword(_Tag, _Rval)) -->
|
|
io__write_string(" /* mkword rval -- unimplemented */ ").
|
|
write_managed_cpp_rval(const(RvalConst)) -->
|
|
write_managed_cpp_rval_const(RvalConst).
|
|
write_managed_cpp_rval(unop(Unop, Rval)) -->
|
|
(
|
|
{ Unop = std_unop(StdUnop) },
|
|
{ c_util__unary_prefix_op(StdUnop, UnopStr) }
|
|
->
|
|
io__write_string(UnopStr),
|
|
io__write_string("("),
|
|
write_managed_cpp_rval(Rval),
|
|
io__write_string(")")
|
|
;
|
|
{ Unop = cast(Type) }
|
|
->
|
|
io__write_string("("),
|
|
write_managed_cpp_type(Type),
|
|
io__write_string(") "),
|
|
write_managed_cpp_rval(Rval)
|
|
;
|
|
io__write_string(" /* XXX box or unbox unop -- unimplemented */ "),
|
|
write_managed_cpp_rval(Rval)
|
|
).
|
|
write_managed_cpp_rval(binop(Binop, Rval1, Rval2)) -->
|
|
(
|
|
{ c_util__binary_infix_op(Binop, BinopStr) }
|
|
->
|
|
io__write_string("("),
|
|
write_managed_cpp_rval(Rval1),
|
|
io__write_string(") "),
|
|
io__write_string(BinopStr),
|
|
io__write_string(" ("),
|
|
write_managed_cpp_rval(Rval2),
|
|
io__write_string(")")
|
|
;
|
|
io__write_string(" /* binop rval -- unimplemented */ ")
|
|
).
|
|
|
|
write_managed_cpp_rval(mem_addr(_)) -->
|
|
io__write_string(" /* mem_addr rval -- unimplemented */ ").
|
|
|
|
:- pred write_managed_cpp_rval_const(mlds__rval_const, io__state, io__state).
|
|
:- mode write_managed_cpp_rval_const(in, di, uo) is det.
|
|
write_managed_cpp_rval_const(true) --> io__write_string("1").
|
|
write_managed_cpp_rval_const(false) --> io__write_string("0").
|
|
write_managed_cpp_rval_const(int_const(I)) --> io__write_int(I).
|
|
write_managed_cpp_rval_const(float_const(F)) --> io__write_float(F).
|
|
% XXX We don't quote this correctly.
|
|
write_managed_cpp_rval_const(string_const(S)) -->
|
|
io__write_string(""""),
|
|
io__write_string(S),
|
|
io__write_string("""").
|
|
write_managed_cpp_rval_const(multi_string_const(_L, _S)) -->
|
|
io__write_string(" /* multi_string_const rval -- unimplemented */ ").
|
|
write_managed_cpp_rval_const(code_addr_const(CodeAddrConst)) -->
|
|
(
|
|
{ CodeAddrConst = proc(ProcLabel, _FuncSignature) },
|
|
{ mangle_mlds_proc_label(ProcLabel, no, ClassName,
|
|
MangledName) },
|
|
write_managed_cpp_class_name(ClassName),
|
|
io__write_string("::"),
|
|
io__write_string(MangledName)
|
|
;
|
|
{ CodeAddrConst = internal(ProcLabel, SeqNum,
|
|
_FuncSignature) },
|
|
{ mangle_mlds_proc_label(ProcLabel, yes(SeqNum), ClassName,
|
|
MangledName) },
|
|
write_managed_cpp_class_name(ClassName),
|
|
io__write_string("::"),
|
|
io__write_string(MangledName)
|
|
).
|
|
|
|
|
|
|
|
write_managed_cpp_rval_const(data_addr_const(_)) -->
|
|
io__write_string(" /* data_addr_const rval -- unimplemented */ ").
|
|
write_managed_cpp_rval_const(null(_)) -->
|
|
io__write_string("0").
|
|
|
|
:- pred write_managed_cpp_lval(mlds__lval, io__state, io__state).
|
|
:- mode write_managed_cpp_lval(in, di, uo) is det.
|
|
write_managed_cpp_lval(field(_, Rval, named_field(FieldId, _Type), _, _)) -->
|
|
io__write_string("("),
|
|
write_managed_cpp_rval(Rval),
|
|
io__write_string(")"),
|
|
io__write_string("->"),
|
|
{ FieldId = qual(_, FieldName) },
|
|
io__write_string(FieldName).
|
|
|
|
write_managed_cpp_lval(field(_, Rval, offset(OffSet), _, _)) -->
|
|
io__write_string("("),
|
|
write_managed_cpp_rval(Rval),
|
|
io__write_string(")"),
|
|
io__write_string("["),
|
|
write_managed_cpp_rval(OffSet),
|
|
io__write_string("]").
|
|
|
|
write_managed_cpp_lval(mem_ref(Rval, _)) -->
|
|
io__write_string("*"),
|
|
write_managed_cpp_rval(Rval).
|
|
write_managed_cpp_lval(var(Var, _VarType)) -->
|
|
{ mangle_mlds_var(Var, Id) },
|
|
io__write_string(Id).
|
|
|
|
:- pred write_managed_cpp_defn_decl(mlds__defn, io__state, io__state).
|
|
:- mode write_managed_cpp_defn_decl(in, di, uo) is det.
|
|
write_managed_cpp_defn_decl(Defn) -->
|
|
{ Defn = mlds__defn(Name, _Context, _Flags, DefnBody) },
|
|
( { DefnBody = data(Type, _Initializer) },
|
|
{ Name = data(var(VarName)) }
|
|
->
|
|
write_managed_cpp_type(Type),
|
|
io__write_string(" "),
|
|
write_mlds_varname(VarName),
|
|
io__write_string(";\n")
|
|
;
|
|
io__write_string("// unimplemented defn decl\n")
|
|
).
|
|
|
|
:- pred write_mlds_varname(mlds__var_name, io__state, io__state).
|
|
:- mode write_mlds_varname(in, di, uo) is det.
|
|
write_mlds_varname(var_name(Var, yes(Num))) -->
|
|
io__format("%s_%d", [s(Var), i(Num)]).
|
|
write_mlds_varname(var_name(Var, no)) -->
|
|
io__write_string(Var).
|
|
|
|
:- pred write_managed_cpp_type(mlds__type, io__state, io__state).
|
|
:- mode write_managed_cpp_type(in, di, uo) is det.
|
|
write_managed_cpp_type(Type) -->
|
|
globals__io_lookup_bool_option(highlevel_data, HighLevelData),
|
|
{ DataRep = il_data_rep(HighLevelData) },
|
|
write_il_type_as_managed_cpp_type(
|
|
mlds_type_to_ilds_type(DataRep, Type)).
|
|
|
|
% XXX this could be more efficient
|
|
:- pred has_inline_target_code_statement(mlds__statement).
|
|
:- mode has_inline_target_code_statement(in) is semidet.
|
|
has_inline_target_code_statement(Statement) :-
|
|
GetTargetCode = (pred(SubStatement::out) is nondet :-
|
|
statement_contains_statement(Statement, SubStatement),
|
|
SubStatement = statement(atomic(inline_target_code(_, _)), _)
|
|
),
|
|
solutions(GetTargetCode, [_|_]).
|
|
|
|
|
|
|
|
:- pred write_il_ret_type_as_managed_cpp_type(ret_type::in,
|
|
io__state::di, io__state::uo) is det.
|
|
write_il_ret_type_as_managed_cpp_type(void) --> io__write_string("void").
|
|
write_il_ret_type_as_managed_cpp_type(simple_type(T)) -->
|
|
write_il_simple_type_as_managed_cpp_type(T).
|
|
|
|
% XXX need to revisit this and choose types appropriately
|
|
:- pred write_il_simple_type_as_managed_cpp_type(simple_type::in,
|
|
io__state::di, io__state::uo) is det.
|
|
write_il_simple_type_as_managed_cpp_type(int8) -->
|
|
io__write_string("mercury::MR_Integer8").
|
|
write_il_simple_type_as_managed_cpp_type(int16) -->
|
|
io__write_string("mercury::MR_Integer16").
|
|
write_il_simple_type_as_managed_cpp_type(int32) -->
|
|
io__write_string("mercury::MR_Integer").
|
|
write_il_simple_type_as_managed_cpp_type(int64) -->
|
|
io__write_string("mercury::MR_Integer64").
|
|
write_il_simple_type_as_managed_cpp_type(uint8) -->
|
|
io__write_string("unsigned int").
|
|
write_il_simple_type_as_managed_cpp_type(uint16) -->
|
|
io__write_string("unsigned int").
|
|
write_il_simple_type_as_managed_cpp_type(uint32) -->
|
|
io__write_string("unsigned int").
|
|
write_il_simple_type_as_managed_cpp_type(uint64) -->
|
|
io__write_string("unsigned int").
|
|
write_il_simple_type_as_managed_cpp_type(native_int) -->
|
|
io__write_string("mercury::MR_Integer").
|
|
write_il_simple_type_as_managed_cpp_type(native_uint) -->
|
|
io__write_string("unsigned int").
|
|
write_il_simple_type_as_managed_cpp_type(float32) -->
|
|
io__write_string("float").
|
|
write_il_simple_type_as_managed_cpp_type(float64) -->
|
|
io__write_string("mercury::MR_Float").
|
|
write_il_simple_type_as_managed_cpp_type(native_float) -->
|
|
io__write_string("mercury::MR_Float").
|
|
write_il_simple_type_as_managed_cpp_type(bool) -->
|
|
io__write_string("mercury::MR_Integer").
|
|
write_il_simple_type_as_managed_cpp_type(char) -->
|
|
io__write_string("mercury::MR_Char").
|
|
write_il_simple_type_as_managed_cpp_type(refany) -->
|
|
io__write_string("mercury::MR_RefAny").
|
|
write_il_simple_type_as_managed_cpp_type(class(ClassName)) -->
|
|
( { ClassName = il_generic_class_name } ->
|
|
io__write_string("mercury::MR_Box")
|
|
;
|
|
io__write_string("public class "),
|
|
write_managed_cpp_class_name(ClassName),
|
|
io__write_string(" *")
|
|
).
|
|
% XXX this is not the right syntax
|
|
write_il_simple_type_as_managed_cpp_type(value_class(ClassName)) -->
|
|
io__write_string("value class "),
|
|
write_managed_cpp_class_name(ClassName),
|
|
io__write_string(" *").
|
|
% XXX this is not the right syntax
|
|
write_il_simple_type_as_managed_cpp_type(interface(ClassName)) -->
|
|
io__write_string("interface "),
|
|
write_managed_cpp_class_name(ClassName),
|
|
io__write_string(" *").
|
|
% XXX this needs more work
|
|
write_il_simple_type_as_managed_cpp_type('[]'(_Type, _Bounds)) -->
|
|
io__write_string("mercury::MR_Word").
|
|
write_il_simple_type_as_managed_cpp_type('&'(Type)) -->
|
|
io__write_string("MR_Ref("),
|
|
write_il_type_as_managed_cpp_type(Type),
|
|
io__write_string(")").
|
|
write_il_simple_type_as_managed_cpp_type('*'(Type)) -->
|
|
write_il_type_as_managed_cpp_type(Type),
|
|
io__write_string(" *").
|
|
|
|
:- pred write_managed_cpp_class_name(structured_name::in, io__state::di,
|
|
io__state::uo) is det.
|
|
write_managed_cpp_class_name(structured_name(_Assembly, DottedName)) -->
|
|
io__write_list(DottedName, "::", io__write_string).
|
|
|
|
:- pred write_il_type_as_managed_cpp_type(ilds__type::in,
|
|
io__state::di, io__state::uo) is det.
|
|
write_il_type_as_managed_cpp_type(ilds__type(Modifiers, SimpleType)) -->
|
|
io__write_list(Modifiers, " ",
|
|
write_il_type_modifier_as_managed_cpp_type),
|
|
write_il_simple_type_as_managed_cpp_type(SimpleType).
|
|
|
|
:- pred write_il_type_modifier_as_managed_cpp_type(ilds__type_modifier::in,
|
|
io__state::di, io__state::uo) is det.
|
|
write_il_type_modifier_as_managed_cpp_type(const) -->
|
|
io__write_string("const").
|
|
write_il_type_modifier_as_managed_cpp_type(readonly) -->
|
|
io__write_string("readonly").
|
|
write_il_type_modifier_as_managed_cpp_type(volatile) -->
|
|
io__write_string("volatile").
|
|
|
|
:- pred write_il_arg_as_managed_cpp_type(pair(ilds__type,
|
|
maybe(ilds__id))::in, io__state::di, io__state::uo) is det.
|
|
write_il_arg_as_managed_cpp_type(Type - MaybeId) -->
|
|
write_il_type_as_managed_cpp_type(Type),
|
|
( { MaybeId = yes(Id) } ->
|
|
io__write_string(" "),
|
|
io__write_string(Id)
|
|
;
|
|
% XXX should make up a name!
|
|
{ sorry(this_file, "unnamed arguments in method parameters") }
|
|
).
|
|
|
|
|
|
:- func this_file = string.
|
|
this_file = "mlds_to_mcpp.m".
|
|
|