Allow the compilation of programs with class name conflicts and submodule name conflicts.
note: fix valgrind script to inlude new name mangling
Signed-off-by: Jean Privat <jean@pryen.org>
v.add_decl("#include <nit_common.h>")
compile_tables_to_c(v)
compile_main_part(v)
- var filename = "{cprogram.compdir}/{main_module.name}._tables.c"
+ var filename = "{cprogram.compdir}/{main_module.cname}._tables.c"
cprogram.files.add(filename)
var f = new OFStream.open(filename)
- f.write("/* This C file is generated by NIT to compile program {main_module.name}. */\n")
+ f.write("/* This C file is generated by NIT to compile program {main_module.cname}. */\n")
for m in main_module.mhe.greaters_and_self do
f.write("#include \"{cprogram.module_header_name(m)}\"\n")
end
private fun compile_separate_module(cprogram: CProgram)
do
var tc = cprogram.program.tc
- tc.info("Generating C code for module: {name}",2)
+ tc.info("Generating C code for module: {full_name}",2)
var v = new CompilerVisitor(self, cprogram)
v.add_decl("#include <nit_common.h>")
var hfilename = cprogram.module_header_name(self)
var f = new OFStream.open("{cprogram.compdir}/{hfilename}")
- f.write("/* This C header file is generated by NIT to compile modules and programs that requires {name}. */\n")
- f.write("#ifndef {name}{cprogram.get_file_ending}\n")
- f.write("#define {name}{cprogram.get_file_ending}\n")
+ f.write("/* This C header file is generated by NIT to compile modules and programs that requires {full_name}. */\n")
+ f.write("#ifndef {cname}{cprogram.get_file_ending}\n")
+ f.write("#define {cname}{cprogram.get_file_ending}\n")
for m in mhe.direct_greaters do f.write("#include \"{cprogram.module_header_name(m)}\"\n")
v.header_writer.write_to_stream(f)
f.write("#endif\n")
f.close
- var cfilename = "{cprogram.compdir}/{name}.{cprogram.get_file_ending}.c"
+ var cfilename = "{cprogram.compdir}/{cname}.{cprogram.get_file_ending}.c"
cprogram.files.add(cfilename)
f = new OFStream.open("{cfilename}")
- f.write("/* This C file is generated by NIT to compile module {name}. */\n")
+ f.write("/* This C file is generated by NIT to compile module {cname}. */\n")
f.write("#include \"{hfilename}\"\n")
v.top_writer.write_to_stream(f)
f.close
do
_program = p
_compdir = p.tc.compdir.as(not null)
- _build_file = "{compdir}/{program.main_module.name}._build.sh"
+ _build_file = "{compdir}/{program.main_module.cname}._build.sh"
end
# The Nit program compiled to C
if _module_include.has_key(m) then
return _module_include[m]
end
- var filename = "{m.name}.{get_file_ending}.h"
+ var filename = "{m.cname}.{get_file_ending}.h"
_module_include[m] = filename
return filename
end
end
f.write("#!/bin/sh\n")
- f.write("# This shell script is generated by NIT to compile the program {program.main_module.name}.\n")
+ f.write("# This shell script is generated by NIT to compile the program {program.main_module.full_name}.\n")
f.write("CLIBDIR=\"{tc.clibdir.as(not null)}\"\n")
f.write("{tc.bindir.as(not null)}/gccx {verbose} -d {compdir} -I $CLIBDIR {include_dirs.join(" ")}")
if tc.output_file != null then
end
redef class MMGlobalClass
+ # Cacher result of cname
+ var _cname_cache: nullable String
+
+ # The mangled name of the global class
+ fun cname: String
+ do
+ var cname = _cname_cache
+ if cname == null then
+ cname = intro.mmmodule.cname + "___" + cmangle(intro.name)
+ _cname_cache = cname
+ end
+ return cname
+ end
+
# C symbol refering the identifier of the class
fun id_id: String
do
- return "ID_{intro.name}"
+ return "ID_{cname}"
end
# C symbol refering the color of the class (for subtype tests)
fun color_id: String
do
- return "COLOR_{intro.name}"
+ return "COLOR_{cname}"
end
# C symbol refering the init table position of the class (for constructor linearization)
fun init_table_pos_id: String
do
- return "INIT_TABLE_POS_{intro.name}"
+ return "INIT_TABLE_POS_{cname}"
+ end
+end
+
+redef class MMModule
+ # Cacher result of cname
+ var _cname_cache: nullable String
+
+ # The mangled name of the module
+ fun cname: String
+ do
+ var cname = _cname_cache
+ if cname == null then
+ var l = new List[String]
+ var m: nullable MMModule = self
+ while m != null do
+ l.unshift(cmangle(m.name))
+ var d: nullable MMDirectory = m.directory
+ while d != null and d.owner == m do d = d.parent
+ if d == null then m = null else m = d.owner
+ end
+ cname = l.to_a.join("___")
+ _cname_cache = cname
+ end
+ return cname
end
end
+redef class MMLocalClass
+ # The mangled name of the global class
+ fun cname: String do return global.cname
+end
+
redef class MMLocalProperty
# Cacher result of cname
var _cname_cache: nullable String
do
var cname = _cname_cache
if cname == null then
- cname = cmangle(mmmodule.name, local_class.name, name)
+ cname = mmmodule.cname + "___" + cmangle(local_class.name, name)
_cname_cache = cname
end
return cname
var s = new Buffer.from("classtable_t TAG2VFT[4] = \{NULL")
for t in ["Int","Char","Bool"] do
if main_module.has_global_class_named(t.to_symbol) then
- s.append(", (const classtable_t)VFT_{t}")
+ var c = main_module.class_by_name(t.to_symbol)
+ s.append(", (const classtable_t)VFT_{c.cname}")
else
s.append(", NULL")
end
if v.program.main_method == null then
print("No main")
else
- v.add_instr("G_sys = NEW_Sys();")
+ var c = v.program.main_class
+ v.add_instr("G_sys = NEW_{c.cname}();")
v.add_instr("register_static_object(&G_sys);")
v.add_instr("{v.program.main_method.cname}(G_sys);")
end
# Compile sep files
fun compile_mod_to_c(v: CompilerVisitor)
do
- v.add_decl("extern const char *LOCATE_{name};")
+ v.add_decl("extern const char *LOCATE_{cname};")
if not v.program.tc.use_SFT_optimization then
- v.add_decl("extern const int SFT_{name}[];")
+ v.add_decl("extern const int SFT_{cname}[];")
end
var i = 0
for e in local_table do
if v.program.tc.use_SFT_optimization then
value = "{e.value(v.program)}"
else
- value = "SFT_{name}[{i}]"
+ value = "SFT_{cname}[{i}]"
i = i + 1
end
e.compile_macros(v, value)
# Compile module file for the current module
fun compile_local_table_to_c(v: CompilerVisitor)
do
- v.add_instr("const char *LOCATE_{name} = \"{location.file}\";")
+ v.add_instr("const char *LOCATE_{cname} = \"{location.file}\";")
if v.program.tc.use_SFT_optimization or local_table.is_empty then
return
end
- v.add_instr("const int SFT_{name}[{local_table.length}] = \{")
+ v.add_instr("const int SFT_{cname}[{local_table.length}] = \{")
v.indent
for e in local_table do
v.add_instr(e.value(v.program) + ",")
do
v.add_decl("")
var pi = primitive_info
- v.add_decl("extern const classtable_elt_t VFT_{name}[];")
+ v.add_decl("extern const classtable_elt_t VFT_{cname}[];")
if pi != null and not pi.tagged then
var t = pi.cname
var tbox = "struct TBOX_{name}"
clen = v.program.table_information.max_class_table_length
end
- v.add_instr("const classtable_elt_t VFT_{name}[{clen}] = \{")
+ v.add_instr("const classtable_elt_t VFT_{cname}[{clen}] = \{")
v.indent
for e in ctab do
if e == null then
v.indent
v.add_instr("Nit_NativeArray array;")
v.add_instr("array = (Nit_NativeArray)alloc(sizeof(struct Nit_NativeArray) + ((length - 1) * size));")
- v.add_instr("array->vft = (classtable_elt_t*)VFT_{name};")
+ v.add_instr("array->vft = (classtable_elt_t*)VFT_{cname};")
v.add_instr("array->object_id = object_id_counter;")
v.add_instr("object_id_counter = object_id_counter + 1;")
v.add_instr("array->size = length;")
else if pi == null then
do
# Generate INIT_ATTRIBUTES routine
- var cname = "INIT_ATTRIBUTES__{name}"
+ var cname = "INIT_ATTRIBUTES__{cname}"
var args = init_var_iroutine.compile_signature_to_c(v, cname, "init var of {name}", null, null)
var decl_writer_old = v.decl_writer
v.decl_writer = v.writer.sub
end
do
# Generate NEW routine
- v.add_decl("val_t NEW_{name}(void);")
- v.add_instr("val_t NEW_{name}(void)")
+ v.add_decl("val_t NEW_{cname}(void);")
+ v.add_instr("val_t NEW_{cname}(void)")
v.add_instr("\{")
v.indent
v.add_instr("obj_t obj;")
v.add_instr("obj = alloc(sizeof(val_t) * {itab.length});")
- v.add_instr("obj->vft = (classtable_elt_t*)VFT_{name};")
+ v.add_instr("obj->vft = (classtable_elt_t*)VFT_{cname};")
v.add_instr("obj[1].object_id = object_id_counter;")
v.add_instr("object_id_counter = object_id_counter + 1;")
v.add_instr("return OBJ2VAL(obj);")
end
do
# Compile CHECKNAME
- var cname = "CHECKNEW_{name}"
+ var cname = "CHECKNEW_{cname}"
var args = checknew_iroutine.compile_signature_to_c(v, cname, "check new {name}", null, null)
var decl_writer_old = v.decl_writer
v.decl_writer = v.writer.sub
v.add_instr("val_t BOX_{name}({t} val) \{")
v.indent
v.add_instr("{tbox} *box = ({tbox}*)alloc(sizeof({tbox}));")
- v.add_instr("box->vft = VFT_{name};")
+ v.add_instr("box->vft = VFT_{cname};")
v.add_instr("box->val = val;")
v.add_instr("box->object_id = object_id_counter;")
v.add_instr("object_id_counter = object_id_counter + 1;")
v.add_decl("struct \{struct stack_frame_t me;\} fra;")
end
v.add_instr("fra.me.prev = stack_frame_head; stack_frame_head = &fra.me;")
- v.add_instr("fra.me.file = LOCATE_{v.visitor.mmmodule.name};")
+ v.add_instr("fra.me.file = LOCATE_{v.visitor.mmmodule.cname};")
v.add_instr("fra.me.line = {ll};")
v.add_instr("fra.me.meth = LOCATE_{v.basecname};")
v.add_instr("fra.me.has_broke = 0;")
v.add_location(location)
var w = new_result(v)
w.add("NEW_")
- w.add(stype.local_class.name.to_s)
+ w.add(stype.local_class.cname)
w.add("()")
end
end
v.add_location(location)
var w = new_result(v)
w.add("CHECKNEW_")
- w.add(stype.local_class.name.to_s)
+ w.add(stype.local_class.cname)
w.add("(")
w.add(v.register(expr))
w.add(")")
v.add_location(location)
var w = v.new_instr
w.add("INIT_ATTRIBUTES__")
- w.add(stype.local_class.name.to_s)
+ w.add(stype.local_class.cname)
w.add("(")
w.add(v.register(expr))
w.add(");\n")
w.add("\", NULL")
end
w.add(", LOCATE_")
- w.add(module_location.name.to_s)
+ w.add(module_location.cname)
var ll = location
if ll != null then
w.add(", ")
export NIT_GC_OPTION
# Skip usual methods with blocks to avoid loops
-exec valgrind --tool=callgrind --fn-skip=array___Array___iterate --fn-skip=abstract_collection___Collection___iterate --fn-skip=parser_prod___Visitor___enter_visit "$@"
+exec valgrind --tool=callgrind --fn-skip=array___Array___iterate --fn-skip=abstract_collection___Collection___iterate --fn-skip=parser_prod___Visitor___enter_visit --fn-skip=standard___collection___abstract_collection___Collection___iterate --fn-skip=standard___collection___array___Array___iterate "$@"
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import base_conflict_class_name_submodule1
+import base_conflict_class_name_submodule2
+
+var a1 = newa1
+fooa1(a1)
+var a2 = newa2
+fooa2(a2)
+#alt1#fooa1(a2)
+#alt2#fooa2(a1)
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+ fun foo do 1.output
+end
+
+fun newa1: Object do return new A
+fun fooa1(a: Object) do a.as(A).foo
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+ fun foo do 2.output
+end
+
+fun newa2: Object do return new A
+fun fooa2(a: Object) do a.as(A).foo
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import base_conflict_submodule_name_submodule1
+import base_conflict_submodule_name_submodule2
+
+var a1 = newa1
+fooa1(a1)
+var a2 = newa2
+fooa2(a2)
+#alt1#fooa1(a2)
+#alt2#fooa2(a1)
--- /dev/null
+import submodule
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+ fun foo do 1.output
+end
+
+fun newa1: Object do return new A
+fun fooa1(a: Object) do a.as(A).foo
--- /dev/null
+import submodule
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+class A
+ fun foo do 2.output
+end
+
+fun newa2: Object do return new A
+fun fooa2(a: Object) do a.as(A).foo
--- /dev/null
+1
+2
+Cast failed (./base_conflict_class_name_submodule1.nit:22)
--- /dev/null
+1
+2
+Cast failed (./base_conflict_class_name_submodule2.nit:22)
--- /dev/null
+1
+2
+Cast failed (./base_conflict_submodule_name_submodule1//submodule.nit:22)
--- /dev/null
+1
+2
+Cast failed (./base_conflict_submodule_name_submodule2//submodule.nit:22)