From: Jean Privat Date: Thu, 11 Jul 2013 08:21:45 +0000 (+0200) Subject: Merge remote-tracking branch 'alexandre/libhtml' X-Git-Tag: v0.6~34 X-Git-Url: http://nitlanguage.org?hp=6ec3753ddd1bb177f8be935818704b3258548bbc Merge remote-tracking branch 'alexandre/libhtml' --- diff --git a/clib/gc_chooser.c b/clib/gc_chooser.c new file mode 100644 index 0000000..5a8cffe --- /dev/null +++ b/clib/gc_chooser.c @@ -0,0 +1,123 @@ +/* This file is part of NIT ( http://www.nitlanguage.org ). + * + * Copyright 2006-2009 Jean Privat + * + * This file is free software, which comes along with NIT. This software is + * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. You can modify it is you want, provided this header + * is kept unaltered, and a notification of the changes is added. + * You are allowed to redistribute it and sell it, alone or is a part of + * another product. + */ + +#include "gc_chooser.h" +#include +#include + +#ifdef ANDROID + #include + #define PRINT_ERROR(...) ((void)__android_log_print(ANDROID_LOG_WARN, "nit", __VA_ARGS__)) +#else + #define PRINT_ERROR(...) ((void)fprintf(stderr, __VA_ARGS__)) +#endif + +enum gc_option { gc_opt_large, gc_opt_malloc, gc_opt_boehm } gc_option; + +#ifdef WITH_LIBGC +#define GC_DEBUG +#include +#endif + +void *nit_raw_alloc(size_t s0) +{ + switch (gc_option) { + case gc_opt_malloc: return malloc(s0); +#ifdef WITH_LIBGC + case gc_opt_boehm: return GC_MALLOC_ATOMIC(s0); +#endif + + default: return nit_alloc(s0); + } +} + +static void *large_alloc(size_t s0) +{ + static char * alloc_pos = NULL; + static size_t alloc_size = 0; + void * res; + size_t s = ((s0+3)/4)*4; + if(alloc_size < s) { + alloc_size = s + 1024*1024; + alloc_pos = (char *)calloc(alloc_size, 1); + } + res = alloc_pos; + alloc_size -= s; + alloc_pos += s; + return res; +} + +void nit_gcollect(void) { + switch (gc_option) { +#ifdef WITH_LIBGC + case gc_opt_boehm: GC_gcollect(); break; +#endif + } +} + +void *nit_alloc(size_t s0) +{ + switch (gc_option) { +#ifdef WITH_LIBGC + case gc_opt_boehm: return GC_MALLOC(s0); +#endif + case gc_opt_malloc: return calloc(1, s0); + case gc_opt_large: + default: return large_alloc(s0); + } +} + +void initialize_gc_option(void) { + /* GC default */ + char *def; +#ifdef WITH_LIBGC + gc_option = gc_opt_boehm; + def = "boehm"; +#else + gc_option = gc_opt_malloc; + def = "malloc"; +#endif + + /* Process GC runtime selection */ + if (getenv("NIT_GC_OPTION") != NULL) { + char *opt=getenv("NIT_GC_OPTION"); + if (strcmp(opt, "boehm")==0) { +#ifdef WITH_LIBGC + gc_option = gc_opt_boehm; +#else + PRINT_ERROR( "Compiled without Boehm GC support. Using default '%s'.\n", def); +#endif + } else if (strcmp(opt, "malloc")==0) { + gc_option = gc_opt_malloc; + } else if (strcmp(opt, "large")==0) { + gc_option = gc_opt_large; + } else if (strcmp(opt, "help")==0) { + PRINT_ERROR( "NIT_GC_OPTION accepts 'malloc', 'large'" +#ifdef WITH_LIBGC + ", 'boehm'" +#endif + ". Default is '%s'.\n", def); + exit(1); + } else { + PRINT_ERROR( "Invalid GC option in NIT_GC_OPTION environment variable. Using default '%s'.\n", def); + } + } + + /* Initialize GC (if needed) */ + switch(gc_option) { +#ifdef WITH_LIBGC + case gc_opt_boehm: GC_INIT(); break; +#endif + default: break; /* Nothing */ + } +} diff --git a/clib/gc_chooser.h b/clib/gc_chooser.h new file mode 100644 index 0000000..4d1d03a --- /dev/null +++ b/clib/gc_chooser.h @@ -0,0 +1,23 @@ +#ifndef NIT_GC_CHOOSER_H +#define NIT_GC_CHOOSER_H + +/* This file is part of NIT ( http://www.nitlanguage.org ). + * + * This file is free software, which comes along with NIT. This software is + * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. You can modify it is you want, provided this header + * is kept unaltered, and a notification of the changes is added. + * You are allowed to redistribute it and sell it, alone or is a part of + * another product. + */ + +#include + +/* GC and memory management */ +void *nit_alloc(size_t); /* allocate memory to store an object with an object header */ +void *nit_raw_alloc(size_t); /* allocate raw memory to store a raw stram of byte */ +void nit_gcollect(void); /* force a garbage collection */ +void initialize_gc_option(void); /* Select the wanted GC using envvar `NIT_GC_OPTION` */ + +#endif diff --git a/lib/standard/string.nit b/lib/standard/string.nit index d1c4b7c..dc00916 100644 --- a/lib/standard/string.nit +++ b/lib/standard/string.nit @@ -75,7 +75,7 @@ abstract class AbstractString var myitems = _items var itsitems = str._items if myindex > length or itsindex > myindex then return false - var its_index_from = str._indexFrom + var its_index_from = str._index_from itsindex += its_index_from while itsindex >= its_index_from do if myitems[myindex] != itsitems[itsindex] then return false @@ -177,6 +177,25 @@ abstract class AbstractString return s.to_s end + # Trims trailing and preceding white spaces + # A whitespace is defined as any character which ascii value is less than or equal to 32 + fun trim: String + do + if self._length == 0 then return self.to_s + # find position of the first non white space char (ascii < 32) from the start of the string + var start_pos = 0 + while self[start_pos].ascii <= 32 do + start_pos += 1 + if start_pos == _length then return "" + end + # find position of the first non white space char from the end of the string + var end_pos = length - 1 + while self[end_pos].ascii <= 32 do + end_pos -= 1 + if end_pos == start_pos then return self[start_pos].to_s + end + return self.substring(start_pos, end_pos - start_pos + 1) + end redef fun output do @@ -196,8 +215,11 @@ class String redef type OTHER: String - readable var _indexFrom: Int - readable var _indexTo: Int + # Index in _items of the start of the string + readable var _index_from: Int + + # Indes in _items of the last item of the string + readable var _index_to: Int ################################################ # AbstractString specific methods # @@ -207,16 +229,23 @@ class String # redef fun [](index) do assert index >= 0 - assert (index + _indexFrom) < (_indexFrom + _length) - return items[index + _indexFrom] + # Check that the index (+ index_from) is not larger than indexTo + # In other terms, if the index is valid + assert (index + _index_from) <= _index_to + return _items[index + _index_from] end # Create a substring. # # "abcd".substring(1, 2) # --> "bc" # "abcd".substring(-1, 2) # --> "a" - # "abcd".substring(1, 0) # --> "" - # "abcd".substring(2, 5) # --> "cd" + # "abcd".substring(1, 0) # --> "" + # "abcd".substring(2, 5) # --> "cd" + # + # A "from" index < 0 will be replaced by 0 + # Unless a count value is > 0 at the same time + # In this case, from += count and count -= from + # redef fun substring(from: Int, count: Int): String do assert count >= 0 @@ -227,9 +256,9 @@ class String from = 0 end - var realFrom = _indexFrom + from + var realFrom = _index_from + from - if (realFrom + count) > _indexTo then return new String.from_substring(realFrom, _indexTo, _items) + if (realFrom + count) > _index_to then return new String.from_substring(realFrom, _index_to, _items) if count == 0 then return "" @@ -238,9 +267,12 @@ class String # Create a substring from `self' beginning at the 'from' position # - # "abcd".substring(1) # --> "bcd" - # "abcd".substring(-1) # --> "abcd" - # "abcd".substring(2) # --> "cd" + # "abcd".substring_from(1) # --> "bcd" + # "abcd".substring_from(-1) # --> "abcd" + # "abcd".substring_from(2) # --> "cd" + # + # As with substring, a "from" index < 0 will be replaced by 0 + # redef fun substring_from(from: Int): String do if from > _length then return "" @@ -263,9 +295,9 @@ class String if myindex > _length or itsindex > myindex then return false - var itsindexfrom = str.indexFrom + var itsindexfrom = str.index_from itsindex += itsindexfrom - myindex += indexFrom + myindex += index_from while itsindex >= itsindexfrom do if myitems[myindex] != itsitems[itsindex] then return false @@ -280,15 +312,15 @@ class String redef fun to_upper: String do var outstr = calloc_string(self._length + 1) - var index = 0 + var out_index = 0 var myitems = self._items - var index_from = self._indexFrom - var max = self._indexTo + var index_from = self._index_from + var max = self._index_to while index_from <= max do - outstr[index] = myitems[index_from].to_upper - index += 1 + outstr[out_index] = myitems[index_from].to_upper + out_index += 1 index_from += 1 end @@ -301,15 +333,15 @@ class String redef fun to_lower : String do var outstr = calloc_string(self._length + 1) - var index = 0 + var out_index = 0 var myitems = self._items - var index_from = self._indexFrom - var max = self._indexTo + var index_from = self._index_from + var max = self._index_to while index_from <= max do - outstr[index] = myitems[index_from].to_lower - index += 1 + outstr[out_index] = myitems[index_from].to_lower + out_index += 1 index_from += 1 end @@ -318,10 +350,31 @@ class String return new String.with_native(outstr, self._length) end + redef fun trim: String + do + if self._length == 0 then return self + # find position of the first non white space char (ascii < 32) from the start of the string + var start_pos = self._index_from + while _items[start_pos].ascii <= 32 do + start_pos += 1 + if start_pos == _index_to + 1 then return "" + end + # find position of the first non white space char from the end of the string + var end_pos = _index_to + while _items[end_pos].ascii <= 32 do + end_pos -= 1 + if end_pos == start_pos then return _items[start_pos].to_s + end + start_pos -= index_from + end_pos -= index_from + return self.substring(start_pos, end_pos - start_pos + 1) + end + redef fun output do - var i = self._indexFrom - while i < length do + var i = self._index_from + var imax = self._index_to + while i <= imax do _items[i].output i += 1 end @@ -332,11 +385,16 @@ class String ################################################## # Creates a String object as a substring of another String + # + # From : index to start at + # + # To : Index to stop at (from + count -1) + # private init from_substring(from: Int, to: Int, internalString: NativeString) do _items = internalString - _indexFrom = from - _indexTo = to + _index_from = from + _index_to = to _length = to - from + 1 end @@ -346,8 +404,8 @@ class String assert size >= 0 _items = nat _length = size - _indexFrom = 0 - _indexTo = size - 1 + _index_from = 0 + _index_to = _length - 1 end # Create a new string from a null terminated char *. @@ -356,108 +414,134 @@ class String with_native(str,str.cstring_length) end + # Creates a new Nit String from an existing CString + # Pretty much equals to from_cstring but copies instead + # of passing a reference + # Avoids manual/automatic dealloc problems when dealing with native C code + init copy_from_native(str: NativeString) + do + var temp_length = str.cstring_length + var new_str = calloc_string(temp_length + 1) + str.copy_to(new_str, temp_length, 0, 0) + new_str[temp_length] = '\0' + with_native(new_str, temp_length) + end + # Return a null terminated char * fun to_cstring: NativeString do #return items - if _indexFrom > 0 or _indexTo != items.cstring_length-1 then - var newItems = calloc_string(length+1) - self.items.copy_to(newItems, _length, _indexFrom, 0) + if _index_from > 0 or _index_to != items.cstring_length - 1 then + var newItems = calloc_string(_length + 1) + self.items.copy_to(newItems, _length, _index_from, 0) newItems[length] = '\0' return newItems end return _items end - redef fun ==(o) + redef fun ==(other) do - if not o isa String or o is null then return false + if not other isa String or other is null then return false + + if self.object_id == other.object_id then return true - if self.object_id == o.object_id then return true + var my_length = _length - var l = _length + if other._length != my_length then return false - if o._length != l then return false + var my_index = _index_from + var its_index = other._index_from - var i = _indexFrom - var j = o._indexFrom - var max = l + _indexFrom - var itsitems = o._items + var last_iteration = my_index + my_length + + var itsitems = other._items var myitems = self._items - while i < max do - if myitems[i] != itsitems[j] then return false - i += 1 - j += 1 + while my_index < last_iteration do + if myitems[my_index] != itsitems[its_index] then return false + my_index += 1 + its_index += 1 end return true end - redef fun <(s) + # The comparison between two strings is done on a lexicographical basis + # Eg : "aa" < "b" => true + redef fun <(other) do - if self.object_id == s.object_id then return false + if self.object_id == other.object_id then return false + + var my_curr_char : Char + var its_curr_char : Char + + var curr_id_self = self._index_from + var curr_id_other = other._index_from - var c1 : Int - var c2 : Int - var currIdSelf = self._indexFrom - var currIdOther = s._indexFrom var my_items = self._items - var its_items = s._items + var its_items = other._items - var self_upper_bound = self._length + currIdSelf - var other_upper_bound = s._length + currIdOther + var my_length = self._length + var its_length = other._length - while currIdSelf < self_upper_bound and currIdOther < other_upper_bound do - c1 = my_items[currIdSelf].ascii - c2 = its_items[currIdOther].ascii + var max_iterations = curr_id_self + my_length - if c1 < c2 then - return true - else if c2 < c1 then + while curr_id_self < max_iterations do + my_curr_char = my_items[curr_id_self] + its_curr_char = its_items[curr_id_other] + + if my_curr_char != its_curr_char then + if my_curr_char < its_curr_char then return true return false end - currIdSelf += 1 - currIdOther += 1 + curr_id_self += 1 + curr_id_other += 1 end - if self._length < s._length then - return true - else - return false - end + return my_length < its_length end # The concatenation of `self' with `r' fun +(s: String): String do - var newString = calloc_string(_length + s._length + 1) + var my_length = self._length + var its_length = s._length + + var target_string = calloc_string(my_length + its_length + 1) - self._items.copy_to(newString, _length, _indexFrom, 0) - s._items.copy_to(newString, s._length, s._indexFrom, _length) + self._items.copy_to(target_string, my_length, _index_from, 0) + s._items.copy_to(target_string, its_length, s._index_from, my_length) - newString[self._length + s._length] = '\0' + target_string[my_length + its_length] = '\0' - return new String.with_native(newString, _length + s._length) + return new String.with_native(target_string, my_length + its_length) end # i repetitions of self fun *(i: Int): String do assert i >= 0 - var r = calloc_string((_length * i) + 1) - r[_length * i] = '\0' + var my_length = self._length - var lastStr = new String.with_native(r, (_length * i)) + var final_length = my_length * i - while i > 0 do - self._items.copy_to(r, _length, _indexFrom, _length*(i-1)) - i -= 1 + var my_items = self._items + + var target_string = calloc_string((final_length) + 1) + + target_string[final_length] = '\0' + + var current_last = 0 + + for iteration in [1 .. i] do + my_items.copy_to(target_string, my_length, 0, current_last) + current_last += my_length end - return lastStr + return new String.with_native(target_string, final_length) end redef fun to_s do return self @@ -468,12 +552,12 @@ class String var h = 5381 var i = _length - 1 - var myitems = self.items - var index_from = self._indexFrom + var myitems = _items + var strStart = _index_from - i += index_from + i += strStart - while i >= index_from do + while i >= strStart do h = (h * 32) + h + self._items[i].ascii i -= 1 end @@ -524,7 +608,7 @@ class Buffer if s isa String then var sl = s.length if _capacity < _length + sl then enlarge(_length + sl) - s.items.copy_to(_items, sl, s._indexFrom, _length) + s.items.copy_to(_items, sl, s._index_from, _length) _length += sl else super @@ -576,7 +660,7 @@ class Buffer _capacity = s.length + 1 _length = s.length _items = calloc_string(_capacity) - s.items.copy_to(_items, _length, s._indexFrom, 0) + s.items.copy_to(_items, _length, s._index_from, 0) end # Create a new empty string with a given capacity. diff --git a/src/abstract_compiler.nit b/src/abstract_compiler.nit index 8230b82..62bdc7b 100644 --- a/src/abstract_compiler.nit +++ b/src/abstract_compiler.nit @@ -27,6 +27,8 @@ redef class ToolContext var opt_output: OptionString = new OptionString("Output file", "-o", "--output") # --no-cc var opt_no_cc: OptionBool = new OptionBool("Do not invoke C compiler", "--no-cc") + # --cc-paths + var opt_cc_path: OptionArray = new OptionArray("Set include path for C header files (may be used more than once)", "--cc-path") # --make-flags var opt_make_flags: OptionString = new OptionString("Additional options to make", "--make-flags") # --hardening @@ -56,6 +58,42 @@ redef class ToolContext end redef class ModelBuilder + # The list of directories to search for included C headers (-I for C compilers) + # The list is initially set with : + # * the toolcontext --cc-path option + # * the NIT_CC_PATH environment variable + # * some heuristics including the NIT_DIR environment variable and the progname of the process + # Path can be added (or removed) by the client + var cc_paths = new Array[String] + + redef init(model, toolcontext) + do + super + + # Look for the the Nit clib path + var path_env = "NIT_DIR".environ + if not path_env.is_empty then + var libname = "{path_env}/clib" + if libname.file_exists then cc_paths.add(libname) + end + + var libname = "{sys.program_name.dirname}/../clib" + if libname.file_exists then cc_paths.add(libname.simplify_path) + + if cc_paths.is_empty then + toolcontext.error(null, "Cannot determine the nit clib path. define envvar NIT_DIR.") + end + + # Add user defined cc_paths + cc_paths.append(toolcontext.opt_cc_path.value) + + path_env = "NIT_CC_PATH".environ + if not path_env.is_empty then + cc_paths.append(path_env.split_with(':')) + end + + end + protected fun write_and_make(compiler: AbstractCompiler) do var mainmodule = compiler.mainmodule @@ -72,43 +110,64 @@ redef class ModelBuilder outname = "{mainmodule.name}.bin" end - var hfilename = ".nit_compile/{mainmodule.name}.1.h" - var h = new OFStream.open(hfilename) + var hfilename = compiler.header.file.name + ".h" + var hfilepath = ".nit_compile/{hfilename}" + var h = new OFStream.open(hfilepath) for l in compiler.header.decl_lines do h.write l h.write "\n" end + for l in compiler.header.lines do + h.write l + h.write "\n" + end h.close var cfiles = new Array[String] - var file: nullable OFStream = null - var count = 0 - - var i = 0 - for vis in compiler.visitors do - count += vis.lines.length - if file == null or count > 10000 or vis.file_break then - i += 1 - if file != null then file.close - var cfilename = ".nit_compile/{mainmodule.name}.{i}.c" - cfiles.add(cfilename) - file = new OFStream.open(cfilename) - file.write "#include \"{mainmodule.name}.1.h\"\n" - count = vis.lines.length + for f in compiler.files do + var i = 0 + var hfile: nullable OFStream = null + var count = 0 + var cfilename = ".nit_compile/{f.name}.0.h" + hfile = new OFStream.open(cfilename) + hfile.write "#include \"{hfilename}\"\n" + for key in f.required_declarations do + if not compiler.provided_declarations.has_key(key) then + print "No provided declaration for {key}" + abort + end + hfile.write compiler.provided_declarations[key] + hfile.write "\n" end - if vis != compiler.header then + hfile.close + var file: nullable OFStream = null + for vis in f.writers do + if vis == compiler.header then continue + var total_lines = vis.lines.length + vis.decl_lines.length + if total_lines == 0 then continue + count += total_lines + if file == null or count > 10000 then + i += 1 + if file != null then file.close + cfilename = ".nit_compile/{f.name}.{i}.c" + self.toolcontext.info("new C source files to compile: {cfilename}", 3) + cfiles.add(cfilename) + file = new OFStream.open(cfilename) + file.write "#include \"{f.name}.0.h\"\n" + count = total_lines + end for l in vis.decl_lines do file.write l file.write "\n" end + for l in vis.lines do + file.write l + file.write "\n" + end end - for l in vis.lines do - file.write l - file.write "\n" - end + if file != null then file.close end - if file != null then file.close self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2) @@ -117,7 +176,12 @@ redef class ModelBuilder var makename = ".nit_compile/{mainmodule.name}.mk" var makefile = new OFStream.open(makename) - makefile.write("CC = ccache cc\nCFLAGS = -g -O2\nLDFLAGS ?= \nLDLIBS ?= -lm -lgc\n\n") + var cc_includes = "" + for p in cc_paths do + #p = "..".join_path(p) + cc_includes += " -I \"" + p + "\"" + end + makefile.write("CC = ccache cc\nCFLAGS = -g -O2{cc_includes}\nLDFLAGS ?= \nLDLIBS ?= -lm -lgc\n\n") makefile.write("all: {outname}\n\n") var ofiles = new Array[String] @@ -127,13 +191,19 @@ redef class ModelBuilder makefile.write("{o}: {f}\n\t$(CC) $(CFLAGS) -D NONITCNI -c -o {o} {f}\n\n") ofiles.add(o) end + + # Add gc_choser.h to aditionnal bodies + var gc_chooser = new ExternCFile("{cc_paths.first}/gc_chooser.c", "-DWITH_LIBGC") + compiler.extern_bodies.add(gc_chooser) + # Compile each required extern body into a specific .o for f in compiler.extern_bodies do - i += 1 - var o = ".nit_compile/{mainmodule.name}.{i}.o" - makefile.write("{o}: {f}\n\t$(CC) $(CFLAGS) -D NONITCNI -c -o {o} {f}\n\n") + var basename = f.filename.basename(".c") + var o = ".nit_compile/{basename}.extern.o" + makefile.write("{o}: {f.filename}\n\t$(CC) $(CFLAGS) -D NONITCNI {f.cflags} -c -o {o} {f.filename}\n\n") ofiles.add(o) end + # Link edition makefile.write("{outname}: {ofiles.join(" ")}\n\t$(CC) $(LDFLAGS) -o {outname} {ofiles.join(" ")} $(LDLIBS)\n\n") # Clean @@ -190,25 +260,33 @@ abstract class AbstractCompiler # Force the creation of a new file # The point is to avoid contamination between must-be-compiled-separately files - fun new_file + fun new_file(name: String): CodeFile do - var v = self.new_visitor - v.file_break = true + var f = new CodeFile(name) + self.files.add(f) + return f end - # The list of all associated visitors + # The list of all associated files # Used to generate .c files - # FIXME: should not be vistors but just somewhere to store lines - var visitors: List[VISITOR] = new List[VISITOR] + var files: List[CodeFile] = new List[CodeFile] # Initialize a visitor specific for a compiler engine fun new_visitor: VISITOR is abstract # Where global declaration are stored (the main .h) - # - # FIXME: should not be a visitor but just somewhere to store lines - # FIXME: should not have a global .h since it does not help recompilations - var header: VISITOR writable + var header: CodeWriter writable + + # Provide a declaration that can be requested (before or latter) by a visitor + fun provide_declaration(key: String, s: String) + do + if self.provided_declarations.has_key(key) then + assert self.provided_declarations[key] == s + end + self.provided_declarations[key] = s + end + + private var provided_declarations = new HashMap[String, String] # Compile C headers # This method call compile_header_strucs method that has to be refined @@ -217,16 +295,7 @@ abstract class AbstractCompiler self.header.add_decl("#include ") self.header.add_decl("#include ") self.header.add_decl("#include ") - self.header.add_decl("#ifndef NOBOEHM") - self.header.add_decl("#include ") - self.header.add_decl("#ifdef NOBOEHM_ATOMIC") - self.header.add_decl("#undef GC_MALLOC_ATOMIC") - self.header.add_decl("#define GC_MALLOC_ATOMIC(x) GC_MALLOC(x)") - self.header.add_decl("#endif /*NOBOEHM_ATOMIC*/") - self.header.add_decl("#else /*NOBOEHM*/") - self.header.add_decl("#define GC_MALLOC(x) calloc(1, (x))") - self.header.add_decl("#define GC_MALLOC_ATOMIC(x) calloc(1, (x))") - self.header.add_decl("#endif /*NOBOEHM*/") + self.header.add_decl("#include ") compile_header_structs @@ -263,6 +332,7 @@ abstract class AbstractCompiler end v.add_decl("int main(int argc, char** argv) \{") v.add("glob_argc = argc; glob_argv = argv;") + v.add("initialize_gc_option();") var main_type = mainmodule.sys_type if main_type != null then var mainmodule = v.compiler.mainmodule @@ -307,31 +377,11 @@ abstract class AbstractCompiler v.add("\}") end - # look for a needed .h and .c file for a given .nit source-file - # FIXME: bad API, parameter should be a MModule, not its source-file - fun add_extern(file: String) - do - file = file.strip_extension(".nit") - var tryfile = file + ".nit.h" - if tryfile.file_exists then - self.header.add_decl("#include \"{"..".join_path(tryfile)}\"") - end - tryfile = file + "_nit.h" - if tryfile.file_exists then - self.header.add_decl("#include \"{"..".join_path(tryfile)}\"") - end - tryfile = file + ".nit.c" - if tryfile.file_exists then - self.extern_bodies.add(tryfile) - end - tryfile = file + "_nit.c" - if tryfile.file_exists then - self.extern_bodies.add(tryfile) - end - end - # List of additional .c files required to compile (native interface) - var extern_bodies = new ArraySet[String] + var extern_bodies = new Array[ExternCFile] + + # This is used to avoid adding an extern file more than once + private var seen_extern = new ArraySet[String] # Generate code that check if an instance is correctly initialized fun generate_check_init_instance(mtype: MClassType) is abstract @@ -429,6 +479,34 @@ abstract class AbstractCompiler end end +# A file unit (may be more than one file if +# A file unit aim to be autonomous and is made or one or more `CodeWriter`s +class CodeFile + var name: String + var writers = new Array[CodeWriter] + var required_declarations = new HashSet[String] +end + +# Where to store generated lines +class CodeWriter + var file: CodeFile + var lines: List[String] = new List[String] + var decl_lines: List[String] = new List[String] + + # Add a line in the main part of the generated C + fun add(s: String) do self.lines.add(s) + + # Add a line in the + # (used for local or global declaration) + fun add_decl(s: String) do self.decl_lines.add(s) + + init(file: CodeFile) + do + self.file = file + file.writers.add(self) + end +end + # A visitor on the AST of property definition that generate the C code. abstract class AbstractCompilerVisitor @@ -449,12 +527,12 @@ abstract class AbstractCompilerVisitor # Alias for self.compiler.mainmodule.bool_type fun bool_type: MClassType do return self.compiler.mainmodule.bool_type - var file_break: Bool = false + var writer: CodeWriter init(compiler: COMPILER) do self.compiler = compiler - compiler.visitors.add(self) + self.writer = new CodeWriter(compiler.files.last) end # Force to get the primitive class named `name' or abort @@ -741,15 +819,51 @@ abstract class AbstractCompilerVisitor # Code generation - private var lines: List[String] = new List[String] - private var decl_lines: List[String] = new List[String] - # Add a line in the main part of the generated C - fun add(s: String) do self.lines.add(s) + fun add(s: String) do self.writer.lines.add(s) # Add a line in the # (used for local or global declaration) - fun add_decl(s: String) do self.decl_lines.add(s) + fun add_decl(s: String) do self.writer.decl_lines.add(s) + + # Request the presence of a global declaration + fun require_declaration(key: String) + do + self.writer.file.required_declarations.add(key) + end + + # Add a declaration in the local-header + # The declaration is ensured to be present once + fun declare_once(s: String) + do + self.compiler.provide_declaration(s, s) + self.require_declaration(s) + end + + # look for a needed .h and .c file for a given .nit source-file + # FIXME: bad API, parameter should be a MModule, not its source-file + fun add_extern(file: String) + do + file = file.strip_extension(".nit") + var tryfile = file + ".nit.h" + if tryfile.file_exists then + self.declare_once("#include \"{"..".join_path(tryfile)}\"") + end + tryfile = file + "_nit.h" + if tryfile.file_exists then + self.declare_once("#include \"{"..".join_path(tryfile)}\"") + end + + if self.compiler.seen_extern.has(file) then return + self.compiler.seen_extern.add(file) + tryfile = file + ".nit.c" + if not tryfile.file_exists then + tryfile = file + "_nit.c" + if not tryfile.file_exists then return + end + var f = new ExternCFile(tryfile, "") + self.compiler.extern_bodies.add(f) + end # Return a new local runtime_variable initialized with the C expression `cexpr'. fun new_expr(cexpr: String, mtype: MType): RuntimeVariable @@ -935,6 +1049,14 @@ class Frame var returnlabel: nullable String writable = null end +# An extern C file to compile +class ExternCFile + # The filename of the file + var filename: String + # Additionnal specific CC compiler -c flags + var cflags: String +end + redef class String # Mangle a string to be a unique valid C identifier fun to_cmangle: String @@ -1484,7 +1606,7 @@ redef class AInternMethPropdef v.ret(v.new_expr("glob_sys", ret.as(not null))) return else if pname == "calloc_string" then - v.ret(v.new_expr("(char*)GC_MALLOC_ATOMIC({arguments[1]})", ret.as(not null))) + v.ret(v.new_expr("(char*)nit_alloc({arguments[1]})", ret.as(not null))) return else if pname == "calloc_array" then v.calloc_array(ret.as(not null), arguments) @@ -1504,7 +1626,7 @@ redef class AInternMethPropdef v.ret(v.new_expr("(char*){nat}", ret.as(not null))) return else if pname == "force_garbage_collection" then - v.add("GC_gcollect();") + v.add("nit_gcollect();") return end v.add("printf(\"NOT YET IMPLEMENTED {class_name}:{mpropdef} at {location.to_s}\\n\");") @@ -1525,7 +1647,7 @@ redef class AExternMethPropdef externname = nextern.text.substring(1, nextern.text.length-2) if location.file != null then var file = location.file.filename - v.compiler.add_extern(file) + v.add_extern(file) end var res: nullable RuntimeVariable = null var ret = mpropdef.msignature.return_mtype @@ -1557,7 +1679,7 @@ redef class AExternInitPropdef externname = nextern.text.substring(1, nextern.text.length-2) if location.file != null then var file = location.file.filename - v.compiler.add_extern(file) + v.add_extern(file) end v.adapt_signature(mpropdef, arguments) var ret = arguments.first.mtype diff --git a/src/global_compiler.nit b/src/global_compiler.nit index 4741df6..7b3c944 100644 --- a/src/global_compiler.nit +++ b/src/global_compiler.nit @@ -37,10 +37,9 @@ redef class ModelBuilder var compiler = new GlobalCompiler(mainmodule, self, runtime_type_analysis) compiler.compile_header - var v = compiler.header for t in runtime_type_analysis.live_types do - compiler.declare_runtimeclass(v, t) + compiler.declare_runtimeclass(t) end compiler.compile_class_names @@ -64,7 +63,7 @@ redef class ModelBuilder self.toolcontext.info("Compile {m} ({compiler.seen.length-compiler.todos.length}/{compiler.seen.length})", 3) m.compile_to_c(compiler) end - self.toolcontext.info("Total methods to compile to C: {compiler.visitors.length}", 2) + self.toolcontext.info("Total methods to compile to C: {compiler.seen.length}", 2) compiler.display_stats @@ -89,7 +88,8 @@ class GlobalCompiler init(mainmodule: MModule, modelbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do super(mainmodule, modelbuilder) - self.header = new_visitor + var file = new_file(mainmodule.name) + self.header = new CodeWriter(file) self.runtime_type_analysis = runtime_type_analysis self.live_primitive_types = new Array[MClassType] for t in runtime_type_analysis.live_types do @@ -101,12 +101,13 @@ class GlobalCompiler # Compile class names (for the class_name and output_class_name methods) protected fun compile_class_names do + var v = new_visitor self.header.add_decl("extern const char const * class_names[];") - self.header.add("const char const * class_names[] = \{") + v.add("const char const * class_names[] = \{") for t in self.runtime_type_analysis.live_types do - self.header.add("\"{t}\", /* {self.classid(t)} */") + v.add("\"{t}\", /* {self.classid(t)} */") end - self.header.add("\};") + v.add("\};") end # Return the C symbol associated to a live type runtime @@ -150,8 +151,9 @@ class GlobalCompiler private var seen: HashSet[AbstractRuntimeFunction] = new HashSet[AbstractRuntimeFunction] # Declare C structures and identifiers for a runtime class - fun declare_runtimeclass(v: VISITOR, mtype: MClassType) + fun declare_runtimeclass(mtype: MClassType) do + var v = self.header assert self.runtime_type_analysis.live_types.has(mtype) v.add_decl("/* runtime class {mtype} */") var idnum = classids.length @@ -210,9 +212,9 @@ class GlobalCompiler res.is_exact = true if is_native_array then var mtype_elt = mtype.arguments.first - v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));") + v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}) + length*sizeof({mtype_elt.ctype}));") else - v.add("{res} = GC_MALLOC(sizeof(struct {mtype.c_name}));") + v.add("{res} = nit_alloc(sizeof(struct {mtype.c_name}));") end v.add("{res}->classid = {self.classid(mtype)};") @@ -243,7 +245,7 @@ class GlobalCompiler self.header.add_decl("val* BOX_{mtype.c_name}({mtype.ctype});") v.add_decl("/* allocate {mtype} */") v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{") - v.add("struct {mtype.c_name}*res = GC_MALLOC(sizeof(struct {mtype.c_name}));") + v.add("struct {mtype.c_name}*res = nit_alloc(sizeof(struct {mtype.c_name}));") v.add("res->classid = {self.classid(mtype)};") v.add("res->value = value;") v.add("return (val*)res;") diff --git a/src/ngall.sh b/src/ngall.sh index 79b2033..b533848 100755 --- a/src/ngall.sh +++ b/src/ngall.sh @@ -4,9 +4,9 @@ rm nitg nitg.bin hello_world.bin 2>/dev/null set -x set -e time ./nitc_3 -O nitg.nit -v -time ./nitg nitg.nit -v -time ./nitg.bin nitg.nit -v -time ./nitg.bin nitg.nit -v -./nitg.bin ../examples/hello_world.nit +time ./nitg nitg.nit -v "$@" +time ./nitg.bin nitg.nit -v "$@" +time ./nitg.bin nitg.nit -v "$@" +./nitg.bin ../examples/hello_world.nit "$@" ./hello_world.bin diff --git a/src/poset.nit b/src/poset.nit index 58d4cb6..aca5d32 100644 --- a/src/poset.nit +++ b/src/poset.nit @@ -26,17 +26,12 @@ class POSet[E: Object] super NaiveCollection[E] super AbstractSorter[E] - redef fun iterator do return nodes.iterator + redef fun iterator do return elements.keys.iterator # All the nodes - private var nodes: Set[E] = new HashSet[E] - private var tos: HashMap[E, Set[E]] = new HashMap[E, Set[E]] - private var froms: HashMap[E, Set[E]] = new HashMap[E, Set[E]] - private var dtos: HashMap[E, Set[E]] = new HashMap[E, Set[E]] - private var dfroms: HashMap[E, Set[E]] = new HashMap[E, Set[E]] private var elements: HashMap[E, POSetElement[E]] = new HashMap[E, POSetElement[E]] - redef fun has(e) do return self.nodes.has(e) + redef fun has(e) do return self.elements.keys.has(e) # Add a node (an element) to the posed # The new element is added unconnected to any other nodes (it is both a new root and a new leaf). @@ -44,15 +39,10 @@ class POSet[E: Object] # If `e' is already present in the POSet then just return the POSetElement (usually you will prefer []) is this case. fun add_node(e: E): POSetElement[E] do - if nodes.has(e) then return self.elements[e] - nodes.add(e) - tos[e] = new HashSet[E] - tos[e].add(e) - froms[e] = new HashSet[E] - froms[e].add(e) - dtos[e] = new HashSet[E] - dfroms[e] = new HashSet[E] - var poe = new POSetElement[E](self, e, nodes.length) + if elements.keys.has(e) then return self.elements[e] + var poe = new POSetElement[E](self, e, elements.length) + poe.tos.add(e) + poe.froms.add(e) self.elements[e] = poe return poe end @@ -70,7 +60,7 @@ class POSet[E: Object] # REQUIRE: has(e) fun [](e: E): POSetElement[E] do - assert nodes.has(e) + assert elements.keys.has(e) return self.elements[e] end @@ -82,48 +72,56 @@ class POSet[E: Object] # FIXME: Do somethind clever to manage loops. fun add_edge(f, t: E) do - add_node(f) - add_node(t) + var fe = add_node(f) + var te = add_node(t) # Skip if edge already present - if tos[f].has(t) then return + if fe.tos.has(t) then return # Add the edge and close the transitivity - for ff in froms[f] do - for tt in tos[t] do - froms[tt].add ff - tos[ff].add tt + for ff in fe.froms do + var ffe = self.elements[ff] + for tt in te.tos do + var tte = self.elements[tt] + tte.froms.add ff + ffe.tos.add tt end end # Update the transitive reduction - if tos[t].has(f) then return # Skip the reduction if there is a loop + if te.tos.has(f) then return # Skip the reduction if there is a loop - for x in dfroms[t].to_a do - if tos[x].has(f) then - dfroms[t].remove(x) - dtos[x].remove(t) + for x in te.dfroms.to_a do + var xe = self.elements[x] + if xe.tos.has(f) then + te.dfroms.remove(x) + xe.dtos.remove(t) end end - for x in dtos[f].to_a do - if froms[x].has(t) then - dfroms[x].remove(f) - dtos[f].remove(x) + for x in fe.dtos.to_a do + var xe = self.elements[x] + if xe.froms.has(t) then + xe.dfroms.remove(f) + fe.dtos.remove(x) end end - dtos[f].add t - dfroms[t].add f + fe.dtos.add t + te.dfroms.add f end # Is there an edge (transitive or not) from `f' to `t'? # Since the POSet is reflexive, true is returned if `f == t'. fun has_edge(f,t: E): Bool do - return nodes.has(f) and tos[f].has(t) + if not elements.keys.has(f) then return false + var fe = self.elements[f] + return fe.tos.has(t) end # Is there a direct edge from `f' to `t'? # Note that because of loops, the result may not be the expected one. fun has_direct_edge(f,t: E): Bool do - return nodes.has(f) and dtos[f].has(t) + if not elements.keys.has(f) then return false + var fe = self.elements[f] + return fe.dtos.has(t) end # Display the POSet in a gaphical windows. @@ -134,8 +132,9 @@ class POSet[E: Object] var f = new OProcess("dot", "-Txlib") #var f = stdout f.write "digraph \{\n" - for x in nodes do - for y in dtos[x] do + for x in elements.keys do + var xe = self.elements[x] + for y in xe.dtos do if self.has_edge(y,x) then f.write "\"{x}\" -> \"{y}\"[dir=both];\n" else @@ -157,7 +156,9 @@ class POSet[E: Object] # The total order is stable unless a new node or a new edge is added redef fun compare(a, b: E): Int do - var res = tos[a].length <=> tos[b].length + var ae = self.elements[a] + var be = self.elements[b] + var res = ae.tos.length <=> be.tos.length if res != 0 then return res return elements[a].count <=> elements[b].count end @@ -182,6 +183,11 @@ class POSetElement[E: Object] # The real object behind the view var element: E + private var tos = new HashSet[E] + private var froms = new HashSet[E] + private var dtos = new HashSet[E] + private var dfroms = new HashSet[E] + # The rank of the # This attribute is used to force a total order for POSet#compare private var count: Int @@ -190,37 +196,37 @@ class POSetElement[E: Object] # Since the POSet is reflexive, element is included in the set. fun greaters: Collection[E] do - return self.poset.tos[self.element] + return self.tos end # Return the set of all elements `t' that have a direct edge from `element' to `t'. fun direct_greaters: Collection[E] do - return self.poset.dtos[self.element] + return self.dtos end # Return the set of all elements `f' that have an edge from `f' to `element'. # Since the POSet is reflexive, element is included in the set. fun smallers: Collection[E] do - return self.poset.froms[self.element] + return self.froms end # Return the set of all elements `f' that have an edge from `f' to `element'. fun direct_smallers: Collection[E] do - return self.poset.dfroms[self.element] + return self.dfroms end # Is there an edge from `object' to `t'? fun <=(t: E): Bool do - return self.poset.tos[self.element].has(t) + return self.tos.has(t) end # Is `t != element' and is there an edge from `object' to `t'? fun <(t: E): Bool do - return t != self.element and self.poset.tos[self.element].has(t) + return t != self.element and self.tos.has(t) end end diff --git a/src/separate_compiler.nit b/src/separate_compiler.nit index ee0299d..7bbbdeb 100644 --- a/src/separate_compiler.nit +++ b/src/separate_compiler.nit @@ -65,6 +65,8 @@ redef class ModelBuilder compiler.compile_header # compile class structures + compiler.new_file("{mainmodule.name}.classes") + compiler.do_property_coloring for m in mainmodule.in_importation.greaters do for mclass in m.intro_mclasses do compiler.compile_class_to_c(mclass) @@ -72,17 +74,17 @@ redef class ModelBuilder end # The main function of the C - compiler.new_file + compiler.new_file("{mainmodule.name}.main") compiler.compile_main_function # compile methods for m in mainmodule.in_importation.greaters do - compiler.new_file + compiler.new_file("{m.name}.sep") compiler.compile_module_to_c(m) end # compile live & cast type structures - compiler.new_file + compiler.new_file("{mainmodule.name}.types") var mtypes = compiler.do_type_coloring for t in mtypes do compiler.compile_type_to_c(t) @@ -112,24 +114,25 @@ class SeparateCompiler init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do super(mainmodule, mmbuilder) - self.header = new_visitor + var file = new_file("nit.common") + self.header = new CodeWriter(file) self.runtime_type_analysis = runtime_type_analysis - self.do_property_coloring self.compile_box_kinds end redef fun compile_header_structs do self.header.add_decl("typedef void(*nitmethod_t)(void); /* general C type representing a Nit method. */") self.compile_header_attribute_structs - self.header.add_decl("struct class \{ int box_kind; nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */") + self.header.add_decl("struct class \{ int box_kind; nitmethod_t vft[]; \}; /* general C type representing a Nit class. */") # With resolution_table_table, all live type resolution are stored in a big table: resolution_table - self.header.add_decl("struct type \{ int id; const char *name; int color; short int is_nullable; struct types *resolution_table; int table_size; int type_table[1]; \}; /* general C type representing a Nit type. */") + self.header.add_decl("struct type \{ int id; const char *name; int color; short int is_nullable; const struct types *resolution_table; int table_size; int type_table[]; \}; /* general C type representing a Nit type. */") + self.header.add_decl("struct instance \{ const struct type *type; const struct class *class; nitattribute_t attrs[]; \}; /* general C type representing a Nit instance. */") if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then - self.header.add_decl("struct types \{ int mask; struct type *types[1]; \}; /* a list types (used for vts, fts and unresolved lists). */") + self.header.add_decl("struct types \{ int mask; const struct type *types[]; \}; /* a list types (used for vts, fts and unresolved lists). */") else - self.header.add_decl("struct types \{ struct type *types[1]; \}; /* a list types (used for vts, fts and unresolved lists). */") + self.header.add_decl("struct types \{ int dummy; const struct type *types[]; \}; /* a list types (used for vts, fts and unresolved lists). */") end if modelbuilder.toolcontext.opt_phmod_typing.value then @@ -138,7 +141,7 @@ class SeparateCompiler self.header.add_decl("#define HASH(mask, id) ((mask)&(id))") end - self.header.add_decl("typedef struct \{ struct type *type; struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */") + self.header.add_decl("typedef struct instance val; /* general C type representing a Nit instance. */") end fun compile_header_attribute_structs @@ -183,21 +186,22 @@ class SeparateCompiler end fun compile_color_consts(colors: Map[Object, Int]) do + var v = new_visitor for m, c in colors do if color_consts_done.has(m) then continue if m isa MProperty then if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.header.add_decl("#define {m.const_color} {c}") + self.provide_declaration(m.const_color, "#define {m.const_color} {c}") else - self.header.add_decl("extern const int {m.const_color};") - self.header.add("const int {m.const_color} = {c};") + self.provide_declaration(m.const_color, "extern const int {m.const_color};") + v.add("const int {m.const_color} = {c};") end else if m isa MType then if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.header.add_decl("#define {m.const_color} {c}") + self.provide_declaration(m.const_color, "#define {m.const_color} {c}") else - self.header.add_decl("extern const int {m.const_color};") - self.header.add("const int {m.const_color} = {c};") + self.provide_declaration(m.const_color, "extern const int {m.const_color};") + v.add("const int {m.const_color} = {c};") end end color_consts_done.add(m) @@ -504,12 +508,10 @@ class SeparateCompiler for pd in cd.mpropdefs do if not pd isa MMethodDef then continue #print "compile {pd} @ {cd} @ {mmodule}" - var r = new SeparateRuntimeFunction(pd) + var r = pd.separate_runtime_function r.compile_to_c(self) - if true or cd.bound_mtype.ctype != "val*" then - var r2 = new VirtualRuntimeFunction(pd) - r2.compile_to_c(self) - end + var r2 = pd.virtual_runtime_function + r2.compile_to_c(self) end end self.mainmodule = old_module @@ -523,19 +525,10 @@ class SeparateCompiler v.add_decl("/* runtime type {mtype} */") # extern const struct type_X - self.header.add_decl("extern const struct type_{c_name} type_{c_name};") - self.header.add_decl("struct type_{c_name} \{") - self.header.add_decl("int id;") - self.header.add_decl("const char *name;") - self.header.add_decl("int color;") - self.header.add_decl("short int is_nullable;") - self.header.add_decl("const struct types *resolution_table;") - self.header.add_decl("int table_size;") - self.header.add_decl("int type_table[{self.type_tables[mtype].length}];") - self.header.add_decl("\};") + self.provide_declaration("type_{c_name}", "extern const struct type type_{c_name};") # const struct type_X - v.add_decl("const struct type_{c_name} type_{c_name} = \{") + v.add_decl("const struct type type_{c_name} = \{") v.add_decl("{self.type_layout.ids[mtype]},") v.add_decl("\"{mtype}\", /* class_name_string */") var layout = self.type_layout @@ -550,7 +543,8 @@ class SeparateCompiler v.add_decl("0,") end if compile_type_resolution_table(mtype) then - v.add_decl("(struct types*) &resolution_table_{c_name},") + v.require_declaration("resolution_table_{c_name}") + v.add_decl("&resolution_table_{c_name},") else v.add_decl("NULL,") end @@ -580,19 +574,15 @@ class SeparateCompiler var layout = self.resolution_layout # extern const struct resolution_table_X resolution_table_X - self.header.add_decl("extern const struct resolution_table_{mtype.c_name} resolution_table_{mtype.c_name};") - self.header.add_decl("struct resolution_table_{mtype.c_name} \{") - if layout isa PHLayout[MClassType, MType] then - self.header.add_decl("int mask;") - end - self.header.add_decl("struct type *types[{self.resolution_tables[mclass_type].length}];") - self.header.add_decl("\};") + self.provide_declaration("resolution_table_{mtype.c_name}", "extern const struct types resolution_table_{mtype.c_name};") # const struct fts_table_X fts_table_X var v = new_visitor - v.add_decl("const struct resolution_table_{mtype.c_name} resolution_table_{mtype.c_name} = \{") + v.add_decl("const struct types resolution_table_{mtype.c_name} = \{") if layout isa PHLayout[MClassType, MType] then v.add_decl("{layout.masks[mclass_type]},") + else + v.add_decl("0, /* dummy */") end v.add_decl("\{") for t in self.resolution_tables[mclass_type] do @@ -605,13 +595,14 @@ class SeparateCompiler var tv = t.resolve_for(mclass_type, mclass_type, self.mainmodule, true) # FIXME: What typeids means here? How can a tv not be live? if self.type_layout.ids.has_key(tv) then - v.add_decl("(struct type*)&type_{tv.c_name}, /* {t}: {tv} */") + v.require_declaration("type_{tv.c_name}") + v.add_decl("&type_{tv.c_name}, /* {t}: {tv} */") else v.add_decl("NULL, /* empty ({t}: {tv} not a live type) */") end end end - v.add_decl("\},") + v.add_decl("\}") v.add_decl("\};") return true end @@ -630,14 +621,9 @@ class SeparateCompiler v.add_decl("/* runtime class {c_name} */") - self.header.add_decl("struct class_{c_name} \{") - self.header.add_decl("int box_kind;") - self.header.add_decl("nitmethod_t vft[{vft.length}];") - self.header.add_decl("\};") - # Build class vft - self.header.add_decl("extern const struct class_{c_name} class_{c_name};") - v.add_decl("const struct class_{c_name} class_{c_name} = \{") + self.provide_declaration("class_{c_name}", "extern const struct class class_{c_name};") + v.add_decl("const struct class class_{c_name} = \{") v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */") v.add_decl("\{") for i in [0 .. vft.length[ do @@ -645,11 +631,10 @@ class SeparateCompiler if mpropdef == null then v.add_decl("NULL, /* empty */") else - if true or mpropdef.mclassdef.bound_mtype.ctype != "val*" then - v.add_decl("(nitmethod_t)VIRTUAL_{mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") - else - v.add_decl("(nitmethod_t){mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") - end + assert mpropdef isa MMethodDef + var rf = mpropdef.virtual_runtime_function + v.require_declaration(rf.c_name) + v.add_decl("(nitmethod_t){rf.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") end end v.add_decl("\}") @@ -665,63 +650,56 @@ class SeparateCompiler if not self.runtime_type_analysis.live_types.has(mtype) then return + #Build BOX self.header.add_decl("val* BOX_{c_name}({mtype.ctype});") v.add_decl("/* allocate {mtype} */") v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{") - v.add("struct instance_{c_name}*res = GC_MALLOC(sizeof(struct instance_{c_name}));") - v.add("res->type = (struct type*) &type_{c_name};") - v.add("res->class = (struct class*) &class_{c_name};") + v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));") + v.require_declaration("type_{c_name}") + v.add("res->type = &type_{c_name};") + v.require_declaration("class_{c_name}") + v.add("res->class = &class_{c_name};") v.add("res->value = value;") v.add("return (val*)res;") v.add("\}") return - end - - var is_native_array = mclass.name == "NativeArray" - - var sig - if is_native_array then - sig = "int length, struct type* type" - else - sig = "struct type* type" - end - - #Build instance struct - #extern const struct instance_array__NativeArray instance_array__NativeArray; - self.header.add_decl("struct instance_{c_name} \{") - self.header.add_decl("const struct type *type;") - self.header.add_decl("const struct class *class;") - self.header.add_decl("nitattribute_t attrs[{attrs.length}];") - if is_native_array then + else if mclass.name == "NativeArray" then + #Build instance struct + self.header.add_decl("struct instance_{c_name} \{") + self.header.add_decl("const struct type *type;") + self.header.add_decl("const struct class *class;") # NativeArrays are just a instance header followed by an array of values self.header.add_decl("val* values[0];") - end - self.header.add_decl("\};") + self.header.add_decl("\};") + #Build NEW + self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(int length, const struct type* type);") + v.add_decl("/* allocate {mtype} */") + v.add_decl("{mtype.ctype} NEW_{c_name}(int length, const struct type* type) \{") + var res = v.new_named_var(mtype, "self") + res.is_exact = true + var mtype_elt = mtype.arguments.first + v.add("{res} = nit_alloc(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));") + v.add("{res}->type = type;") + hardening_live_type(v, "type") + v.require_declaration("class_{c_name}") + v.add("{res}->class = &class_{c_name};") + v.add("return {res};") + v.add("\}") + return + end - self.header.add_decl("{mtype.ctype} NEW_{c_name}({sig});") + #Build NEW + self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(const struct type* type);") v.add_decl("/* allocate {mtype} */") - v.add_decl("{mtype.ctype} NEW_{c_name}({sig}) \{") + v.add_decl("{mtype.ctype} NEW_{c_name}(const struct type* type) \{") var res = v.new_named_var(mtype, "self") res.is_exact = true - if is_native_array then - var mtype_elt = mtype.arguments.first - v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));") - else - v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}));") - end + v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));") v.add("{res}->type = type;") - if v.compiler.modelbuilder.toolcontext.opt_hardening.value then - v.add("if(type == NULL) \{") - v.add_abort("type null") - v.add("\}") - v.add("if(type->resolution_table == NULL) \{") - v.add("fprintf(stderr, \"Insantiation of a dead type: %s\\n\", type->name);") - v.add_abort("type dead") - v.add("\}") - end - v.add("{res}->class = (struct class*) &class_{c_name};") - + hardening_live_type(v, "type") + v.require_declaration("class_{c_name}") + v.add("{res}->class = &class_{c_name};") self.generate_init_attr(v, res, mtype) v.add("return {res};") v.add("\}") @@ -729,6 +707,19 @@ class SeparateCompiler generate_check_init_instance(mtype) end + # Add a dynamic test to ensure that the type referenced by `t` is a live type + fun hardening_live_type(v: VISITOR, t: String) + do + if not v.compiler.modelbuilder.toolcontext.opt_hardening.value then return + v.add("if({t} == NULL) \{") + v.add_abort("type null") + v.add("\}") + v.add("if({t}->resolution_table == NULL) \{") + v.add("fprintf(stderr, \"Insantiation of a dead type: %s\\n\", {t}->name);") + v.add_abort("type dead") + v.add("\}") + end + redef fun generate_check_init_instance(mtype) do if self.modelbuilder.toolcontext.opt_no_check_initialization.value then return @@ -736,7 +727,7 @@ class SeparateCompiler var v = self.new_visitor var c_name = mtype.mclass.c_name var res = new RuntimeVariable("self", mtype, mtype) - self.header.add_decl("void CHECK_NEW_{c_name}({mtype.ctype});") + self.provide_declaration("CHECK_NEW_{c_name}", "void CHECK_NEW_{c_name}({mtype.ctype});") v.add_decl("/* allocate {mtype} */") v.add_decl("void CHECK_NEW_{c_name}({mtype.ctype} {res}) \{") self.generate_check_attr(v, res, mtype) @@ -860,6 +851,7 @@ class SeparateCompilerVisitor if value.mtype.ctype == "val*" then return "{value}->type" else + self.require_declaration("type_{value.mtype.c_name}") return "(&type_{value.mtype.c_name})" end end @@ -948,6 +940,7 @@ class SeparateCompilerVisitor var r if ret == null then r = "void" else r = ret.ctype + self.require_declaration(mmethod.const_color) var call = "(({r} (*)({s}))({arguments.first}->class->vft[{mmethod.const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/" if res != null then @@ -996,6 +989,7 @@ class SeparateCompilerVisitor # Autobox arguments self.adapt_signature(mmethoddef, arguments) + self.require_declaration(mmethoddef.c_name) if res == null then self.add("{mmethoddef.c_name}({arguments.join(", ")});") return null @@ -1047,6 +1041,7 @@ class SeparateCompilerVisitor return res end + self.require_declaration(a.const_color) if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then self.add("{res} = {recv}->attrs[{a.const_color}] != NULL; /* {a} on {recv.inspect}*/") else @@ -1069,6 +1064,7 @@ class SeparateCompilerVisitor var intromclassdef = a.intro.mclassdef ret = ret.resolve_for(intromclassdef.bound_mtype, intromclassdef.bound_mtype, intromclassdef.mmodule, true) + self.require_declaration(a.const_color) if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then # Get the attribute or a box (ie. always a val*) var cret = self.object_type.as_nullable @@ -1114,6 +1110,7 @@ class SeparateCompilerVisitor # Adapt the value to the declared type value = self.autobox(value, mtype) + self.require_declaration(a.const_color) if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then var attr = "{recv}->attrs[{a.const_color}]" if mtype.ctype != "val*" then @@ -1137,24 +1134,28 @@ class SeparateCompilerVisitor redef fun init_instance(mtype) do + self.require_declaration("NEW_{mtype.mclass.c_name}") var compiler = self.compiler if mtype isa MGenericType and mtype.need_anchor then link_unresolved_type(self.frame.mpropdef.mclassdef, mtype) var recv = self.frame.arguments.first var recv_type_info = self.type_info(recv) + self.require_declaration(mtype.const_color) if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then - return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) else - return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) end end compiler.undead_types.add(mtype) - return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) &type_{mtype.c_name})", mtype) + self.require_declaration("type_{mtype.c_name}") + return self.new_expr("NEW_{mtype.mclass.c_name}(&type_{mtype.c_name})", mtype) end redef fun check_init_instance(value, mtype) do if self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then return + self.require_declaration("CHECK_NEW_{mtype.mclass.c_name}") self.add("CHECK_NEW_{mtype.mclass.c_name}({value});") end @@ -1192,10 +1193,11 @@ class SeparateCompilerVisitor if ntype.need_anchor then var type_struct = self.get_name("type_struct") - self.add_decl("struct type* {type_struct};") + self.add_decl("const struct type* {type_struct};") # Either with resolution_table with a direct resolution link_unresolved_type(self.frame.mpropdef.mclassdef, ntype) + self.require_declaration(ntype.const_color) if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then self.add("{type_struct} = {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {ntype.const_color})];") else @@ -1215,6 +1217,7 @@ class SeparateCompilerVisitor end else if ntype isa MClassType then compiler.undead_types.add(mtype) + self.require_declaration("type_{mtype.c_name}") self.add("{cltype} = type_{mtype.c_name}.color;") self.add("{idtype} = type_{mtype.c_name}.id;") if compiler.modelbuilder.toolcontext.opt_typing_test_metrics.value then @@ -1263,7 +1266,8 @@ class SeparateCompilerVisitor self.add("{res} = 0; /* is_same_type_test: incompatible types {value1.mtype} vs. {value2.mtype}*/") else var mtype1 = value1.mtype.as(MClassType) - self.add("{res} = ({value2} != NULL) && ({value2}->class == (struct class*) &class_{mtype1.c_name}); /* is_same_type_test */") + self.require_declaration("class_{mtype1.c_name}") + self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name}); /* is_same_type_test */") end else self.add("{res} = ({value1} == {value2}) || ({value1} != NULL && {value2} != NULL && {value1}->class == {value2}->class); /* is_same_type_test */") @@ -1278,6 +1282,7 @@ class SeparateCompilerVisitor if value.mtype.ctype == "val*" then self.add "{res} = {value} == NULL ? \"null\" : {value}->type->name;" else + self.require_declaration("type_{value.mtype.c_name}") self.add "{res} = type_{value.mtype.c_name}.name;" end return res @@ -1298,7 +1303,8 @@ class SeparateCompilerVisitor self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/") else var mtype1 = value1.mtype.as(MClassType) - self.add("{res} = ({value2} != NULL) && ({value2}->class == (struct class*) &class_{mtype1.c_name});") + self.require_declaration("class_{mtype1.c_name}") + self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name});") self.add("if ({res}) \{") self.add("{res} = ({self.autobox(value2, value1.mtype)} == {value1});") self.add("\}") @@ -1409,20 +1415,23 @@ class SeparateCompilerVisitor fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable do var mtype = self.get_class("NativeArray").get_mtype([elttype]) + self.require_declaration("NEW_{mtype.mclass.c_name}") assert mtype isa MGenericType var compiler = self.compiler if mtype.need_anchor then link_unresolved_type(self.frame.mpropdef.mclassdef, mtype) var recv = self.frame.arguments.first var recv_type_info = self.type_info(recv) + self.require_declaration(mtype.const_color) if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then - return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({length}, {recv_type_info}->resolution_table->types[HASH({recv_type_info}->resolution_table->mask, {mtype.const_color})])", mtype) else - return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) + return self.new_expr("NEW_{mtype.mclass.c_name}({length}, {recv_type_info}->resolution_table->types[{mtype.const_color}])", mtype) end end compiler.undead_types.add(mtype) - return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) &type_{mtype.c_name})", mtype) + self.require_declaration("type_{mtype.c_name}") + return self.new_expr("NEW_{mtype.mclass.c_name}({length}, &type_{mtype.c_name})", mtype) end redef fun native_array_def(pname, ret_type, arguments) @@ -1461,6 +1470,30 @@ class SeparateCompilerVisitor end end +redef class MMethodDef + fun separate_runtime_function: AbstractRuntimeFunction + do + var res = self.separate_runtime_function_cache + if res == null then + res = new SeparateRuntimeFunction(self) + self.separate_runtime_function_cache = res + end + return res + end + private var separate_runtime_function_cache: nullable SeparateRuntimeFunction + + fun virtual_runtime_function: AbstractRuntimeFunction + do + var res = self.virtual_runtime_function_cache + if res == null then + res = new VirtualRuntimeFunction(self) + self.virtual_runtime_function_cache = res + end + return res + end + private var virtual_runtime_function_cache: nullable VirtualRuntimeFunction +end + # The C function associated to a methoddef separately compiled class SeparateRuntimeFunction super AbstractRuntimeFunction @@ -1495,7 +1528,7 @@ class SeparateRuntimeFunction end sig.append(self.c_name) sig.append("({selfvar.mtype.ctype} {selfvar}") - comment.append("(self: {selfvar}") + comment.append("({selfvar}: {selfvar.mtype}") arguments.add(selfvar) for i in [0..msignature.arity[ do var mtype = msignature.mparameters[i].mtype @@ -1512,7 +1545,7 @@ class SeparateRuntimeFunction if ret != null then comment.append(": {ret}") end - compiler.header.add_decl("{sig};") + compiler.provide_declaration(self.c_name, "{sig};") v.add_decl("/* method {self} for {comment} */") v.add_decl("{sig} \{") @@ -1571,7 +1604,7 @@ class VirtualRuntimeFunction end sig.append(self.c_name) sig.append("({selfvar.mtype.ctype} {selfvar}") - comment.append("(self: {selfvar}") + comment.append("({selfvar}: {selfvar.mtype}") arguments.add(selfvar) for i in [0..msignature.arity[ do var mtype = msignature.mparameters[i].mtype @@ -1588,7 +1621,7 @@ class VirtualRuntimeFunction if ret != null then comment.append(": {ret}") end - compiler.header.add_decl("{sig};") + compiler.provide_declaration(self.c_name, "{sig};") v.add_decl("/* method {self} for {comment} */") v.add_decl("{sig} \{") @@ -1597,10 +1630,11 @@ class VirtualRuntimeFunction end frame.returnlabel = v.get_name("RET_LABEL") - if recv != arguments.first.mtype then - #print "{self} {recv} {arguments.first}" + var subret = v.call(mmethoddef, recv, arguments) + if ret != null then + assert subret != null + v.assign(frame.returnvar.as(not null), subret) end - mmethoddef.compile_inside_to_c(v, arguments) v.add("{frame.returnlabel.as(not null)}:;") if ret != null then diff --git a/src/separate_erasure_compiler.nit b/src/separate_erasure_compiler.nit index 1442af0..d8bb170 100644 --- a/src/separate_erasure_compiler.nit +++ b/src/separate_erasure_compiler.nit @@ -41,20 +41,22 @@ redef class ModelBuilder compiler.compile_header # compile class structures - compiler.new_file + compiler.new_file("{mainmodule.name}.tables") + compiler.do_property_coloring for m in mainmodule.in_importation.greaters do for mclass in m.intro_mclasses do compiler.compile_class_to_c(mclass) end end + compiler.compile_color_consts(compiler.vt_layout.pos) # The main function of the C - compiler.new_file + compiler.new_file("{mainmodule.name}.main") compiler.compile_main_function # compile methods for m in mainmodule.in_importation.greaters do - compiler.new_file + compiler.new_file("{m.name}.sep") compiler.compile_module_to_c(m) end @@ -92,7 +94,6 @@ class SeparateErasureCompiler var vt_coloring = new MVirtualTypePropColorer(mainmodule) var vt_layout = vt_coloring.build_layout(mclasses) self.vt_tables = build_vt_tables(mclasses, vt_layout) - self.compile_color_consts(vt_layout.pos) self.vt_layout = vt_layout end @@ -171,14 +172,14 @@ class SeparateErasureCompiler redef fun compile_header_structs do self.header.add_decl("typedef void(*nitmethod_t)(void); /* general C type representing a Nit method. */") self.compile_header_attribute_structs - self.header.add_decl("struct class \{ int id; const char *name; int box_kind; int color; struct vts_table *vts_table; struct type_table *type_table; nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */") - self.header.add_decl("struct type_table \{ int size; int table[1]; \}; /* colorized type table. */") - self.header.add_decl("struct vts_entry \{ short int is_nullable; struct class *class; \}; /* link (nullable or not) between the vts and is bound. */") + self.header.add_decl("struct class \{ int id; const char *name; int box_kind; int color; const struct vts_table *vts_table; const struct type_table *type_table; nitmethod_t vft[]; \}; /* general C type representing a Nit class. */") + self.header.add_decl("struct type_table \{ int size; int table[]; \}; /* colorized type table. */") + self.header.add_decl("struct vts_entry \{ short int is_nullable; const struct class *class; \}; /* link (nullable or not) between the vts and is bound. */") if self.vt_layout isa PHLayout[MClass, MVirtualTypeProp] then - self.header.add_decl("struct vts_table \{ int mask; struct vts_entry vts[1]; \}; /* vts list of a C type representation. */") + self.header.add_decl("struct vts_table \{ int mask; const struct vts_entry vts[]; \}; /* vts list of a C type representation. */") else - self.header.add_decl("struct vts_table \{ struct vts_entry vts[1]; \}; /* vts list of a C type representation. */") + self.header.add_decl("struct vts_table \{ int dummy; const struct vts_entry vts[]; \}; /* vts list of a C type representation. */") end if modelbuilder.toolcontext.opt_phmod_typing.value then @@ -187,7 +188,7 @@ class SeparateErasureCompiler self.header.add_decl("#define HASH(mask, id) ((mask)&(id))") end - self.header.add_decl("typedef struct val \{ struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */") + self.header.add_decl("typedef struct instance \{ const struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */") end redef fun compile_class_to_c(mclass: MClass) @@ -202,19 +203,11 @@ class SeparateErasureCompiler v.add_decl("/* runtime class {c_name} */") - self.header.add_decl("extern const struct class_{c_name} class_{c_name};") - self.header.add_decl("struct class_{c_name} \{") - self.header.add_decl("int id;") - self.header.add_decl("const char *name;") - self.header.add_decl("int box_kind;") - self.header.add_decl("int color;") - self.header.add_decl("const struct vts_table *vts_table;") - self.header.add_decl("struct type_table *type_table;") - self.header.add_decl("nitmethod_t vft[{vft.length}];") - self.header.add_decl("\};") + self.provide_declaration("class_{c_name}", "extern const struct class class_{c_name};") + v.add_decl("extern const struct type_table type_table_{c_name};") # Build class vft - v.add_decl("const struct class_{c_name} class_{c_name} = \{") + v.add_decl("const struct class class_{c_name} = \{") v.add_decl("{self.class_layout.ids[mclass]},") v.add_decl("\"{mclass.name}\", /* class_name_string */") v.add_decl("{self.box_kind_of(mclass)}, /* box_kind */") @@ -225,11 +218,12 @@ class SeparateErasureCompiler v.add_decl("{layout.pos[mclass]},") end if build_class_vts_table(mclass) then - v.add_decl("(const struct vts_table*) &vts_table_{c_name},") + v.require_declaration("vts_table_{c_name}") + v.add_decl("&vts_table_{c_name},") else v.add_decl("NULL,") end - v.add_decl("(struct type_table*) &type_table_{c_name},") + v.add_decl("&type_table_{c_name},") v.add_decl("\{") for i in [0 .. vft.length[ do var mpropdef = vft[i] @@ -237,8 +231,10 @@ class SeparateErasureCompiler v.add_decl("NULL, /* empty */") else if true or mpropdef.mclassdef.bound_mtype.ctype != "val*" then + v.require_declaration("VIRTUAL_{mpropdef.c_name}") v.add_decl("(nitmethod_t)VIRTUAL_{mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") else + v.require_declaration("{mpropdef.c_name}") v.add_decl("(nitmethod_t){mpropdef.c_name}, /* pointer to {mclass.intro_mmodule}:{mclass}:{mpropdef} */") end end @@ -247,13 +243,8 @@ class SeparateErasureCompiler v.add_decl("\};") # Build class type table - self.header.add_decl("extern const struct type_table_{c_name} type_table_{c_name};") - self.header.add_decl("struct type_table_{c_name} \{") - self.header.add_decl("int size;") - self.header.add_decl("int table[{class_table.length}];") - self.header.add_decl("\};") - v.add_decl("const struct type_table_{c_name} type_table_{c_name} = \{") + v.add_decl("const struct type_table type_table_{c_name} = \{") v.add_decl("{class_table.length},") v.add_decl("\{") for msuper in class_table do @@ -266,58 +257,55 @@ class SeparateErasureCompiler v.add_decl("\}") v.add_decl("\};") - #Build instance struct if mtype.ctype != "val*" then + #Build instance struct self.header.add_decl("struct instance_{c_name} \{") self.header.add_decl("const struct class *class;") self.header.add_decl("{mtype.ctype} value;") self.header.add_decl("\};") + #Build BOX self.header.add_decl("val* BOX_{c_name}({mtype.ctype});") v.add_decl("/* allocate {mtype} */") v.add_decl("val* BOX_{mtype.c_name}({mtype.ctype} value) \{") - v.add("struct instance_{c_name}*res = GC_MALLOC(sizeof(struct instance_{c_name}));") - v.add("res->class = (struct class*) &class_{c_name};") + v.add("struct instance_{c_name}*res = nit_alloc(sizeof(struct instance_{c_name}));") + v.require_declaration("class_{c_name}") + v.add("res->class = &class_{c_name};") v.add("res->value = value;") v.add("return (val*)res;") v.add("\}") return - end - - var is_native_array = mclass.name == "NativeArray" - - var sig - if is_native_array then - sig = "int length" - else - sig = "" - end + else if mclass.name == "NativeArray" then + #Build instance struct + self.header.add_decl("struct instance_{c_name} \{") + self.header.add_decl("const struct class *class;") + self.header.add_decl("val* values[];") + self.header.add_decl("\};") - #Build instance struct - #extern const struct instance_array__NativeArray instance_array__NativeArray; - self.header.add_decl("struct instance_{c_name} \{") - self.header.add_decl("const struct class *class;") - self.header.add_decl("nitattribute_t attrs[{attrs.length}];") - if is_native_array then - # NativeArrays are just a instance header followed by an array of values - self.header.add_decl("val* values[0];") + #Build NEW + self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(int length);") + v.add_decl("/* allocate {mtype} */") + v.add_decl("{mtype.ctype} NEW_{c_name}(int length) \{") + var res = v.new_named_var(mtype, "self") + res.is_exact = true + var mtype_elt = mtype.arguments.first + v.add("{res} = nit_alloc(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));") + v.require_declaration("class_{c_name}") + v.add("{res}->class = &class_{c_name};") + v.add("return {res};") + v.add("\}") + return end - self.header.add_decl("\};") - - self.header.add_decl("{mtype.ctype} NEW_{c_name}({sig});") + #Build NEW + self.provide_declaration("NEW_{c_name}", "{mtype.ctype} NEW_{c_name}(void);") v.add_decl("/* allocate {mtype} */") - v.add_decl("{mtype.ctype} NEW_{c_name}({sig}) \{") + v.add_decl("{mtype.ctype} NEW_{c_name}(void) \{") var res = v.new_named_var(mtype, "self") res.is_exact = true - if is_native_array then - var mtype_elt = mtype.arguments.first - v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}) + length*sizeof({mtype_elt.ctype}));") - else - v.add("{res} = GC_MALLOC(sizeof(struct instance_{c_name}));") - end - v.add("{res}->class = (struct class*) &class_{c_name};") - + v.add("{res} = nit_alloc(sizeof(struct instance) + {attrs.length}*sizeof(nitattribute_t));") + v.require_declaration("class_{c_name}") + v.add("{res}->class = &class_{c_name};") self.generate_init_attr(v, res, mtype) v.add("return {res};") v.add("\}") @@ -328,19 +316,15 @@ class SeparateErasureCompiler private fun build_class_vts_table(mclass: MClass): Bool do if self.vt_tables[mclass].is_empty then return false - self.header.add_decl("extern const struct vts_table_{mclass.c_name} vts_table_{mclass.c_name};") - self.header.add_decl("struct vts_table_{mclass.c_name} \{") - if self.vt_layout isa PHLayout[MClass, MVirtualTypeProp] then - self.header.add_decl("int mask;") - end - self.header.add_decl("struct vts_entry vts[{self.vt_tables[mclass].length}];") - self.header.add_decl("\};") + self.provide_declaration("vts_table_{mclass.c_name}", "extern const struct vts_table vts_table_{mclass.c_name};") var v = new_visitor - v.add_decl("const struct vts_table_{mclass.c_name} vts_table_{mclass.c_name} = \{") + v.add_decl("const struct vts_table vts_table_{mclass.c_name} = \{") if self.vt_layout isa PHLayout[MClass, MVirtualTypeProp] then #TODO redo this when PHPropertyLayoutBuilder will be implemented #v.add_decl("{vt_masks[mclass]},") + else + v.add_decl("0, /* dummy */") end v.add_decl("\{") @@ -354,7 +338,9 @@ class SeparateErasureCompiler bound = retrieve_vt_bound(mclass.intro.bound_mtype, bound.mtype) is_null = 1 end - v.add_decl("\{{is_null}, (struct class*)&class_{bound.as(MClassType).mclass.c_name}\}, /* {vt} */") + var vtclass = bound.as(MClassType).mclass + v.require_declaration("class_{vtclass.c_name}") + v.add_decl("\{{is_null}, &class_{vtclass.c_name}\}, /* {vt} */") end end v.add_decl("\},") @@ -449,7 +435,11 @@ class SeparateErasureCompilerVisitor return res end - redef fun init_instance(mtype) do return self.new_expr("NEW_{mtype.mclass.c_name}()", mtype) + redef fun init_instance(mtype) + do + self.require_declaration("NEW_{mtype.mclass.c_name}") + return self.new_expr("NEW_{mtype.mclass.c_name}()", mtype) + end redef fun type_test(value, mtype, tag) do @@ -492,10 +482,12 @@ class SeparateErasureCompilerVisitor class_ptr = "{value}->class->" else var mclass = value.mtype.as(MClassType).mclass + self.require_declaration("class_{mclass.c_name}") class_ptr = "class_{mclass.c_name}." end if mtype isa MClassType then + self.require_declaration("class_{mtype.mclass.c_name}") self.add("{cltype} = class_{mtype.mclass.c_name}.color;") self.add("{idtype} = class_{mtype.mclass.c_name}.id;") if compiler.modelbuilder.toolcontext.opt_typing_test_metrics.value then @@ -509,10 +501,12 @@ class SeparateErasureCompilerVisitor recv_ptr = "{recv}->class->" else var mclass = recv.mtype.as(MClassType).mclass + self.require_declaration("class_{mclass.c_name}") recv_ptr = "class_{mclass.c_name}." end var entry = self.get_name("entry") self.add("struct vts_entry {entry};") + self.require_declaration(mtype.mproperty.const_color) if self.compiler.as(SeparateErasureCompiler).vt_layout isa PHLayout[MClass, MVirtualTypeProp] then self.add("{entry} = {recv_ptr}vts_table->vts[HASH({recv_ptr}vts_table->mask, {mtype.mproperty.const_color})];") else @@ -563,6 +557,7 @@ class SeparateErasureCompilerVisitor if value.mtype.ctype == "val*" then self.add "{res} = {value} == NULL ? \"null\" : {value}->class->name;" else + self.require_declaration("class_{value.mtype.c_name}") self.add "{res} = class_{value.mtype.c_name}.name;" end return res @@ -577,6 +572,7 @@ class SeparateErasureCompilerVisitor self.add("\{ /* {res} = array_instance Array[{elttype}] */") var nat = self.new_var(self.get_class("NativeArray").get_mtype([elttype])) nat.is_exact = true + self.require_declaration("NEW_{nclass.c_name}") self.add("{nat} = NEW_{nclass.c_name}({array.length});") for i in [0..array.length[ do var r = self.autobox(array[i], self.object_type) @@ -592,6 +588,7 @@ class SeparateErasureCompilerVisitor redef fun calloc_array(ret_type, arguments) do var ret = ret_type.as(MClassType) + self.require_declaration("NEW_{ret.mclass.c_name}") self.ret(self.new_expr("NEW_{ret.mclass.c_name}({arguments[1]})", ret_type)) end end diff --git a/src/test_parser.nit b/src/test_parser.nit index 8824764..98669e2 100644 --- a/src/test_parser.nit +++ b/src/test_parser.nit @@ -87,6 +87,12 @@ else var tree = parser.parse f.close + var error = tree.n_eof + if error isa AError then + print("Error at {error.location}:\n\t{error.message}") + return + end + if not no_print then (new PrintTreeVisitor).enter_visit(tree) end diff --git a/tests/base_virtual_type3.nit b/tests/base_virtual_type3.nit index c2794fe..929d84a 100644 --- a/tests/base_virtual_type3.nit +++ b/tests/base_virtual_type3.nit @@ -14,8 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -import base_virtual_type2 import array +import base_virtual_type2 class C super A diff --git a/tests/sav/fixme/base_virtual_type3.res b/tests/sav/fixme/base_virtual_type3.res deleted file mode 100644 index 27035df..0000000 --- a/tests/sav/fixme/base_virtual_type3.res +++ /dev/null @@ -1,87 +0,0 @@ -../lib/standard/collection/array.nit:24,21--27: Error: No property AbstractArrayRead::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:26,12--19: Error: No property AbstractArrayRead::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:28,12--14: Error: No property AbstractArrayRead::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:39,12--19: Error: No property AbstractArrayRead::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:50,12--16: Error: No property AbstractArrayRead::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:62,12--19: Error: No property AbstractArrayRead::index_of is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:83,12--19: Error: No property NaiveCollection::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:85,12--17: Error: No property NaiveCollection::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:92,12--14: Error: No property NaiveCollection::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:98,12--19: Error: No property NaiveCollection::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:104,12--16: Error: No property NaiveCollection::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:111,12--16: Error: No property NaiveCollection::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:128,12--17: Error: No property AbstractArrayRead::output is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:137,12--16: Error: No property Container::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:139,12--19: Error: No property AbstractArrayRead::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:139,12--19: Error: No property Container::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:141,12--17: Error: No property Container::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:142,12--13: Error: No property AbstractArrayRead::== is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:143,12--14: Error: No property Container::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:145,12--19: Error: No property Container::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:147,12--16: Error: No property Container::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:156,12--19: Error: No property Container::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:166,12--15: Error: No property AbstractArray::push is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:168,12--14: Error: No property AbstractArray::pop is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:168,12--15: Error: No property ContainerIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:170,12--15: Error: No property ContainerIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:174,21--26: Error: No property ContainerIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:176,12--16: Error: No property AbstractArray::shift is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:190,12--18: Error: No property AbstractArray::unshift is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:212,12--14: Error: No property AbstractArray::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:214,12--16: Error: No property AbstractArray::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:215,12--19: Error: No property Set::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:216,12--17: Error: No property AbstractArray::remove is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:218,12--21: Error: No property AbstractArray::remove_all is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:227,12--20: Error: No property AbstractArray::remove_at is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:228,12--16: Error: No property Set::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:238,12--21: Error: No property Set::remove_all is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:266,12--18: Error: No property Array::iterate is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:278,12--13: Error: No property Array::[] is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:284,12--14: Error: No property Array::[]= is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:296,12--14: Error: No property Array::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:306,12--18: Error: No property Array::enlarge is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:321,12--17: Error: No property Map::values is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:323,12--15: Error: No property Map::keys is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:375,12--16: Error: No property SequenceRead::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:407,12--19: Error: No property SequenceRead::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:431,12--15: Error: No property ArrayIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:434,12--14: Error: No property Sequence::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:435,12--16: Error: No property ArrayIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:437,12--15: Error: No property ArrayIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:445,21--26: Error: No property ArrayIterator::index is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:458,12--14: Error: No property ArraySet::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:460,12--14: Error: No property ArraySet::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:462,12--19: Error: No property ArraySet::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:464,12--17: Error: No property ArraySet::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:466,12--16: Error: No property ArraySet::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:472,12--17: Error: No property ArraySet::remove is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:473,12--13: Error: No property CoupleMap::[] is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:478,12--21: Error: No property ArraySet::remove_all is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:480,12--16: Error: No property ArraySet::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:482,12--19: Error: No property ArraySet::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:489,12--15: Error: No property CoupleMapIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:493,12--14: Error: No property CoupleMapIterator::key is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:495,12--16: Error: No property CoupleMapIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:497,12--15: Error: No property CoupleMapIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:504,12--16: Error: No property ArraySetIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:506,12--15: Error: No property ArraySetIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:508,12--15: Error: No property ArraySetIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:521,12--13: Error: No property ArrayMap::[] is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:532,12--14: Error: No property ArrayMap::[]= is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:542,12--15: Error: No property ArrayMap::keys is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:543,12--17: Error: No property ArrayMap::values is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:546,12--17: Error: No property ArrayMap::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:548,12--19: Error: No property ArrayMap::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:550,12--19: Error: No property ArrayMap::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:552,12--16: Error: No property ArrayMap::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:557,12--20: Error: No property ArrayMap::couple_at is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:629,12--16: Error: No property ArrayMapValues::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:630,12--19: Error: No property ArrayMapValues::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:631,12--17: Error: No property ArrayMapValues::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:632,12--19: Error: No property ArrayMapValues::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:635,12--14: Error: No property ArrayMapValues::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:642,12--19: Error: No property ArrayMapValues::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:649,12--16: Error: No property ArrayMapValues::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:656,12--16: Error: No property ArrayMapValues::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:658,12--17: Error: No property ArrayMapValues::remove is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:671,12--21: Error: No property ArrayMapValues::remove_all is inherited. Remove the redef keyword to define a new property. diff --git a/tests/sav/fixme/base_virtual_type3_alt1.res b/tests/sav/fixme/base_virtual_type3_alt1.res deleted file mode 100644 index 27035df..0000000 --- a/tests/sav/fixme/base_virtual_type3_alt1.res +++ /dev/null @@ -1,87 +0,0 @@ -../lib/standard/collection/array.nit:24,21--27: Error: No property AbstractArrayRead::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:26,12--19: Error: No property AbstractArrayRead::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:28,12--14: Error: No property AbstractArrayRead::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:39,12--19: Error: No property AbstractArrayRead::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:50,12--16: Error: No property AbstractArrayRead::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:62,12--19: Error: No property AbstractArrayRead::index_of is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:83,12--19: Error: No property NaiveCollection::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:85,12--17: Error: No property NaiveCollection::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:92,12--14: Error: No property NaiveCollection::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:98,12--19: Error: No property NaiveCollection::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:104,12--16: Error: No property NaiveCollection::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:111,12--16: Error: No property NaiveCollection::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:128,12--17: Error: No property AbstractArrayRead::output is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:137,12--16: Error: No property Container::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:139,12--19: Error: No property AbstractArrayRead::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:139,12--19: Error: No property Container::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:141,12--17: Error: No property Container::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:142,12--13: Error: No property AbstractArrayRead::== is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:143,12--14: Error: No property Container::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:145,12--19: Error: No property Container::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:147,12--16: Error: No property Container::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:156,12--19: Error: No property Container::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:166,12--15: Error: No property AbstractArray::push is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:168,12--14: Error: No property AbstractArray::pop is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:168,12--15: Error: No property ContainerIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:170,12--15: Error: No property ContainerIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:174,21--26: Error: No property ContainerIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:176,12--16: Error: No property AbstractArray::shift is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:190,12--18: Error: No property AbstractArray::unshift is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:212,12--14: Error: No property AbstractArray::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:214,12--16: Error: No property AbstractArray::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:215,12--19: Error: No property Set::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:216,12--17: Error: No property AbstractArray::remove is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:218,12--21: Error: No property AbstractArray::remove_all is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:227,12--20: Error: No property AbstractArray::remove_at is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:228,12--16: Error: No property Set::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:238,12--21: Error: No property Set::remove_all is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:266,12--18: Error: No property Array::iterate is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:278,12--13: Error: No property Array::[] is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:284,12--14: Error: No property Array::[]= is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:296,12--14: Error: No property Array::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:306,12--18: Error: No property Array::enlarge is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:321,12--17: Error: No property Map::values is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:323,12--15: Error: No property Map::keys is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:375,12--16: Error: No property SequenceRead::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:407,12--19: Error: No property SequenceRead::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:431,12--15: Error: No property ArrayIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:434,12--14: Error: No property Sequence::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:435,12--16: Error: No property ArrayIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:437,12--15: Error: No property ArrayIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:445,21--26: Error: No property ArrayIterator::index is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:458,12--14: Error: No property ArraySet::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:460,12--14: Error: No property ArraySet::add is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:462,12--19: Error: No property ArraySet::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:464,12--17: Error: No property ArraySet::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:466,12--16: Error: No property ArraySet::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:472,12--17: Error: No property ArraySet::remove is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:473,12--13: Error: No property CoupleMap::[] is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:478,12--21: Error: No property ArraySet::remove_all is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:480,12--16: Error: No property ArraySet::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:482,12--19: Error: No property ArraySet::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:489,12--15: Error: No property CoupleMapIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:493,12--14: Error: No property CoupleMapIterator::key is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:495,12--16: Error: No property CoupleMapIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/abstract_collection.nit:497,12--15: Error: No property CoupleMapIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:504,12--16: Error: No property ArraySetIterator::is_ok is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:506,12--15: Error: No property ArraySetIterator::next is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:508,12--15: Error: No property ArraySetIterator::item is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:521,12--13: Error: No property ArrayMap::[] is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:532,12--14: Error: No property ArrayMap::[]= is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:542,12--15: Error: No property ArrayMap::keys is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:543,12--17: Error: No property ArrayMap::values is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:546,12--17: Error: No property ArrayMap::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:548,12--19: Error: No property ArrayMap::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:550,12--19: Error: No property ArrayMap::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:552,12--16: Error: No property ArrayMap::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:557,12--20: Error: No property ArrayMap::couple_at is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:629,12--16: Error: No property ArrayMapValues::first is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:630,12--19: Error: No property ArrayMapValues::is_empty is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:631,12--17: Error: No property ArrayMapValues::length is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:632,12--19: Error: No property ArrayMapValues::iterator is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:635,12--14: Error: No property ArrayMapValues::has is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:642,12--19: Error: No property ArrayMapValues::has_only is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:649,12--16: Error: No property ArrayMapValues::count is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:656,12--16: Error: No property ArrayMapValues::clear is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:658,12--17: Error: No property ArrayMapValues::remove is inherited. Remove the redef keyword to define a new property. -../lib/standard/collection/array.nit:671,12--21: Error: No property ArrayMapValues::remove_all is inherited. Remove the redef keyword to define a new property. diff --git a/tests/sav/string_ffi_ref_test.sav b/tests/sav/string_ffi_ref_test.sav new file mode 100644 index 0000000..e9856d5 --- /dev/null +++ b/tests/sav/string_ffi_ref_test.sav @@ -0,0 +1,3 @@ +This is a test string +This is a test string +Do the strings have the same NativeString reference ? False diff --git a/tests/sav/string_trim.sav b/tests/sav/string_trim.sav new file mode 100644 index 0000000..24d9987 --- /dev/null +++ b/tests/sav/string_trim.sav @@ -0,0 +1,13 @@ +resulttrim = nono nono +returntrim + nono nono +thirdtrim = nono nono +emptytrim = +bufferemptytrim = +onelettertrim = d +oneletterbuftest = d +twolettertrim = hg +twoletterbuftest = hg +firstlettertrimtest = d +firstlettertrimbuftest = d +lastlettertrimtest = d +lastlettertrimbuftest = d diff --git a/tests/sav/test_parser.sav b/tests/sav/test_parser.res similarity index 100% rename from tests/sav/test_parser.sav rename to tests/sav/test_parser.res diff --git a/tests/sav/test_parser_args1.sav b/tests/sav/test_parser_args1.res similarity index 86% rename from tests/sav/test_parser_args1.sav rename to tests/sav/test_parser_args1.res index 5ce5f8f..ecf3dad 100644 --- a/tests/sav/test_parser_args1.sav +++ b/tests/sav/test_parser_args1.res @@ -1,5 +1,5 @@ -../src/test_parser.nit:17,1--96,1 - ../src/test_parser.nit:17,1--95,3 +../src/test_parser.nit:17,1--102,1 + ../src/test_parser.nit:17,1--101,3 ../src/test_parser.nit:17,1--18,19 ../src/test_parser.nit:17,1--18,0 '# Program used to test the NIT parser @@ -161,9 +161,9 @@ literal value '0' ... ../src/test_parser.nit:40,11 keyword 'end' ... ../src/test_parser.nit:41,2--4 keyword 'end' ... ../src/test_parser.nit:42,1--3 - ../src/test_parser.nit:44,1--95,3 - ../src/test_parser.nit:44,1--95,3 - ../src/test_parser.nit:44,1--95,3 + ../src/test_parser.nit:44,1--101,3 + ../src/test_parser.nit:44,1--101,3 + ../src/test_parser.nit:44,1--101,3 ../src/test_parser.nit:44,1--20 keyword 'var' ... ../src/test_parser.nit:44,1--3 identifier 'no_print' ... ../src/test_parser.nit:44,5--12 @@ -339,7 +339,7 @@ identifier 'shift' ... ../src/test_parser.nit:61,7--11 ../src/test_parser.nit:61,2 keyword 'end' ... ../src/test_parser.nit:62,1--3 - ../src/test_parser.nit:64,1--95,3 + ../src/test_parser.nit:64,1--101,3 keyword 'if' ... ../src/test_parser.nit:64,1--2 ../src/test_parser.nit:64,4--29 ../src/test_parser.nit:64,4--16 @@ -410,8 +410,8 @@ ../src/test_parser.nit:71,8--29 literal value '" -h print this help"' ... ../src/test_parser.nit:71,8--29 ')' ... ../src/test_parser.nit:71,30 - ../src/test_parser.nit:73,2--95,3 - ../src/test_parser.nit:73,2--94,4 + ../src/test_parser.nit:73,2--101,3 + ../src/test_parser.nit:73,2--100,4 keyword 'for' ... ../src/test_parser.nit:73,2--4 identifier 'a' ... ../src/test_parser.nit:73,6 ../src/test_parser.nit:73,11--14 @@ -419,7 +419,7 @@ identifier 'args' ... ../src/test_parser.nit:73,11--14 ../src/test_parser.nit:73,11 keyword 'do' ... ../src/test_parser.nit:73,16--17 - ../src/test_parser.nit:74,3--94,4 + ../src/test_parser.nit:74,3--100,4 ../src/test_parser.nit:74,3--30 keyword 'var' ... ../src/test_parser.nit:74,3--5 identifier 'f' ... ../src/test_parser.nit:74,7 @@ -462,7 +462,7 @@ ../src/test_parser.nit:75,43 ')' ... ../src/test_parser.nit:75,44 ')' ... ../src/test_parser.nit:75,45 - ../src/test_parser.nit:76,3--93,5 + ../src/test_parser.nit:76,3--99,5 keyword 'if' ... ../src/test_parser.nit:76,3--4 ../src/test_parser.nit:76,6--15 ../src/test_parser.nit:76,6 @@ -551,7 +551,7 @@ ../src/test_parser.nit:84,4 identifier 'close' ... ../src/test_parser.nit:84,6--10 ../src/test_parser.nit:84,4 - ../src/test_parser.nit:86,4--93,5 + ../src/test_parser.nit:86,4--99,5 ../src/test_parser.nit:86,4--33 keyword 'var' ... ../src/test_parser.nit:86,4--6 identifier 'parser' ... ../src/test_parser.nit:86,8--13 @@ -585,35 +585,87 @@ ../src/test_parser.nit:88,4 identifier 'close' ... ../src/test_parser.nit:88,6--10 ../src/test_parser.nit:88,4 - ../src/test_parser.nit:90,4--92,6 - keyword 'if' ... ../src/test_parser.nit:90,4--5 - ../src/test_parser.nit:90,7--18 - keyword 'not' ... ../src/test_parser.nit:90,7--9 - ../src/test_parser.nit:90,11--18 - ../src/test_parser.nit:90,11 - identifier 'no_print' ... ../src/test_parser.nit:90,11--18 - ../src/test_parser.nit:90,11 - ../src/test_parser.nit:91,5--44 - ../src/test_parser.nit:91,5--44 - ../src/test_parser.nit:91,5--26 - '(' ... ../src/test_parser.nit:91,5 - ../src/test_parser.nit:91,6--25 - keyword 'new' ... ../src/test_parser.nit:91,6--8 - ../src/test_parser.nit:91,10--25 - type identifier 'PrintTreeVisitor' ... ../src/test_parser.nit:91,10--25 - ../src/test_parser.nit:91,6 - ')' ... ../src/test_parser.nit:91,26 - identifier 'enter_visit' ... ../src/test_parser.nit:91,28--38 - ../src/test_parser.nit:91,39--44 - '(' ... ../src/test_parser.nit:91,39 - ../src/test_parser.nit:91,40--43 - ../src/test_parser.nit:91,40 - identifier 'tree' ... ../src/test_parser.nit:91,40--43 - ../src/test_parser.nit:91,40 - ')' ... ../src/test_parser.nit:91,44 - ../src/test_parser.nit:92,4--6 - keyword 'end' ... ../src/test_parser.nit:92,4--6 - keyword 'end' ... ../src/test_parser.nit:93,3--5 - keyword 'end' ... ../src/test_parser.nit:94,2--4 - keyword 'end' ... ../src/test_parser.nit:95,1--3 - end of file ... ../src/test_parser.nit:96,1 + ../src/test_parser.nit:90,4--25 + keyword 'var' ... ../src/test_parser.nit:90,4--6 + identifier 'error' ... ../src/test_parser.nit:90,8--12 + '=' ... ../src/test_parser.nit:90,14 + ../src/test_parser.nit:90,16--25 + ../src/test_parser.nit:90,16--19 + ../src/test_parser.nit:90,16 + identifier 'tree' ... ../src/test_parser.nit:90,16--19 + ../src/test_parser.nit:90,16 + identifier 'n_eof' ... ../src/test_parser.nit:90,21--25 + ../src/test_parser.nit:90,16 + ../src/test_parser.nit:91,4--94,6 + keyword 'if' ... ../src/test_parser.nit:91,4--5 + ../src/test_parser.nit:91,7--22 + ../src/test_parser.nit:91,7--11 + ../src/test_parser.nit:91,7 + identifier 'error' ... ../src/test_parser.nit:91,7--11 + ../src/test_parser.nit:91,7 + ../src/test_parser.nit:91,17--22 + type identifier 'AError' ... ../src/test_parser.nit:91,17--22 + ../src/test_parser.nit:92,5--93,10 + ../src/test_parser.nit:92,5--58 + ../src/test_parser.nit:92,11 + identifier 'print' ... ../src/test_parser.nit:92,5--9 + ../src/test_parser.nit:92,10--58 + '(' ... ../src/test_parser.nit:92,10 + ../src/test_parser.nit:92,11--57 + ../src/test_parser.nit:92,11--21 + literal value '"Error at {' ... ../src/test_parser.nit:92,11--21 + ../src/test_parser.nit:92,22--35 + ../src/test_parser.nit:92,22--26 + ../src/test_parser.nit:92,22 + identifier 'error' ... ../src/test_parser.nit:92,22--26 + ../src/test_parser.nit:92,22 + identifier 'location' ... ../src/test_parser.nit:92,28--35 + ../src/test_parser.nit:92,22 + ../src/test_parser.nit:92,36--42 + literal value '}:\n\t{' ... ../src/test_parser.nit:92,36--42 + ../src/test_parser.nit:92,43--55 + ../src/test_parser.nit:92,43--47 + ../src/test_parser.nit:92,43 + identifier 'error' ... ../src/test_parser.nit:92,43--47 + ../src/test_parser.nit:92,43 + identifier 'message' ... ../src/test_parser.nit:92,49--55 + ../src/test_parser.nit:92,43 + ../src/test_parser.nit:92,56--57 + '}"' ... ../src/test_parser.nit:92,56--57 + ')' ... ../src/test_parser.nit:92,58 + ../src/test_parser.nit:93,5--10 + keyword 'return' ... ../src/test_parser.nit:93,5--10 + ../src/test_parser.nit:94,4--6 + keyword 'end' ... ../src/test_parser.nit:94,4--6 + ../src/test_parser.nit:96,4--98,6 + keyword 'if' ... ../src/test_parser.nit:96,4--5 + ../src/test_parser.nit:96,7--18 + keyword 'not' ... ../src/test_parser.nit:96,7--9 + ../src/test_parser.nit:96,11--18 + ../src/test_parser.nit:96,11 + identifier 'no_print' ... ../src/test_parser.nit:96,11--18 + ../src/test_parser.nit:96,11 + ../src/test_parser.nit:97,5--44 + ../src/test_parser.nit:97,5--44 + ../src/test_parser.nit:97,5--26 + '(' ... ../src/test_parser.nit:97,5 + ../src/test_parser.nit:97,6--25 + keyword 'new' ... ../src/test_parser.nit:97,6--8 + ../src/test_parser.nit:97,10--25 + type identifier 'PrintTreeVisitor' ... ../src/test_parser.nit:97,10--25 + ../src/test_parser.nit:97,6 + ')' ... ../src/test_parser.nit:97,26 + identifier 'enter_visit' ... ../src/test_parser.nit:97,28--38 + ../src/test_parser.nit:97,39--44 + '(' ... ../src/test_parser.nit:97,39 + ../src/test_parser.nit:97,40--43 + ../src/test_parser.nit:97,40 + identifier 'tree' ... ../src/test_parser.nit:97,40--43 + ../src/test_parser.nit:97,40 + ')' ... ../src/test_parser.nit:97,44 + ../src/test_parser.nit:98,4--6 + keyword 'end' ... ../src/test_parser.nit:98,4--6 + keyword 'end' ... ../src/test_parser.nit:99,3--5 + keyword 'end' ... ../src/test_parser.nit:100,2--4 + keyword 'end' ... ../src/test_parser.nit:101,1--3 + end of file ... ../src/test_parser.nit:102,1 diff --git a/tests/sav/test_parser_args2.sav b/tests/sav/test_parser_args2.res similarity index 88% rename from tests/sav/test_parser_args2.sav rename to tests/sav/test_parser_args2.res index 96121b3..5c9bc73 100644 --- a/tests/sav/test_parser_args2.sav +++ b/tests/sav/test_parser_args2.res @@ -484,32 +484,69 @@ Read token at ../src/test_parser.nit:88,11--89,0 text=' ' Read token at ../src/test_parser.nit:89,1--90,0 text=' ' -Read token at ../src/test_parser.nit:90,4--5 text='if' -Read token at ../src/test_parser.nit:90,7--9 text='not' -Read token at ../src/test_parser.nit:90,11--18 text='no_print' -Read token at ../src/test_parser.nit:90,20--23 text='then' -Read token at ../src/test_parser.nit:90,24--91,0 text=' -' -Read token at ../src/test_parser.nit:91,5 text='(' -Read token at ../src/test_parser.nit:91,6--8 text='new' -Read token at ../src/test_parser.nit:91,10--25 text='PrintTreeVisitor' -Read token at ../src/test_parser.nit:91,26 text=')' -Read token at ../src/test_parser.nit:91,27 text='.' -Read token at ../src/test_parser.nit:91,28--38 text='enter_visit' -Read token at ../src/test_parser.nit:91,39 text='(' -Read token at ../src/test_parser.nit:91,40--43 text='tree' -Read token at ../src/test_parser.nit:91,44 text=')' -Read token at ../src/test_parser.nit:91,45--92,0 text=' -' -Read token at ../src/test_parser.nit:92,4--6 text='end' -Read token at ../src/test_parser.nit:92,7--93,0 text=' -' -Read token at ../src/test_parser.nit:93,3--5 text='end' -Read token at ../src/test_parser.nit:93,6--94,0 text=' -' -Read token at ../src/test_parser.nit:94,2--4 text='end' -Read token at ../src/test_parser.nit:94,5--95,0 text=' -' -Read token at ../src/test_parser.nit:95,1--3 text='end' -Read token at ../src/test_parser.nit:95,4--96,0 text=' +Read token at ../src/test_parser.nit:90,4--6 text='var' +Read token at ../src/test_parser.nit:90,8--12 text='error' +Read token at ../src/test_parser.nit:90,14 text='=' +Read token at ../src/test_parser.nit:90,16--19 text='tree' +Read token at ../src/test_parser.nit:90,20 text='.' +Read token at ../src/test_parser.nit:90,21--25 text='n_eof' +Read token at ../src/test_parser.nit:90,26--91,0 text=' +' +Read token at ../src/test_parser.nit:91,4--5 text='if' +Read token at ../src/test_parser.nit:91,7--11 text='error' +Read token at ../src/test_parser.nit:91,13--15 text='isa' +Read token at ../src/test_parser.nit:91,17--22 text='AError' +Read token at ../src/test_parser.nit:91,24--27 text='then' +Read token at ../src/test_parser.nit:91,28--92,0 text=' +' +Read token at ../src/test_parser.nit:92,5--9 text='print' +Read token at ../src/test_parser.nit:92,10 text='(' +Read token at ../src/test_parser.nit:92,11--21 text='"Error at {' +Read token at ../src/test_parser.nit:92,22--26 text='error' +Read token at ../src/test_parser.nit:92,27 text='.' +Read token at ../src/test_parser.nit:92,28--35 text='location' +Read token at ../src/test_parser.nit:92,36--42 text='}:\n\t{' +Read token at ../src/test_parser.nit:92,43--47 text='error' +Read token at ../src/test_parser.nit:92,48 text='.' +Read token at ../src/test_parser.nit:92,49--55 text='message' +Read token at ../src/test_parser.nit:92,56--57 text='}"' +Read token at ../src/test_parser.nit:92,58 text=')' +Read token at ../src/test_parser.nit:92,59--93,0 text=' +' +Read token at ../src/test_parser.nit:93,5--10 text='return' +Read token at ../src/test_parser.nit:93,11--94,0 text=' +' +Read token at ../src/test_parser.nit:94,4--6 text='end' +Read token at ../src/test_parser.nit:94,7--95,0 text=' +' +Read token at ../src/test_parser.nit:95,1--96,0 text=' +' +Read token at ../src/test_parser.nit:96,4--5 text='if' +Read token at ../src/test_parser.nit:96,7--9 text='not' +Read token at ../src/test_parser.nit:96,11--18 text='no_print' +Read token at ../src/test_parser.nit:96,20--23 text='then' +Read token at ../src/test_parser.nit:96,24--97,0 text=' +' +Read token at ../src/test_parser.nit:97,5 text='(' +Read token at ../src/test_parser.nit:97,6--8 text='new' +Read token at ../src/test_parser.nit:97,10--25 text='PrintTreeVisitor' +Read token at ../src/test_parser.nit:97,26 text=')' +Read token at ../src/test_parser.nit:97,27 text='.' +Read token at ../src/test_parser.nit:97,28--38 text='enter_visit' +Read token at ../src/test_parser.nit:97,39 text='(' +Read token at ../src/test_parser.nit:97,40--43 text='tree' +Read token at ../src/test_parser.nit:97,44 text=')' +Read token at ../src/test_parser.nit:97,45--98,0 text=' +' +Read token at ../src/test_parser.nit:98,4--6 text='end' +Read token at ../src/test_parser.nit:98,7--99,0 text=' +' +Read token at ../src/test_parser.nit:99,3--5 text='end' +Read token at ../src/test_parser.nit:99,6--100,0 text=' +' +Read token at ../src/test_parser.nit:100,2--4 text='end' +Read token at ../src/test_parser.nit:100,5--101,0 text=' +' +Read token at ../src/test_parser.nit:101,1--3 text='end' +Read token at ../src/test_parser.nit:101,4--102,0 text=' ' diff --git a/tests/sav/test_parser_args3.res b/tests/sav/test_parser_args3.res new file mode 100644 index 0000000..100c6c8 --- /dev/null +++ b/tests/sav/test_parser_args3.res @@ -0,0 +1,2 @@ +Error at ./error_syntax.nit:19,2: + Syntax error: unknown token ?. diff --git a/tests/sav/test_parser_args4.res b/tests/sav/test_parser_args4.res new file mode 100644 index 0000000..9618d89 --- /dev/null +++ b/tests/sav/test_parser_args4.res @@ -0,0 +1,38 @@ +Read token at ./error_syntax.nit:1,1--2,0 text='# This file is part of NIT ( http://www.nitlanguage.org ). +' +Read token at ./error_syntax.nit:2,1--3,0 text='# +' +Read token at ./error_syntax.nit:3,1--4,0 text='# Copyright 2009 Jean Privat +' +Read token at ./error_syntax.nit:4,1--5,0 text='# +' +Read token at ./error_syntax.nit:5,1--6,0 text='# Licensed under the Apache License, Version 2.0 (the "License"); +' +Read token at ./error_syntax.nit:6,1--7,0 text='# you may not use this file except in compliance with the License. +' +Read token at ./error_syntax.nit:7,1--8,0 text='# You may obtain a copy of the License at +' +Read token at ./error_syntax.nit:8,1--9,0 text='# +' +Read token at ./error_syntax.nit:9,1--10,0 text='# http://www.apache.org/licenses/LICENSE-2.0 +' +Read token at ./error_syntax.nit:10,1--11,0 text='# +' +Read token at ./error_syntax.nit:11,1--12,0 text='# Unless required by applicable law or agreed to in writing, software +' +Read token at ./error_syntax.nit:12,1--13,0 text='# distributed under the License is distributed on an "AS IS" BASIS, +' +Read token at ./error_syntax.nit:13,1--14,0 text='# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +' +Read token at ./error_syntax.nit:14,1--15,0 text='# See the License for the specific language governing permissions and +' +Read token at ./error_syntax.nit:15,1--16,0 text='# limitations under the License. +' +Read token at ./error_syntax.nit:16,1--17,0 text=' +' +Read token at ./error_syntax.nit:17,1--5 text='class' +Read token at ./error_syntax.nit:17,7 text='A' +Read token at ./error_syntax.nit:17,8--18,0 text=' +' +Read token at ./error_syntax.nit:18,2--19,0 text='#alt1#once +' diff --git a/tests/sav/test_parser_args5.res b/tests/sav/test_parser_args5.res new file mode 100644 index 0000000..2b55dba --- /dev/null +++ b/tests/sav/test_parser_args5.res @@ -0,0 +1,2 @@ +Error at ./error_syntax3.nit:1,1--4: + Syntax error: unexpected keyword 'else'. diff --git a/tests/string_ffi_ref_test.nit b/tests/string_ffi_ref_test.nit new file mode 100644 index 0000000..d2c6277 --- /dev/null +++ b/tests/string_ffi_ref_test.nit @@ -0,0 +1,67 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2013 Lucas Bajolet +# +# 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. + +module string_ffi_ref_test + +class StringTest + + var copied_str: nullable String + + var referenced_str: nullable String + + init + do + copied_str = null + referenced_str = null + end + + fun get_c_string import String::items, String::from_cstring, String::copy_from_native, StringTest::ref_test, StringTest::copy_test `{ + char* string = "This is a test string"; + + String ref_string = new_String_from_cstring(string); + StringTest_ref_test(recv, ref_string); + + String copy_string = new_String_copy_from_native(string); + StringTest_copy_test(recv, copy_string); + + int same_refs = String_items(copy_string) == String_items(ref_string); + + printf("Do the strings have the same NativeString reference ? "); + + if(same_refs){ + printf("True\n"); + }else{ + printf("False\n"); + } + `} + + private fun ref_test(referenced: String) + do + print referenced + referenced_str = referenced + end + + private fun copy_test(copied: String) + do + print copied + copied_str = copied + end + +end + +var str_test = new StringTest + +str_test.get_c_string diff --git a/tests/string_trim.nit b/tests/string_trim.nit new file mode 100644 index 0000000..09bd541 --- /dev/null +++ b/tests/string_trim.nit @@ -0,0 +1,53 @@ +module string_trim + +var trimtest = " \t nono nono \n \t" + +var subtrim = trimtest.substring(2,15) + +var buffertrimtest = new Buffer.from(trimtest) + +print "resulttrim = {buffertrimtest.trim}" + +print "returntrim + {trimtest.trim}" + +print "thirdtrim = {subtrim.trim}" + +var emptytrim = " \t " + +var bufferemptytest = new Buffer.from(emptytrim) + +print "emptytrim = {emptytrim.trim}" + +print "bufferemptytrim = {bufferemptytest.trim}" + +var onelettertrim = " \n d \n\t " + +var oneletterbuftest = new Buffer.from(onelettertrim) + +print "onelettertrim = {onelettertrim.trim}" + +print "oneletterbuftest = {oneletterbuftest.trim}" + +var twolettertrim = " \n hg \n\t " + +var twoletterbuftest = new Buffer.from(twolettertrim) + +print "twolettertrim = {twolettertrim.trim}" + +print "twoletterbuftest = {twoletterbuftest.trim}" + +var firstlettertrim = "d " + +var firstlettertrimbuf = new Buffer.from(firstlettertrim) + +print "firstlettertrimtest = {firstlettertrim.trim}" + +print "firstlettertrimbuftest = {firstlettertrimbuf.trim}" + +var lastlettertrim = " d" + +var lastlettertrimbuf = new Buffer.from(lastlettertrim) + +print "lastlettertrimtest = {lastlettertrim.trim}" + +print "lastlettertrimbuftest = {lastlettertrimbuf.trim}" diff --git a/tests/test_parser.args b/tests/test_parser.args index 78cd96e..9ee0788 100644 --- a/tests/test_parser.args +++ b/tests/test_parser.args @@ -1,2 +1,5 @@ ../src/test_parser.nit -l ../src/test_parser.nit +./error_syntax.nit +-l ./error_syntax.nit +./error_syntax3.nit