Merge branch 'use_more_callsite'
authorJean Privat <jean@pryen.org>
Mon, 24 Feb 2014 15:55:20 +0000 (10:55 -0500)
committerJean Privat <jean@pryen.org>
Mon, 24 Feb 2014 15:55:20 +0000 (10:55 -0500)
CallSite is a great data-class to store various information on a call
site.

This series generalizes its usage in some place, and remove a old
depreciated API.

This uniformization and cleanup will be useful in future work, like
call-site optimizations and the new constructors

97 files changed:
contrib/sort_downloads/src/sort_downloads.nit
examples/callback_monkey.nit
examples/draw_operation.nit
lib/base64.nit
lib/bcm2835.nit
lib/curl/curl_c.nit
lib/curses/curses.nit
lib/gtk3_4/gtk_assistant.nit
lib/gtk3_4/gtk_core.nit
lib/gtk3_4/gtk_dialogs.nit
lib/gtk3_4/gtk_widgets_ext.nit
lib/json/json_reader.nit
lib/json/json_writer.nit
lib/json/jsonable.nit
lib/md5.nit
lib/mnit/opengles1.nit
lib/mnit_linux/linux_opengles1.nit
lib/mnit_linux/sdl.nit
lib/opts.nit
lib/signals.nit
lib/socket/socket_c.nit
lib/sqlite3/sqlite3.nit
lib/standard/file.nit
lib/standard/file_nit.c
lib/standard/file_nit.h
lib/standard/math.nit
lib/standard/posix.nit
lib/standard/standard.nit
lib/standard/stream.nit
lib/standard/stream_nit.c
lib/standard/stream_nit.h
lib/standard/string.nit
lib/standard/string_search.nit
lib/standard/time.nit
src/abstract_compiler.nit
src/c_tools.nit
src/common_ffi/c.nit [new file with mode: 0644]
src/common_ffi/common_ffi.nit [new file with mode: 0644]
src/common_ffi/extern_classes.nit [new file with mode: 0644]
src/common_ffi/ffi_base.nit [new file with mode: 0644]
src/common_ffi/header_dependency.nit [new file with mode: 0644]
src/compiler_ffi.nit [new file with mode: 0644]
src/debugger.nit
src/full_boostrap [new file with mode: 0755]
src/global_compiler.nit
src/literal.nit
src/location.nit
src/markdown.nit
src/mkcsrc
src/model/model.nit
src/modelize_property.nit
src/naive_interpreter.nit
src/network_debugger.nit
src/nitni/nitni.nit [new file with mode: 0644]
src/nitni/nitni_base.nit [new file with mode: 0644]
src/nitni/nitni_callbacks.nit [new file with mode: 0644]
src/nitni/nitni_utilities.nit [new file with mode: 0644]
src/nitx.nit
src/parser/lexer.nit
src/parser/xss/lexer.xss
src/separate_compiler.nit
src/test_parser.nit
src/typing.nit
tests/base_error_doubledef.nit [new file with mode: 0644]
tests/base_string.nit
tests/bench_string_append.nit
tests/example_procedural_string.nit
tests/sav/base_error_doubledef.res [new file with mode: 0644]
tests/sav/error_ref_param.res
tests/sav/error_ref_ret.res
tests/sav/error_spe_param.res
tests/sav/error_spe_param2.res
tests/sav/error_spe_ret.res
tests/sav/fixme/error_ref_param.res [deleted file]
tests/sav/fixme/error_spe_param.res [deleted file]
tests/sav/fixme/test_multiconstraint_inh.res [deleted file]
tests/sav/test_multiconstraint_inh.res
tests/sav/test_parser_args1.res
tests/sav/test_parser_args2.res
tests/sav/test_ropes.res [deleted file]
tests/shootout_nsieve.nit
tests/string_ffi_ref_test.nit
tests/test_ffi_c_accessor.nit
tests/test_ffi_c_callback_extern_receiver.nit
tests/test_ffi_c_callbacks.nit
tests/test_ffi_c_casts.nit
tests/test_ffi_c_global_ref.nit
tests/test_ffi_c_more.nit
tests/test_ffi_c_more_callbacks.nit
tests/test_ffi_c_operators.nit
tests/test_ffi_c_strings.nit
tests/test_ffi_c_super.nit
tests/test_ropes.nit [deleted file]
tests/test_string2.nit
tests/test_string_long.nit
tests/test_string_unicode.nit
tests/test_substring.nit

index cb9caa5..99c4f87 100755 (executable)
@@ -63,8 +63,8 @@ redef class String
        end
 
        # Returns null on success
-       fun file_rename_to(dest: String): nullable String import String::to_cstring,
-       NativeString::to_s, String as nullable `{
+       fun file_rename_to(dest: String): nullable String import String.to_cstring,
+       NativeString.to_s, String as nullable `{
                int res = rename(String_to_cstring(recv), String_to_cstring(dest));
                if (res == 0) return null_String();
                return String_as_nullable(NativeString_to_s(strerror(errno)));
index 074df9f..8b04b94 100644 (file)
@@ -69,7 +69,7 @@ extern Monkey `{ CMonkey * `}
        
        # Object method which will get a callback in wokeUp method, defined in MonkeyActionCallable interface
        # Must be defined as Nit/C method because of C call inside
-       fun wokeUpAction( toCall: MonkeyActionCallable, message: Object ) is extern import MonkeyActionCallable::wokeUp `{
+       fun wokeUpAction( toCall: MonkeyActionCallable, message: Object ) is extern import MonkeyActionCallable.wokeUp `{
 
                // Allocating memory to keep reference of received parameters :
                // - Object receiver
index 8ad92fc..cada831 100644 (file)
@@ -124,7 +124,7 @@ redef class String
                end
 
                var ci = 0
-               for c in self do
+               for c in self.chars do
                        var local_dispc
                        if c.override_dispc then
                                local_dispc = c
@@ -193,10 +193,10 @@ else
        b = gets.to_i
 
        printn "Operator (+, -, *, /, %): "
-       op_char = gets[0]
+       op_char = gets.chars[0]
 
        printn "Char to display: "
-       disp_char = gets[0]
+       disp_char = gets.chars[0]
 
        printn "Size of text: "
        disp_size = gets.to_i
index 861cb9a..9c57166 100644 (file)
@@ -28,7 +28,7 @@ redef class String
        do
                var inv_base64_chars = new HashMap[Char,Int]
                for k in [0..base64_chars.length[ do
-                       inv_base64_chars[ base64_chars[k] ] = k
+                       inv_base64_chars[ base64_chars.chars[k] ] = k
                end
                return inv_base64_chars
        end
@@ -52,23 +52,23 @@ redef class String
                for s in [0..steps[ do
                        var e = 0
                        for ss in [0..3[ do
-                               e += self[s*3+ss].ascii.lshift((2-ss)*8)
+                               e += self.chars[s*3+ss].ascii.lshift((2-ss)*8)
                        end
                        for ss in [0..4[ do
-                               result[s*4+3-ss] = base64_chars[ e.rshift(ss*6).bin_and( mask_6bit ) ]
+                               result[s*4+3-ss] = base64_chars.chars[ e.rshift(ss*6).bin_and( mask_6bit ) ]
                        end
                end
 
                if chars_in_last_step == 1 then
-                       var e = self[length-1].ascii.lshift(16)
+                       var e = self.chars[length-1].ascii.lshift(16)
                        for ss in [0..2[ do
-                               result[steps*4+1-ss] = base64_chars[ e.rshift((ss+2)*6).bin_and( mask_6bit ) ]
+                               result[steps*4+1-ss] = base64_chars.chars[ e.rshift((ss+2)*6).bin_and( mask_6bit ) ]
                        end
                else if chars_in_last_step == 2 then
-                       var e = self[length-2].ascii.lshift(16) +
-                               self[length-1].ascii.lshift(8)
+                       var e = self.chars[length-2].ascii.lshift(16) +
+                               self.chars[length-1].ascii.lshift(8)
                        for ss in [0..3[ do
-                               result[steps*4+2-ss] = base64_chars[ e.rshift((ss+1)*6).bin_and( mask_6bit ) ]
+                               result[steps*4+2-ss] = base64_chars.chars[ e.rshift((ss+1)*6).bin_and( mask_6bit ) ]
                        end
                end
 
@@ -104,7 +104,7 @@ redef class String
                for s in [0..steps[ do
                        var e = 0
                        for ss in [0..4[ do
-                               e += inverted_base64_chars[self[s*4+ss]].lshift((3-ss)*6)
+                               e += inverted_base64_chars[self.chars[s*4+ss]].lshift((3-ss)*6)
                        end
 
                        for ss in [0..3[ do
@@ -116,7 +116,7 @@ redef class String
                if padding_count == 1 then
                        var e = 0
                        for ss in [0..3[ do
-                               e += inverted_base64_chars[self[s*4+ss]].lshift((3-ss)*6)
+                               e += inverted_base64_chars[self.chars[s*4+ss]].lshift((3-ss)*6)
                        end
 
                        for ss in [0..2[ do
@@ -125,7 +125,7 @@ redef class String
                else if padding_count == 2 then
                        var e = 0
                        for ss in [0..2[ do
-                               e += inverted_base64_chars[self[s*4+ss]].lshift((3-ss)*6)
+                               e += inverted_base64_chars[self.chars[s*4+ss]].lshift((3-ss)*6)
                        end
 
                        result[s*3] = e.rshift(2*8).bin_and( mask_8bit ).ascii
index 3557073..aac7352 100644 (file)
@@ -440,7 +440,7 @@ class HD44780
                clear
                return_home
                var count = 0
-               for c in v do
+               for c in v.chars do
                        if c == '\n' then
                                # FIXME, this should work
                                #write(true, "C0".to_hex)
index c5dbf85..7dadbd5 100644 (file)
@@ -101,7 +101,7 @@ extern CCurl `{ CURL * `}
        # Internal method to set options to CURL using CURLSList parameter.
        private fun i_setopt_slist(opt: CURLOption, list: CURLSList):CURLCode `{ return curl_easy_setopt( recv, opt, list); `}
        # Internal method to set options to CURL using String parameter.
-       private fun i_setopt_string(opt: CURLOption, str: String):CURLCode import String::to_cstring `{
+       private fun i_setopt_string(opt: CURLOption, str: String):CURLCode import String.to_cstring `{
                char *rStr = String_to_cstring(str);
                return curl_easy_setopt( recv, opt, rStr);
        `}
@@ -113,7 +113,7 @@ extern CCurl `{ CURL * `}
                 return answ
        end
        # Internal method used to get String object information initially knowns as C Chars type
-       private fun i_getinfo_chars(opt: CURLInfoChars, res: CURLInfoResponseString):CURLCode import CURLInfoResponseString::response=, NativeString::to_s_with_copy `{
+       private fun i_getinfo_chars(opt: CURLInfoChars, res: CURLInfoResponseString):CURLCode import CURLInfoResponseString.response=, NativeString.to_s_with_copy `{
                char *r = NULL;
                CURLcode c = curl_easy_getinfo( recv, opt, &r);
                if((c == CURLE_OK) && r != NULL){
@@ -130,7 +130,7 @@ extern CCurl `{ CURL * `}
                 return answ
        end
        # Internal method used to get Int object information initially knowns as C Long type
-       private fun i_getinfo_long(opt: CURLInfoLong, res: CURLInfoResponseLong):CURLCode import CURLInfoResponseLong::response= `{
+       private fun i_getinfo_long(opt: CURLInfoLong, res: CURLInfoResponseLong):CURLCode import CURLInfoResponseLong.response= `{
                long *r = NULL;
                r = malloc(sizeof(long));
                CURLcode c = curl_easy_getinfo( recv, opt, r);
@@ -146,7 +146,7 @@ extern CCurl `{ CURL * `}
                 return answ
        end
        # Internal method used to get Int object information initially knowns as C Double type
-       private fun i_getinfo_double(opt: CURLInfoDouble, res: CURLInfoResponseDouble):CURLCode import CURLInfoResponseDouble::response= `{
+       private fun i_getinfo_double(opt: CURLInfoDouble, res: CURLInfoResponseDouble):CURLCode import CURLInfoResponseDouble.response= `{
                double *r = NULL;
                r = malloc(sizeof(double));
                CURLcode c = curl_easy_getinfo( recv, opt, r);
@@ -164,7 +164,7 @@ extern CCurl `{ CURL * `}
                return answ
        end
        # Internal method used to get Array[String] object information initially knowns as C SList type
-       private fun i_getinfo_slist(opt: CURLInfoSList, res: CURLInfoResponseArray):CURLCode import CURLInfoResponseArray::prim_response=`{
+       private fun i_getinfo_slist(opt: CURLInfoSList, res: CURLInfoResponseArray):CURLCode import CURLInfoResponseArray.prim_response=`{
                struct curl_slist* csl = NULL;
                CURLcode ce = curl_easy_getinfo( recv, opt, &csl);
                CURLInfoResponseArray_prim_response__assign(res, csl);
@@ -185,7 +185,7 @@ extern CCurl `{ CURL * `}
                return once new CURLCode.unknown_option
        end
        # Internal method used to configure read callback
-       private fun i_register_read_datas_callback(delegate: CCurlCallbacks, datas: String, size: Int):CURLCode import String::to_cstring `{
+       private fun i_register_read_datas_callback(delegate: CCurlCallbacks, datas: String, size: Int):CURLCode import String.to_cstring `{
                CURLCallbackReadDatas *d = NULL;
                d = malloc(sizeof(CURLCallbackReadDatas));
                d->data = (char*)String_to_cstring(datas);
@@ -194,7 +194,7 @@ extern CCurl `{ CURL * `}
                return curl_easy_setopt( recv, CURLOPT_READDATA, d);
        `}
        # Internal method used to configure callbacks in terms of given type
-       private fun i_register_callback(delegate: CCurlCallbacks, cbtype: CURLCallbackType):CURLCode is extern import CCurlCallbacks::header_callback,  CCurlCallbacks::body_callback, CCurlCallbacks::stream_callback  `{
+       private fun i_register_callback(delegate: CCurlCallbacks, cbtype: CURLCallbackType):CURLCode is extern import CCurlCallbacks.header_callback,   CCurlCallbacks.body_callback, CCurlCallbacks.stream_callback    `{
                CURLCallbackDatas *d = malloc(sizeof(CURLCallbackDatas));
                CCurlCallbacks_incr_ref(delegate);
                d->type = cbtype;
@@ -220,7 +220,7 @@ extern CCurl `{ CURL * `}
                return e;
        `}
        # Convert given string to URL encoded string
-       fun escape(url: String):String import String::to_cstring, NativeString::to_s_with_copy `{
+       fun escape(url: String):String import String.to_cstring, NativeString.to_s_with_copy `{
                char *orig_url, *encoded_url = NULL;
                orig_url = String_to_cstring(url);
                encoded_url = curl_easy_escape( recv, orig_url, strlen(orig_url));
@@ -281,7 +281,7 @@ extern CURLCode `{ CURLcode `}
        fun is_valid_protocol:Bool `{ return recv == CURLE_UNSUPPORTED_PROTOCOL; `}
        fun is_valid_init:Bool `{ return recv == CURLE_FAILED_INIT; `}
        fun to_i:Int do return code end
-       redef fun to_s import NativeString::to_s_with_copy `{
+       redef fun to_s import NativeString.to_s_with_copy `{
                char *c = (char*)curl_easy_strerror(recv);
                return NativeString_to_s_with_copy(c);
        `}
@@ -292,7 +292,7 @@ extern CURLSList `{ struct curl_slist * `}
        # Empty constructor which allow us to avoid the use of Nit NULLABLE type
        private new `{ return NULL; `}
        # Constructor allow us to get list instancied by appending an element inside.
-       new with_str(s: String) import String::to_cstring `{
+       new with_str(s: String) import String.to_cstring `{
                struct curl_slist *l = NULL;
                l = curl_slist_append(l, String_to_cstring(s));
                return l;
@@ -300,7 +300,7 @@ extern CURLSList `{ struct curl_slist * `}
        # Check for initialization
        fun is_init:Bool `{ return (recv != NULL); `}
        # Append an element in the linked list
-       fun append(key: String) import String::to_cstring `{
+       fun append(key: String) import String.to_cstring `{
                 char *k = String_to_cstring(key);
                 curl_slist_append(recv, (char*)k);
        `}
@@ -341,18 +341,18 @@ redef class Collection[E]
        end
 end
 
-# Array Response type of CCurl::easy_getinfo method
+# Array Response type of CCurl.easy_getinfo method
 class CURLInfoResponseArray
        var response:Array[String] = new Array[String]
        private var prim_response:CURLSList = new CURLSList
 end
 
-# Long Response type of CCurl::easy_getinfo method
+# Long Response type of CCurl.easy_getinfo method
 class CURLInfoResponseLong
        var response:Int=0
 end
 
-# Double Response type of CCurl::easy_getinfo method
+# Double Response type of CCurl.easy_getinfo method
 class CURLInfoResponseDouble
        var response:Int=0
 end
@@ -362,13 +362,13 @@ class CURLInfoResponseString
        var response:String = ""
 end
 
-# Reproduce Enum of available CURL SList information, used for CCurl::easy_getinfo
+# Reproduce Enum of available CURL SList information, used for CCurl.easy_getinfo
 extern CURLInfoSList `{ CURLINFO `}
        new ssl_engines `{ return CURLINFO_SSL_ENGINES; `}
        new cookielist `{ return CURLINFO_COOKIELIST; `}
 end
 
-# Reproduce Enum of available CURL Long information, used for CCurl::easy_getinfo
+# Reproduce Enum of available CURL Long information, used for CCurl.easy_getinfo
 extern CURLInfoLong `{ CURLINFO `}
        new response_code `{ return CURLINFO_RESPONSE_CODE; `}
        new header_size `{ return CURLINFO_HEADER_SIZE; `}
@@ -390,7 +390,7 @@ extern CURLInfoLong `{ CURLINFO `}
        new rtsp_cseq_recv `{ return CURLINFO_RTSP_CSEQ_RECV; `}
 end
 
-# Reproduce Enum of available CURL Double information, used for CCurl::easy_getinfo
+# Reproduce Enum of available CURL Double information, used for CCurl.easy_getinfo
 extern CURLInfoDouble `{ CURLINFO `}
        new total_time `{ return CURLINFO_TOTAL_TIME; `}
        new namelookup_time `{ return CURLINFO_NAMELOOKUP_TIME; `}
@@ -407,7 +407,7 @@ extern CURLInfoDouble `{ CURLINFO `}
        new content_length_upload `{ return CURLINFO_CONTENT_LENGTH_UPLOAD; `}
 end
 
-# Reproduce Enum of available CURL Chars information, used for CCurl::easy_getinfo
+# Reproduce Enum of available CURL Chars information, used for CCurl.easy_getinfo
 extern CURLInfoChars `{ CURLINFO `}
        new content_type `{ return CURLINFO_CONTENT_TYPE; `}
        new effective_url `{ return CURLINFO_EFFECTIVE_URL; `}
@@ -461,7 +461,7 @@ extern CURLStatusCode `{ int `}
        fun to_i:Int `{ return recv; `}
 end
 
-# Reproduce Enum of CURL Options usable, used for CCurl::easy_setopt
+# Reproduce Enum of CURL Options usable, used for CCurl.easy_setopt
 extern CURLOption `{ CURLoption `}
        new write_function `{ return CURLOPT_WRITEFUNCTION; `}
        new write_data `{ return CURLOPT_WRITEDATA; `}
index 7acc650..158d957 100644 (file)
@@ -37,7 +37,7 @@ extern Window `{WINDOW *`}
 
        # print a string somewhere
        # NOTE: as with the curses API, the position is (y,x)
-       fun mvaddstr(y,x: Int, str: String) import String::to_cstring `{
+       fun mvaddstr(y,x: Int, str: String) import String.to_cstring `{
                char *c_string = String_to_cstring( str );
                mvaddstr(y, x, c_string);
        `}
index 282e35a..417f49c 100644 (file)
@@ -75,7 +75,7 @@ extern GtkAssistant `{GtkAssistant *`}
                return NativeString_to_s( (char *)gtk_assistant_get_page_title( recv, page ) );
        `}
 
-       fun set_page_title( page : GtkWidget, title : String) is extern import String::to_cstring`{
+       fun set_page_title( page : GtkWidget, title : String) is extern import String.to_cstring `{
                gtk_assistant_set_page_title( recv, page, String_to_cstring( title ) );
        `}
 
index a53d08d..e5dd0e2 100644 (file)
@@ -59,7 +59,7 @@ end
 extern GtkWidget `{GtkWidget *`}
        fun show_all is extern `{ gtk_widget_show_all( recv ); `}
 
-       fun signal_connect( signal_name : String, to_call : GtkCallable, user_data : nullable Object ) is extern import String::to_cstring, GtkCallable::signal, Object as not nullable `{
+       fun signal_connect( signal_name : String, to_call : GtkCallable, user_data : nullable Object ) is extern import String.to_cstring, GtkCallable.signal, Object as not nullable `{
                NitGtkSignal *data = malloc( sizeof(NitGtkSignal) );
 
                GtkCallable_incr_ref( to_call );
@@ -171,7 +171,7 @@ extern GtkWindow `{GtkWindow *`}
                return win;
        `}
 
-       fun title=( title : String ) is extern import String::to_cstring `{
+       fun title=( title : String ) is extern import String.to_cstring `{
                gtk_window_set_title( recv, String_to_cstring( title ) );
        `}
 
@@ -285,7 +285,7 @@ end
 extern GtkFrame `{GtkFrame *`}
        super GtkBin
 
-       new ( lbl : String ) is extern import String::to_cstring`{
+       new ( lbl : String ) is extern import String.to_cstring`{
                return (GtkFrame *)gtk_frame_new( String_to_cstring( lbl ) );
        `}
 
@@ -293,7 +293,7 @@ extern GtkFrame `{GtkFrame *`}
                return NativeString_to_s( (char *)gtk_frame_get_label( recv ) );
        `}
 
-       fun frame_label=( lbl : String ) is extern import String::to_cstring`{
+       fun frame_label=( lbl : String ) is extern import String.to_cstring`{
                gtk_frame_set_label( recv, String_to_cstring( lbl ) );
        `}
 
@@ -390,11 +390,11 @@ extern GtkEntry `{GtkEntry *`}
                 return (GtkEntry *)gtk_entry_new();
        `}
 
-       fun text : String is extern import String::to_cstring`{
+       fun text : String is extern import String.to_cstring`{
                return NativeString_to_s( (char *)gtk_entry_get_text( recv ) );
        `}
 
-       fun text=( value : String) is extern import String::to_cstring`{
+       fun text=( value : String) is extern import String.to_cstring`{
                gtk_entry_set_text( recv, String_to_cstring( value ) );
        `}
 
@@ -560,7 +560,7 @@ extern GtkScale `{GtkScale *`}
                gtk_scale_set_has_origin( recv, orig );
        `}
 
-       fun add_mark( value : Float, position : GtkPositionType, markup : String ) is extern import String::to_cstring`{
+       fun add_mark( value : Float, position : GtkPositionType, markup : String ) is extern import String.to_cstring`{
                gtk_scale_add_mark( recv, value, position, String_to_cstring( markup ) );
        `}
 
@@ -590,17 +590,17 @@ extern GtkLabel `{GtkLabel *`}
        super GtkMisc
 
        # Create a GtkLabel with text
-       new ( text : String ) is extern import String::to_cstring `{
+       new ( text : String ) is extern import String.to_cstring `{
                return (GtkLabel*)gtk_label_new( String_to_cstring( text ) );
        `}
 
        # Set the text of the label
-       fun text=( text : String ) import String::to_cstring `{
+       fun text=( text : String ) import String.to_cstring `{
                gtk_label_set_text( recv, String_to_cstring( text ) );
        `}
 
        # Returns the text of the label
-       fun text : String import NativeString::to_s `{
+       fun text : String import NativeString.to_s `{
                return NativeString_to_s( (char*)gtk_label_get_text( recv ) );
        `}
 
@@ -628,7 +628,7 @@ extern GtkImage `{GtkImage *`}
        `}
 
        # Create a GtkImage with text
-       new file( filename : String ) is extern import String::to_cstring `{
+       new file( filename : String ) is extern import String.to_cstring `{
                return (GtkImage*)gtk_image_new_from_file( String_to_cstring( filename ) );
        `}
 
@@ -695,11 +695,11 @@ extern GtkButton `{GtkButton *`}
        `}
 
        #Create a GtkButton with text
-       new with_label( text : String ) is extern import String::to_cstring `{
+       new with_label( text : String ) is extern import String.to_cstring `{
                return (GtkButton *)gtk_button_new_with_label( String_to_cstring( text ) );
        `}
 
-       new from_stock( stock_id : String ) is extern import String::to_cstring `{
+       new from_stock( stock_id : String ) is extern import String.to_cstring `{
                return (GtkButton *)gtk_button_new_from_stock( String_to_cstring( stock_id ) );
        `}
 
@@ -707,7 +707,7 @@ extern GtkButton `{GtkButton *`}
                return NativeString_to_s( (char *)gtk_button_get_label( recv ) );
        `}
 
-       fun text=( value : String ) is extern import String::to_cstring`{
+       fun text=( value : String ) is extern import String.to_cstring`{
                gtk_button_set_label( recv, String_to_cstring( value ) );
        `}
 
@@ -733,7 +733,7 @@ end
 extern GtkLinkButton `{GtkLinkButton *`}
        super GtkButton
 
-       new( uri: String ) is extern import String::to_cstring `{
+       new( uri: String ) is extern import String.to_cstring `{
                return (GtkLinkButton *)gtk_link_button_new( String_to_cstring(uri) );
        `}
 end
@@ -743,11 +743,11 @@ end
 extern GtkExpander `{GtkExpander *`}
        super GtkBin
 
-       new( lbl : String) is extern import String::to_cstring`{
+       new( lbl : String) is extern import String.to_cstring`{
                return (GtkExpander *)gtk_expander_new( String_to_cstring( lbl ) );
        `}
 
-       new with_mnemonic( lbl : String) is extern import String::to_cstring`{
+       new with_mnemonic( lbl : String) is extern import String.to_cstring`{
                return (GtkExpander *)gtk_expander_new_with_mnemonic(String_to_cstring( lbl ));
        `}
 
@@ -771,7 +771,7 @@ extern GtkExpander `{GtkExpander *`}
                return NativeString_to_s( (char *)gtk_expander_get_label( recv ) );
        `}
 
-       fun label_text=( lbl : String ) is extern import String::to_cstring`{
+       fun label_text=( lbl : String ) is extern import String.to_cstring`{
                gtk_expander_set_label( recv, String_to_cstring( lbl ) );
        `}
 
@@ -896,7 +896,7 @@ extern GtkComboBox `{GtkComboBox *`}
                return NativeString_to_s( (char *)gtk_combo_box_get_active_id( recv ) );
        `}
 
-       fun active_id=( id_active : String ) is extern import String::to_cstring`{
+       fun active_id=( id_active : String ) is extern import String.to_cstring`{
                gtk_combo_box_set_active_id( recv, String_to_cstring( id_active ) );
        `}
 
@@ -920,7 +920,7 @@ extern GtkComboBox `{GtkComboBox *`}
                return NativeString_to_s( (char *)gtk_combo_box_get_title( recv ) );
        `}
 
-       fun title=( t : String ) is extern import String::to_cstring`{
+       fun title=( t : String ) is extern import String.to_cstring `{
                gtk_combo_box_set_title( recv, String_to_cstring( t ) );
        `}
 
index 17e6c94..109b381 100644 (file)
@@ -31,7 +31,7 @@ extern GtkDialog `{GtkDialog *`}
                return (GtkDialog *)gtk_dialog_new( );
        `}
 
-       new with_buttons( title : String, parent : GtkWindow, flags : GtkDialogFlags) is extern import String::to_cstring`{
+       new with_buttons( title : String, parent : GtkWindow, flags : GtkDialogFlags) is extern import String.to_cstring`{
                return (GtkDialog *)gtk_dialog_new_with_buttons( String_to_cstring( title ), parent, flags, "", NULL );
        `}
 
@@ -54,7 +54,7 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
                return NativeString_to_s( (char *)gtk_about_dialog_get_program_name( recv ) );
        `}
 
-       fun program_name=( name : String ) is extern import String::to_cstring`{
+       fun program_name=( name : String ) is extern import String.to_cstring`{
                gtk_about_dialog_set_program_name( recv, String_to_cstring( name ) );
        `}
 
@@ -62,7 +62,7 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
                return NativeString_to_s( (char *)gtk_about_dialog_get_version( recv ) );
        `}
 
-       fun version=( v : String ) is extern import String::to_cstring`{
+       fun version=( v : String ) is extern import String.to_cstring`{
                gtk_about_dialog_set_version( recv, String_to_cstring( v ) );
        `}
 
@@ -70,7 +70,7 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
                return NativeString_to_s( (char *)gtk_about_dialog_get_copyright( recv ) );
        `}
 
-       fun copyright=( c : String ) is extern import String::to_cstring`{
+       fun copyright=( c : String ) is extern import String.to_cstring`{
                gtk_about_dialog_set_copyright( recv, String_to_cstring( c ) );
        `}
 
@@ -78,7 +78,7 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
                return NativeString_to_s( (char *)gtk_about_dialog_get_comments( recv ) );
        `}
 
-       fun comments=( com : String ) is extern import String::to_cstring`{
+       fun comments=( com : String ) is extern import String.to_cstring`{
                gtk_about_dialog_set_comments( recv, String_to_cstring( com ) );
        `}
 
@@ -86,7 +86,7 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
                return NativeString_to_s( (char *)gtk_about_dialog_get_license( recv ) );
        `}
 
-       fun license=( li : String ) is extern import String::to_cstring`{
+       fun license=( li : String ) is extern import String.to_cstring`{
                gtk_about_dialog_set_license( recv, String_to_cstring( li ) );
        `}
 
@@ -96,7 +96,7 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
                return NativeString_to_s( (char *)gtk_about_dialog_get_website( recv ) );
        `}
 
-       fun website=( link : String ) is extern import String::to_cstring`{
+       fun website=( link : String ) is extern import String.to_cstring`{
                gtk_about_dialog_set_website( recv, String_to_cstring( link ) );
        `}
 
@@ -104,7 +104,7 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
                return NativeString_to_s( (char *) gtk_about_dialog_get_website_label( recv ) );
        `}
 
-       fun website_label=( link_label : String ) is extern import String::to_cstring`{
+       fun website_label=( link_label : String ) is extern import String.to_cstring`{
                gtk_about_dialog_set_website_label( recv, String_to_cstring( link_label ) );
        `}
 
@@ -114,11 +114,11 @@ extern GtkAboutDialog `{GtkAboutDialog *`}
        #`}
 
        #TODO
-       #fun authors=( authors_list : String ) is extern import String::to_cstring`{
+       #fun authors=( authors_list : String ) is extern import String.to_cstring`{
        #       gtk_about_dialog_set_authors( recv, String_to_cstring( authors_list ) );
        #`}
 
-       fun show ( parent : GtkWindow, params : String ) is extern import String::to_cstring`{
+       fun show ( parent : GtkWindow, params : String ) is extern import String.to_cstring`{
                gtk_show_about_dialog( parent, String_to_cstring( params ), NULL);
        `}
 end
@@ -133,7 +133,7 @@ extern GtkAppChooserDialog `{GtkAppChooserDialog *`}
        #       return (GtkAppChooserDialog *)gtk_app_chooser_dialog_new( parent, flags, file );
        #`}
 
-       new for_content_type ( parent : GtkWindow, flags : GtkDialogFlags, content_type : String ) is extern  import String::to_cstring `{
+       new for_content_type ( parent : GtkWindow, flags : GtkDialogFlags, content_type : String ) is extern  import String.to_cstring `{
                return (GtkAppChooserDialog *)gtk_app_chooser_dialog_new_for_content_type( parent, flags,                                                                                                                                                                                       String_to_cstring( content_type ) );
        `}
 
@@ -143,7 +143,7 @@ extern GtkAppChooserDialog `{GtkAppChooserDialog *`}
                return NativeString_to_s( (char *)gtk_app_chooser_dialog_get_heading( recv ) );
        `}
 
-       fun heading=( text : String ) is extern import String::to_cstring `{
+       fun heading=( text : String ) is extern import String.to_cstring `{
                gtk_app_chooser_dialog_set_heading( recv, String_to_cstring( text ) );
        `}
 
@@ -154,7 +154,7 @@ end
 extern GtkColorChooserDialog `{GtkColorChooserDialog *`}
        super GtkDialog
 
-       new ( title : String, parent : GtkWindow ) is extern import String::to_cstring `{
+       new ( title : String, parent : GtkWindow ) is extern import String.to_cstring `{
                return (GtkColorChooserDialog *)gtk_color_chooser_dialog_new( String_to_cstring( title ), parent );
        `}
 end
@@ -164,7 +164,7 @@ end
 extern GtkFileChooserDialog `{GtkFileChooserDialog *`}
        super GtkDialog
 
-       new ( title : String, parent : GtkWindow, action : GtkFileChooserAction ) is extern import String::to_cstring `{
+       new ( title : String, parent : GtkWindow, action : GtkFileChooserAction ) is extern import String.to_cstring `{
                return (GtkFileChooserDialog *)gtk_file_chooser_dialog_new( String_to_cstring( title ), parent, action, "", NULL );
        `}
 end
@@ -201,7 +201,7 @@ end
 extern GtkMessageDialog `{GtkMessageDialog *`}
        super GtkDialog
 
-       new ( parent : GtkWindow, flags : GtkDialogFlags, msg_type : GtkMessageType, btn_type : GtkButtonsType, format : String ) is extern import String::to_cstring `{
+       new ( parent : GtkWindow, flags : GtkDialogFlags, msg_type : GtkMessageType, btn_type : GtkButtonsType, format : String ) is extern import String.to_cstring `{
                return (GtkMessageDialog *)gtk_message_dialog_new( parent, flags, msg_type, btn_type, String_to_cstring( format ), NULL );
        `}
 end
index c0ea16d..a1793db 100644 (file)
@@ -130,11 +130,11 @@ extern GtkProgressBar `{GtkProgressBar *`}
                gtk_progress_bar_set_show_text( recv, show );
        `}
 
-       fun text : String is extern import String::to_cstring`{
+       fun text : String is extern import String.to_cstring`{
                return NativeString_to_s( (char *)gtk_progress_bar_get_text( recv ) );
        `}
 
-       fun text=( value : String) is extern import String::to_cstring`{
+       fun text=( value : String) is extern import String.to_cstring`{
                gtk_progress_bar_set_text( recv, String_to_cstring( value ) );
        `}
 
@@ -144,7 +144,7 @@ end
 
 extern GtkColorSelectionDialog
        super GtkWidget
-       new ( title : String, parent : GtkWindow ) is extern  import String::to_cstring `{
+       new ( title : String, parent : GtkWindow ) is extern  import String.to_cstring `{
                 return gtk_color_chooser_dialog_new( String_to_cstring( title ), parent );
        `}
 
index f412c87..ab1cb2a 100644 (file)
@@ -15,13 +15,18 @@ module json_reader
 
 intrude import jsonable
 
+in "C Header" `{
+       #define __STRICT_ANSI__
+       #include <json/json.h>
+`}
+
 redef class String
        # Deserializes this String and return its value as a Map[String, nullable Jsonable]
        # On error, null is returned.
-       fun json_to_object : nullable Map[String, nullable Jsonable] import NativeString::to_s, JsonObject::json_to_map `{
+       fun json_to_object : nullable Map[String, nullable Jsonable] import NativeString.to_s, JsonObject.json_to_map `{
                char *native_recv;
                json_object *jobj;
-               nullable_Map map;
+               nullable_Map_of_String_nullable_Jsonable map;
 
                native_recv = String_to_cstring( recv );
                jobj = json_tokener_parse( native_recv );
@@ -34,13 +39,13 @@ end
 
 redef extern JsonObject
        # Get this json object as a Map
-       private fun json_to_map : nullable Map[String, nullable Jsonable] import NativeString::to_s, String::to_cstring, HashMap, HashMap::[]=, json_cross, HashMap[String,nullable Jsonable] as( nullable Map[String,nullable Jsonable] ), String as ( Object ), nullable Jsonable as (nullable Object) `{
-               HashMap map;
+       private fun json_to_map : nullable Map[String, nullable Jsonable] import NativeString.to_s, String.to_cstring, HashMap[String,nullable Jsonable], HashMap[String,nullable Jsonable].[]=, json_cross, HashMap[String, nullable Jsonable].as(nullable Map[String, nullable Jsonable]) `{
+               HashMap_of_String_nullable_Jsonable map;
                String nit_key;
                nullable_Jsonable nit_val;
                enum json_type type;
 
-               map = new_HashMap();
+               map = new_HashMap_of_String_nullable_Jsonable();
 
                { /* prevents "mixed declaration and code" warning for C90 */
                json_object_object_foreach( recv, key, val ) {
@@ -51,11 +56,11 @@ redef extern JsonObject
 
                        nit_val = JsonObject_json_cross( val, type );
 
-                       HashMap__index_assign( map, String_as_Object( nit_key ), nullable_Jsonable_as_nullable_Object( nit_val ) );
+                       HashMap_of_String_nullable_Jsonable__index_assign( map, nit_key, nit_val );
                }
                }
 
-               return HashMap_as_nullable_Map( map );
+               return HashMap_of_String_nullable_Jsonable_as_nullable_Map_of_String_nullable_Jsonable( map );
        `}
 
        # Get this json object as a Bool
@@ -74,31 +79,31 @@ redef extern JsonObject
        `}
 
        # Get this json object as a Sequence
-       private fun json_to_sequence : Sequence[Jsonable] import Array, Array::push, Array[nullable Jsonable] as ( Sequence[nullable Jsonable] ), json_cross `{
+       private fun json_to_sequence : Sequence[nullable Jsonable] import Array[nullable Jsonable], Array[nullable Jsonable].push, json_cross, Array[nullable Jsonable].as(Sequence[nullable Jsonable]) `{
                array_list* jlist;
                json_object* jobj;
                nullable_Jsonable obj;
-               Array dest;
+               Array_of_nullable_Jsonable dest;
                int i;
                int len;
                enum json_type type;
 
                jlist = json_object_get_array( recv );
                len = json_object_array_length( recv );
-               dest = new_Array();
+               dest = new_Array_of_nullable_Jsonable();
                for ( i = 0; i < len; i ++ ) {
                        jobj = json_object_array_get_idx( recv, i );
                        if ( jobj == NULL ) type = json_type_null;
                        else type = json_object_get_type( jobj );
                        obj = JsonObject_json_cross( jobj, type );
-                       Array_push( dest, nullable_Jsonable_as_nullable_Object( obj ) );
+                       Array_of_nullable_Jsonable_push( dest, obj );
                }
 
-               return Array_as_Sequence( dest );
+               return Array_of_nullable_Jsonable_as_Sequence_of_nullable_Jsonable( dest );
        `}
 
        # Get this json object as a String
-       private fun json_to_string : String import NativeString::to_s `{
+       private fun json_to_string : String import NativeString.to_s `{
                const char *cstring;
                cstring = json_object_get_string( recv );
                return NativeString_to_s( (char*)cstring );
index 5e5cef2..9997664 100644 (file)
@@ -15,6 +15,11 @@ module json_writer
 
 intrude import jsonable
 
+in "C Header" `{
+       #define __STRICT_ANSI__
+       #include <json/json.h>
+`}
+
 redef interface Jsonable
        # Get a JsonObject representing this instance, specific to the C library
        private fun to_json_object : JsonObject is abstract
@@ -31,7 +36,7 @@ redef class Map[ K, V ]
                const char *json_native_string;
                String json_string;
 
-               jobj = Map_to_json_object( recv );
+               jobj = Map_of_Object_nullable_Object_to_json_object( recv );
 #ifdef JSON_C_TO_STRING_PRETTY
                if ( pretty )
                        json_native_string = json_object_to_json_string_ext( jobj, JSON_C_TO_STRING_PRETTY );
@@ -93,7 +98,7 @@ redef class Sequence[ E ]
 end
 
 redef class String
-       redef fun to_json_object import NativeString::to_s `{
+       redef fun to_json_object import NativeString.to_s `{
                char *native_recv = String_to_cstring( recv );
                return json_object_new_string( native_recv );
        `}
@@ -121,16 +126,16 @@ redef class JsonObject
        new `{ return json_object_new_object(); `}
 
        # Add a key and value to the object
-       fun add( key : String, val : nullable JsonObject ) import String::to_cstring, nullable JsonObject as not nullable `{
+       fun add( key : String, val : nullable JsonObject ) import String.to_cstring, JsonObject as not nullable `{
                char* native_key;
 
                native_key = String_to_cstring( key );
 
-               if ( JsonObject_is_null(val) ) {
+               if ( nullable_JsonObject_is_null(val) ) {
                        json_object_object_add( recv, native_key, NULL );
                } else {
                        json_object *jobj;
-                       jobj = JsonObject_as_not_null( val );
+                       jobj = nullable_JsonObject_as_JsonObject( val );
                        json_object_object_add( recv, native_key, jobj );
                }
        `}
@@ -142,9 +147,9 @@ private extern JsonArray
        new `{ return json_object_new_array(); `}
 
        fun push( val : nullable JsonObject ) `{
-               if ( JsonObject_is_null(val) )
+               if ( nullable_JsonObject_is_null(val) )
                        json_object_array_add( recv, NULL );
                else
-                       json_object_array_add( recv, JsonObject_as_not_null(val) );
+                       json_object_array_add( recv, nullable_JsonObject_as_JsonObject(val) );
        `}
 end
index 2a87ed9..fbf4a00 100644 (file)
@@ -27,7 +27,7 @@ interface Jsonable
 end
 
 # Main object type used by C library
-private extern JsonObject `{ json_object* `}
+private extern JsonObject `{ struct json_object* `}
        # Give up ownership of this object and decrease the reference count.
        fun put `{ json_object_put( recv ); `}
 
index 63cb639..f0b028e 100644 (file)
@@ -492,7 +492,7 @@ in "C Header" `{
 redef class String
        # returns the md5 digest of the receiver string
        # algorithm implemented by L. Peter Deutsch <ghost@aladdin.com>
-       fun md5: String import String::to_cstring, NativeString::to_s, String::print `{
+       fun md5: String import String.to_cstring, NativeString.to_s, String.print `{
                md5_state_t state;
                md5_byte_t digest[16]; /* result */
                char *hex_output = malloc(33*sizeof(char));
index 182d9d0..e45cac9 100644 (file)
@@ -462,7 +462,7 @@ extern Opengles1Image in "C" `{struct mnit_opengles_Texture *`}
     redef fun blended: Bool is extern `{ return recv->blended; `}
 
     # inherits scale and blend from source
-    redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image as ( Image ) `{
+    redef fun subimage( x, y, w, h: Int ): Image is extern import Opengles1Image.as( Image ) `{
                struct mnit_opengles_Texture* image =
                        malloc( sizeof( struct mnit_opengles_Texture ) );
 
index 8edf757..e27771b 100644 (file)
@@ -92,7 +92,7 @@ redef extern Opengles1Image
        `}
 
        # using sdl
-       new from_file( path: String ) is extern import String::to_cstring `{
+       new from_file( path: String ) is extern import String.to_cstring `{
                SDL_Surface *sdl_image;
                struct mnit_opengles_Texture *opengles_image;
 
index 55d4d07..256b070 100644 (file)
@@ -97,7 +97,7 @@ extern SDLDisplay in "C" `{SDL_Surface *`}
                return events
        end
 
-       private fun poll_event: nullable IE is extern import SDLKeyEvent, SDLMouseButtonEvent, SDLMouseMotionEvent, SDLQuitEvent, NativeString::to_s, SDLMouseButtonEvent as (nullable IE), SDLMouseMotionEvent as (nullable IE), SDLKeyEvent as (nullable IE), SDLQuitEvent as (nullable IE) `{
+       private fun poll_event: nullable IE is extern import SDLKeyEvent, SDLMouseButtonEvent, SDLMouseMotionEvent, SDLQuitEvent, NativeString.to_s, SDLMouseButtonEvent.as(nullable IE), SDLMouseMotionEvent.as(nullable IE), SDLKeyEvent.as(nullable IE), SDLQuitEvent.as(nullable IE) `{
                SDL_Event event;
 
                SDL_PumpEvents();
@@ -185,8 +185,8 @@ extern SDLImage in "C" `{SDL_Surface*`} # TODO remove
        super DrawableImage
        super SDLDrawable
 
-        # Import image from a file
-       new from_file( path: String ) is extern import String::to_cstring `{
+       # Import image from a file
+       new from_file( path: String ) is extern import String.to_cstring `{
                SDL_Surface *image = IMG_Load( String_to_cstring( path ) );
                return image;
        `}
@@ -211,7 +211,7 @@ extern SDLImage in "C" `{SDL_Surface*`} # TODO remove
                return new_image;
        `}
 
-        # Save the image into the specified file
+       # Save the image into the specified file
        fun save_to_file( path: String ) is extern import String::to_cstring `{ `}
 
         # Destroy the image and free the memory
@@ -330,7 +330,7 @@ class SDLKeyEvent
 
        redef fun to_c: nullable Char
        do
-               if key_name.length == 1 then return key_name.first
+               if key_name.length == 1 then return key_name.chars.first
                return null
        end
 
@@ -367,8 +367,8 @@ end
 
 # Class to load and use TTF_Font
 extern SDLFont in "C" `{TTF_Font *`}
-        #Load a font with a specified name and size
-       new ( name: String, points: Int ) is extern import String::to_cstring `{
+       # Load a font with a specified name and size
+       new ( name: String, points: Int ) is extern import String.to_cstring `{
        char * cname = String_to_cstring( name );
 
        TTF_Font *font = TTF_OpenFont( cname, (int)points);
@@ -381,8 +381,9 @@ extern SDLFont in "C" `{TTF_Font *`}
        `}
 
        fun destroy is extern `{ TTF_CloseFont( recv ); `}
-        #Create a String with the specified color, return an SDLImage
-       fun render( text: String, r, g, b: Int ): SDLImage is extern import String::to_cstring `{
+
+       # Create a String with the specified color, return an SDLImage
+       fun render( text: String, r, g, b: Int ): SDLImage is extern import String.to_cstring `{
                SDL_Color color;
                SDL_Surface *text_surface;
                char *ctext;
@@ -421,7 +422,7 @@ extern SDLFont in "C" `{TTF_Font *`}
                return TTF_FontDescent( recv );
        `}
 
-       # Get the recommended pixel height of a rendered line of text of the loaded font. This is usually larger than the Font::height.
+       # Get the recommended pixel height of a rendered line of text of the loaded font. This is usually larger than the Font.height.
        fun line_skip: Int is extern `{
                return TTF_FontLineSkip( recv );
        `}
@@ -432,7 +433,7 @@ extern SDLFont in "C" `{TTF_Font *`}
        `}
 
        # Return the family name of the font
-       fun family_name: nullable String is extern import String::to_cstring, String as nullable `{
+       fun family_name: nullable String is extern import String.to_cstring, String as nullable `{
                char *fn = TTF_FontFaceFamilyName( recv );
 
                if ( fn == NULL )
@@ -442,7 +443,7 @@ extern SDLFont in "C" `{TTF_Font *`}
        `}
 
        # Return the style name of the font
-       fun style_name: nullable String is extern import String::to_cstring, String as nullable `{
+       fun style_name: nullable String is extern import String.to_cstring, String as nullable `{
                char *sn = TTF_FontFaceStyleName( recv );
 
                if ( sn == NULL )
@@ -451,8 +452,8 @@ extern SDLFont in "C" `{TTF_Font *`}
                        return String_as_nullable( NativeString_to_s( sn ) );
        `}
 
-        # Return the estimated width of a String if used with the current font
-       fun width_of( text: String ): Int is extern import NativeString::to_s `{
+       # Return the estimated width of a String if used with the current font
+       fun width_of( text: String ): Int is extern import NativeString.to_s `{
                char *ctext = String_to_cstring( text );
                int w;
                if ( TTF_SizeText( recv, ctext, &w, NULL ) )
index 1ac2326..ec3c006 100644 (file)
@@ -138,7 +138,7 @@ abstract class OptionParameter
        redef fun read_param(it)
        do
                super
-               if it.is_ok and it.item.first != '-' then
+               if it.is_ok and it.item.chars.first != '-' then
                        value = convert(it.item)
                        it.next
                else
@@ -273,7 +273,7 @@ class OptionContext
                                if str.last_index_of('-') == 0 and str.length > 2 then
                                        var next_called = false
                                        for i in [1..str.length] do
-                                               var short_opt = "-" + str[i].to_s
+                                               var short_opt = "-" + str.chars[i].to_s
                                                if _optmap.has_key(short_opt) then
                                                        var option = _optmap[short_opt]
                                                        if option isa OptionParameter then
index cbcde4d..88e5950 100644 (file)
@@ -208,7 +208,7 @@ redef interface Object
        # Check signals for safe operation
        # will callback receiver of raised signals
        # can callback any instance of SignalHandler, not just this one
-       protected fun check_signals: Bool is extern import SignalHandler::receive_signal `{
+       protected fun check_signals: Bool is extern import SignalHandler.receive_signal `{
                int sig;
                int raised_something = 0;
 
index 0e6d020..5eeefdd 100644 (file)
@@ -114,9 +114,9 @@ extern FFSocket `{ S_DESCRIPTOR* `}
        fun descriptor: Int `{ return *recv; `}
        fun errno: Int `{ return errno; `}
 
-       fun gethostbyname(n: String): FFSocketHostent import String::to_cstring `{ return gethostbyname(String_to_cstring(n)); `}
+       fun gethostbyname(n: String): FFSocketHostent import String.to_cstring `{ return gethostbyname(String_to_cstring(n)); `}
        fun connect(addrIn: FFSocketAddrIn): Int `{ return connect( *recv, (S_ADDR*)addrIn, sizeof(*addrIn) ); `}
-       fun write(buffer: String): Int import String::to_cstring, String::length `{ return write(*recv, (char*)String_to_cstring(buffer), String_length(buffer)); `}
+       fun write(buffer: String): Int import String.to_cstring, String.length `{ return write(*recv, (char*)String_to_cstring(buffer), String_length(buffer)); `}
 
        fun read: String `{
                char *c = (char*)malloc(1024);
index a040ee2..2fa105c 100644 (file)
@@ -60,7 +60,7 @@ extern class Sqlite3Code `{int`}
        new done `{ return SQLITE_DONE; `} #       101  /* sqlite3_step() has finished executing */
        fun is_done: Bool `{ return recv == SQLITE_DONE; `}
 
-       redef fun to_s: String import NativeString::to_s `{
+       redef fun to_s: String import NativeString.to_s `{
 #if SQLITE_VERSION_NUMBER >= 3007015
                char *err = (char *)sqlite3_errstr(recv);
 #else
@@ -77,7 +77,7 @@ extern class Statement `{sqlite3_stmt*`}
                return sqlite3_step(recv);
        `}
 
-       fun column_name(i: Int) : String import NativeString::to_s `{
+       fun column_name(i: Int) : String import NativeString.to_s `{
                const char * name = (sqlite3_column_name(recv, i));
                if(name == NULL){
                        name = "";
@@ -98,7 +98,7 @@ extern class Statement `{sqlite3_stmt*`}
                return sqlite3_column_int(recv, i);
        `}
 
-       fun column_text(i: Int) : String import NativeString::to_s `{
+       fun column_text(i: Int) : String import NativeString.to_s `{
                char * ret = (char *) sqlite3_column_text(recv, i);
                if( ret == NULL ){
                        ret = "";
@@ -120,7 +120,7 @@ extern class Statement `{sqlite3_stmt*`}
 end
 
 extern class Sqlite3 `{sqlite3 *`}
-       new open(filename: String) import String::to_cstring `{
+       new open(filename: String) import String.to_cstring `{
                sqlite3 *self;
                sqlite3_open(String_to_cstring(filename), &self);
                return self;
@@ -130,11 +130,11 @@ extern class Sqlite3 `{sqlite3 *`}
 
        fun close `{ sqlite3_close(recv); `}
 
-       fun exec(sql : String): Sqlite3Code import String::to_cstring `{
+       fun exec(sql : String): Sqlite3Code import String.to_cstring `{
                return sqlite3_exec(recv, String_to_cstring(sql), 0, 0, 0);
        `}
 
-       fun prepare(sql: String): nullable Statement import String::to_cstring, Statement as nullable `{
+       fun prepare(sql: String): nullable Statement import String.to_cstring, Statement as nullable `{
                sqlite3_stmt *stmt;
                int res = sqlite3_prepare_v2(recv, String_to_cstring(sql), -1, &stmt, 0);
                if (res == SQLITE_OK)
index 239f785..cbb8ac6 100644 (file)
@@ -20,6 +20,14 @@ intrude import string
 import string_search
 import time
 
+in "C Header" `{
+       #include <dirent.h>
+       #include <string.h>
+       #include <sys/types.h>
+       #include <sys/stat.h>
+       #include <unistd.h>
+`}
+
 redef class Object
 # Simple I/O
 
@@ -240,7 +248,7 @@ redef class String
        fun dirname: String
        do
                var l = _length - 1 # Index of the last char
-               if l > 0 and self[l] == '/' then l -= 1 # remove trailing `/`
+               if l > 0 and self.chars[l] == '/' then l -= 1 # remove trailing `/`
                var pos = last_index_of_from('/', l)
                if pos > 0 then
                        return substring(0, pos)
@@ -309,7 +317,7 @@ redef class String
        do
                if path.is_empty then return self
                if self.is_empty then return path
-               if path[0] == '/' then return path
+               if path.chars[0] == '/' then return path
                return "{self}/{path}"
        end
 
@@ -353,7 +361,36 @@ redef class String
        end
 
        # returns files contained within the directory represented by self
-       fun files : Set[ String ] is extern import HashSet, HashSet::add, NativeString::to_s, String::to_cstring, HashSet[String] as( Set[String] ), String as( Object )
+       fun files : Set[ String ] is extern import HashSet[String], HashSet[String].add, NativeString.to_s, String.to_cstring, HashSet[String].as(Set[String]) `{
+               char *dir_path;
+               DIR *dir;
+
+               dir_path = String_to_cstring( recv );
+               if ((dir = opendir(dir_path)) == NULL)
+               {
+                       perror( dir_path );
+                       exit( 1 );
+               }
+               else
+               {
+                       HashSet_of_String results;
+                       String file_name;
+                       struct dirent *de;
+
+                       results = new_HashSet_of_String();
+
+                       while ( ( de = readdir( dir ) ) != NULL )
+                               if ( strcmp( de->d_name, ".." ) != 0 &&
+                                       strcmp( de->d_name, "." ) != 0 )
+                               {
+                                       file_name = NativeString_to_s( strdup( de->d_name ) );
+                                       HashSet_of_String_add( results, file_name );
+                               }
+
+                       closedir( dir );
+                       return HashSet_of_String_as_Set_of_String( results );
+               }
+       `}
 end
 
 redef class NativeString
index ca02ba1..06f5e2e 100644 (file)
 
 #include "file_nit.h"
 
-#ifndef NONITCNI
-/*
-C implementation of file::String::files
-
-Imported methods signatures:
-       HashSet new_HashSet(  ) for hash_collection::HashSet::init
-       void HashSet_add( HashSet recv, Object item ) for hash_collection::HashSet::(abstract_collection::SimpleCollection::add)
-       String NativeString_to_s() for string::NativeString::to_s
-       int HashSet_is_a_Set( HashSet value ) to check if a HashSet[String] is a Set[String]
-       Set HashSet_as_Set( HashSet value ) to cast from HashSet[String] to Set[String]
-*/
-Set String_files___impl( String recv )
-{
-       char *dir_path;
-       DIR *dir;
-
-       dir_path = String_to_cstring( recv );
-       if ((dir = opendir(dir_path)) == NULL)
-       {
-               perror( dir_path );
-               exit( 1 );
-       }
-       else
-       {
-               HashSet results;
-               String file_name;
-               struct dirent *de;
-
-               results = new_HashSet();
-
-               while ( ( de = readdir( dir ) ) != NULL )
-                       if ( strcmp( de->d_name, ".." ) != 0 &&
-                               strcmp( de->d_name, "." ) != 0 )
-                       {
-                               file_name = NativeString_to_s( strdup( de->d_name ) );
-                               HashSet_add( results, String_as_Object( file_name ) );
-                       }
-
-               closedir( dir );
-               return HashSet_as_Set( results );
-       }
-}
-#endif
-
 int string_NativeString_NativeString_file_exists_0(char *f){
        FILE *hdl = fopen(f,"r");
        if(hdl != NULL){
index 6d7967f..1f5b183 100644 (file)
 #include <stdio.h>
 #include <sys/types.h>
 
-#ifndef NONITCNI
-#include <file._nitni.h>
-
-Set String_files___impl( String recv );
-#endif
-
 extern int string_NativeString_NativeString_file_exists_0(char *f);
 extern void *string_NativeString_NativeString_file_stat_0(char *f);
 extern void *file_NativeFile_NativeFile_file_stat_0(FILE *f);
index 269f3bc..5d73c8e 100644 (file)
@@ -38,6 +38,7 @@ redef class Float
        fun acos: Float is extern "kernel_Float_Float_acos_0"
        fun asin: Float is extern "kernel_Float_Float_asin_0"
        fun atan: Float is extern "kernel_Float_Float_atan_0"
+       fun abs: Float `{ return abs(recv); `}
 
        fun pow(e: Float): Float is extern "kernel_Float_Float_pow_1"
        fun log: Float is extern "kernel_Float_Float_log_0"
index 4fd6a03..4ac70a1 100644 (file)
@@ -42,34 +42,34 @@ end
 
 extern class Passwd `{struct passwd*`}
        new from_uid(uid: Int) `{ return getpwuid(uid); `}
-       new from_name(name: String) import String::to_cstring `{ return getpwnam( String_to_cstring(name) ); `}
+       new from_name(name: String) import String.to_cstring `{ return getpwnam( String_to_cstring(name) ); `}
 
-       fun name: String import NativeString::to_s `{ return NativeString_to_s(recv->pw_name); `}
-       fun passwd: String import NativeString::to_s `{ return NativeString_to_s(recv->pw_passwd); `}
+       fun name: String import NativeString.to_s `{ return NativeString_to_s(recv->pw_name); `}
+       fun passwd: String import NativeString.to_s `{ return NativeString_to_s(recv->pw_passwd); `}
        fun uid: Int `{ return recv->pw_uid; `}
        fun gid: Int `{ return recv->pw_gid; `}
-       fun gecos: String import NativeString::to_s `{ return NativeString_to_s(recv->pw_gecos); `}
-       fun dir: String import NativeString::to_s `{ return NativeString_to_s(recv->pw_dir); `}
-       fun shell: String import NativeString::to_s `{ return NativeString_to_s(recv->pw_shell); `}
+       fun gecos: String import NativeString.to_s `{ return NativeString_to_s(recv->pw_gecos); `}
+       fun dir: String import NativeString.to_s `{ return NativeString_to_s(recv->pw_dir); `}
+       fun shell: String import NativeString.to_s `{ return NativeString_to_s(recv->pw_shell); `}
 end
 
 extern class Group `{struct group*`}
        new from_gid(gid: Int) `{ return getgrgid(gid); `}
-       new from_name(name: String) import String::to_cstring `{ return getgrnam( String_to_cstring(name) ); `}
+       new from_name(name: String) import String.to_cstring `{ return getgrnam( String_to_cstring(name) ); `}
 
-       fun name: String import NativeString::to_s `{ return NativeString_to_s(recv->gr_name); `}
-       fun passwd: String import NativeString::to_s `{ return NativeString_to_s(recv->gr_passwd); `}
+       fun name: String import NativeString.to_s `{ return NativeString_to_s(recv->gr_name); `}
+       fun passwd: String import NativeString.to_s `{ return NativeString_to_s(recv->gr_passwd); `}
        fun gid: Int `{ return recv->gr_gid; `}
-       fun mem: Array[String] import Array, Array::add, NativeString::to_s, String as (nullable Object) `{
+       fun mem: Array[String] import Array[String], Array[String].add, NativeString.to_s `{
                char **mem;
                int m;
-               Array ret;
+               Array_of_String ret;
 
                mem = recv->gr_mem;
-               ret = new_Array();
+               ret = new_Array_of_String();
 
                for (m = 0; mem[m] != NULL; m++)
-                       Array_add(ret, String_as_nullable_Object( NativeString_to_s(mem[m]) ));
+                       Array_of_String_add(ret, NativeString_to_s(mem[m]));
 
                return ret;
        `}
index 4cfac4e..d11fa21 100644 (file)
@@ -16,7 +16,6 @@
 module standard
 
 import posix
-import ropes
 import environ 
 import time
 import string_search
index c63e38a..745064a 100644 (file)
@@ -15,6 +15,13 @@ module stream
 
 import string
 
+in "C" `{
+       #include <unistd.h>
+       #include <poll.h>
+       #include <errno.h>
+       #include <string.h>
+`}
+
 # Abstract stream class
 interface IOS
        # close the stream
@@ -70,7 +77,7 @@ interface IStream
                                if eof then return
                        else
                                var c = x.ascii
-                               s.push(c)
+                               s.chars.push(c)
                                if c == '\n' then return
                        end
                end
@@ -103,7 +110,7 @@ abstract class BufferedIStream
                if _buffer_pos >= _buffer.length then
                        return -1
                end
-               var c = _buffer[_buffer_pos]
+               var c = _buffer.chars[_buffer_pos]
                _buffer_pos += 1
                return c.ascii
        end
@@ -121,7 +128,7 @@ abstract class BufferedIStream
                                k = _buffer.length
                        end
                        while j < k and i > 0 do
-                               s.add(_buffer[j])
+                               s.add(_buffer.chars[j])
                                j +=  1
                                i -= 1
                        end
@@ -137,7 +144,7 @@ abstract class BufferedIStream
                        var j = _buffer_pos
                        var k = _buffer.length
                        while j < k do
-                               s.add(_buffer[j])
+                               s.add(_buffer.chars[j])
                                j += 1
                        end
                        _buffer_pos = j
@@ -151,7 +158,7 @@ abstract class BufferedIStream
                loop
                        # First phase: look for a '\n'
                        var i = _buffer_pos
-                       while i < _buffer.length and _buffer[i] != '\n' do i += 1
+                       while i < _buffer.length and _buffer.chars[i] != '\n' do i += 1
 
                        # if there is something to append
                        if i > _buffer_pos then
@@ -161,7 +168,7 @@ abstract class BufferedIStream
                                # Copy from the buffer to the string
                                var j = _buffer_pos
                                while j < i do
-                                       s.add(_buffer[j])
+                                       s.add(_buffer.chars[j])
                                        j += 1
                                end
                        end
@@ -295,7 +302,57 @@ redef interface Object
                end
        end
 
-       private fun intern_poll( in_fds : Array[Int], out_fds : Array[Int] ) : nullable Int is extern import Array::length, Array::[], nullable Object as ( Int ), Int as nullable
+       private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]) : nullable Int is extern import Array[Int].length, Array[Int].[], Int.as(nullable Int) `{
+               int in_len, out_len, total_len;
+               struct pollfd *c_fds;
+               sigset_t sigmask;
+               int i;
+               int first_polled_fd = -1;
+               int result;
+
+               in_len = Array_of_Int_length( in_fds );
+               out_len = Array_of_Int_length( out_fds );
+               total_len = in_len + out_len;
+               c_fds = malloc( sizeof(struct pollfd) * total_len );
+
+               /* input streams */
+               for ( i=0; i<in_len; i ++ ) {
+                       int fd;
+                       fd = Array_of_Int__index( in_fds, i );
+
+                       c_fds[i].fd = fd;
+                       c_fds[i].events = POLLIN;
+               }
+
+               /* output streams */
+               for ( i=0; i<out_len; i ++ ) {
+                       int fd;
+                       fd = Array_of_Int__index( out_fds, i );
+
+                       c_fds[i].fd = fd;
+                       c_fds[i].events = POLLOUT;
+               }
+
+               /* poll all fds, unlimited timeout */
+               result = poll( c_fds, total_len, -1 );
+
+               if ( result > 0 ) {
+                       /* analyse results */
+                       for ( i=0; i<total_len; i++ )
+                               if ( c_fds[i].revents & c_fds[i].events || /* awaited event */
+                                        c_fds[i].revents & POLLHUP ) /* closed */
+                               {
+                                       first_polled_fd = c_fds[i].fd;
+                                       break;
+                               }
+
+                       return Int_as_nullable( first_polled_fd );
+               }
+               else if ( result < 0 )
+                       fprintf( stderr, "Error in Stream:poll: %s\n", strerror( errno ) );
+
+               return null_Int();
+       `}
 end
 
 # Stream to a String. Mainly used for compatibility with OStream type and tests.
index de71a41..14bfece 100644 (file)
 
 #include "stream_nit.h"
 
-#include <poll.h>
-#include <errno.h>
-
 int stream_FDStream_FDStream_native_read_char_1(void *s, int fd) {
        int result;
        char buf;
        ssize_t r = read(fd, &buf, 1);
-       if (r == 0) 
+       if (r == 0)
                result = -1;
-       else 
+       else
                result = buf;
        return result;
 }
-#ifndef NONITCNI
-
-/*
-C implementation of stream::Object::intern_poll
-
-Imported methods signatures:
-       bigint Array_length( Array recv ) for array::AbstractArrayRead::(abstract_collection::Collection::length)
-       nullable_Object Array__index( Array recv, bigint index ) for array::Array::(abstract_collection::SequenceRead::[])
-       int nullable_Object_is_a_bigint( nullable_Object value ) to check if a nullable Object is a Int
-       bigint nullable_Object_as_bigint( nullable_Object value ) to cast from nullable Object to Int
-       int Int_is_null( nullable_Int value ) to check if a nullable Int is a Int
-       bigint bigint_as_not_null( nullable_Int value ) to cast from nullable Int to Int
-*/
-nullable_Int Object_intern_poll___impl( Object recv, Array in_fds, Array out_fds ) {
-       int in_len, out_len, total_len;
-       struct pollfd *c_fds;
-       sigset_t sigmask;
-       int i;
-       nullable_Object tmp_nit_obj;
-       int first_polled_fd = -1;
-       int result;
-
-       in_len = Array_length( in_fds );
-       out_len = Array_length( out_fds );
-       total_len = in_len + out_len;
-       c_fds = malloc( sizeof(struct pollfd) * total_len );
-
-       /* input streams */
-       for ( i=0; i<in_len; i ++ ) {
-               int fd;
-               tmp_nit_obj = Array__index( in_fds, i );
-               fd = nullable_Object_as_Int( tmp_nit_obj );
-
-               c_fds[i].fd = fd;
-               c_fds[i].events = POLLIN;
-       }
-
-       /* output streams */
-       for ( i=0; i<out_len; i ++ ) {
-               int fd;
-               tmp_nit_obj = Array__index( out_fds, i );
-               fd = nullable_Object_as_Int( tmp_nit_obj );
-
-               c_fds[i].fd = fd;
-               c_fds[i].events = POLLOUT;
-       }
-
-       /* poll all fds, unlimited timeout */
-       result = poll( c_fds, total_len, -1 );
-
-       if ( result > 0 ) {
-               /* analyse results */
-               for ( i=0; i<total_len; i++ )
-                       if ( c_fds[i].revents & c_fds[i].events || /* awaited event */
-                                c_fds[i].revents & POLLHUP ) /* closed */
-                       {
-                               first_polled_fd = c_fds[i].fd;
-                               break;
-                       }
-
-               return Int_as_nullable( first_polled_fd );
-       }
-       else if ( result < 0 )
-               fprintf( stderr, "Error in Stream:poll: %s\n", strerror( errno ) );
-
-       return null_Int();
-}
-#endif
index b28e56a..3a4d51e 100644 (file)
 
 int stream_FDStream_FDStream_native_read_char_1(void *s, int fd);
 
-#ifndef NONITCNI
-#include <stream._nitni.h>
-nullable_Int Object_intern_poll___impl( Object recv, Array in_fds, Array out_fds );
-#endif
-
 #define stream_FDStream_FDStream_native_close_1(self, p0) (close(p0))
 #define stream_FDStream_FDStream_native_read_3(s, i, b, l) read((i), ((b)), ((l)))
 #define stream_FDStream_FDStream_native_write_3(s, i, b, l) write((i), ((b)), ((l)))
index 4326d04..b9ee718 100644 (file)
@@ -30,6 +30,8 @@ abstract class AbstractString
 
        readable private var _items: NativeString
 
+       fun chars: StringCharView is abstract
+
        # Access a character at `index` in the string.
        #
        #     assert "abcd"[2]         == 'c'
@@ -54,7 +56,7 @@ abstract class AbstractString
                if from < count then
                        var r = new Buffer.with_capacity(count - from)
                        while from < count do
-                               r.push(_items[from])
+                               r.chars.push(_items[from])
                                from += 1
                        end
                        return r.to_s
@@ -142,7 +144,7 @@ abstract class AbstractString
                var i = 0
                var neg = false
 
-               for c in self
+               for c in self.chars
                do
                        var v = c.to_i
                        if v > base then
@@ -173,7 +175,7 @@ abstract class AbstractString
        fun is_numeric: Bool
        do
                var has_point_or_comma = false
-               for i in self
+               for i in self.chars
                do
                        if not i.is_numeric
                        then
@@ -194,7 +196,7 @@ abstract class AbstractString
        fun to_upper: String
        do
                var s = new Buffer.with_capacity(length)
-               for i in self do s.add(i.to_upper)
+               for i in self.chars do s.add(i.to_upper)
                return s.to_s
        end
 
@@ -204,7 +206,7 @@ abstract class AbstractString
        fun to_lower : String
        do
                var s = new Buffer.with_capacity(length)
-               for i in self do s.add(i.to_lower)
+               for i in self.chars do s.add(i.to_lower)
                return s.to_s
        end
 
@@ -215,18 +217,18 @@ abstract class AbstractString
        #     assert "\na\nb\tc\t".trim          == "a\nb\tc"
        fun trim: String
        do
-               if self._length == 0 then return self.to_s
+               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
+               while self.chars[start_pos].ascii <= 32 do
                        start_pos += 1
-                       if start_pos == _length then return ""
+                       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
+               while self.chars[end_pos].ascii <= 32 do
                        end_pos -= 1
-                       if end_pos == start_pos then return self[start_pos].to_s
+                       if end_pos == start_pos then return self.chars[start_pos].to_s
                end
                return self.substring(start_pos, end_pos - start_pos + 1)
        end
@@ -245,7 +247,7 @@ abstract class AbstractString
        do
                var res = new Buffer
                var underscore = false
-               for c in self do
+               for c in self.chars do
                        if (c >= 'a' and c <= 'z') or (c >='A' and c <= 'Z') then
                                res.add(c)
                                underscore = false
@@ -278,7 +280,7 @@ abstract class AbstractString
        fun escape_to_c: String
        do
                var b = new Buffer
-               for c in self do
+               for c in self.chars do
                        if c == '\n' then
                                b.append("\\n")
                        else if c == '\0' then
@@ -357,6 +359,44 @@ abstract class AbstractString
        end
 end
 
+# Abstract class for the SequenceRead compatible
+# views on String and Buffer objects
+abstract class StringCharView
+       super SequenceRead[Char]
+
+       type SELFTYPE: AbstractString
+
+       private var target: SELFTYPE
+
+       private init(tgt: SELFTYPE)
+       do
+               target = tgt
+       end
+
+       redef fun is_empty do return target.is_empty
+
+       redef fun length do return target.length
+
+       redef fun has(c: Char): Bool
+       do
+               for i in self do
+                       if i == c then return true
+               end
+               return false
+       end
+
+end
+
+# View on Buffer objects, extends Sequence
+# for mutation operations
+abstract class BufferCharView
+       super StringCharView
+       super Sequence[Char]
+
+       redef type SELFTYPE: Buffer
+
+end
+
 # Immutable strings of characters.
 class String
        super Comparable
@@ -371,6 +411,8 @@ class String
        # Indes in _items of the last item of the string
        readable var _index_to: Int
 
+       redef var chars: StringCharView = new FlatStringCharView(self)
+
        ################################################
        #       AbstractString specific methods        #
        ################################################
@@ -395,11 +437,13 @@ class String
 
                var realFrom = _index_from + from
 
-               if (realFrom + count) > _index_to then return new String.from_substring(realFrom, _index_to, _items)
+               if (realFrom + count) > _index_to then return new String.with_infos(_items, _index_to - realFrom + 1, realFrom, _index_to)
 
                if count == 0 then return ""
 
-               return new String.from_substring(realFrom, realFrom + count - 1, _items)
+               var to = realFrom + count - 1
+
+               return new String.with_infos(_items, to - realFrom + 1, realFrom, to)
        end
 
        redef fun substring_from(from: Int): String
@@ -507,20 +551,6 @@ class String
        #              String Specific Methods           #
        ##################################################
 
-       # 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
-               _index_from = from
-               _index_to = to
-               _length = to - from + 1
-       end
-
        private init with_infos(items: NativeString, len: Int, from: Int, to: Int)
        do
                self._items = items
@@ -676,6 +706,50 @@ class String
        end
 end
 
+private class FlatStringIterator
+       super IndexedIterator[Char]
+
+       var target: String
+
+       var target_items: NativeString
+
+       var curr_pos: Int
+
+       init with_pos(tgt: String, pos: Int)
+       do
+               target = tgt
+               target_items = tgt.items
+               curr_pos = pos + target.index_from
+       end
+
+       redef fun is_ok do return curr_pos <= target.index_to
+
+       redef fun item do return target_items[curr_pos]
+
+       redef fun next do curr_pos += 1
+
+       redef fun index do return curr_pos - target.index_from
+
+end
+
+private class FlatStringCharView
+       super StringCharView
+
+       redef type SELFTYPE: String
+
+       redef fun [](index)
+       do
+               # Check that the index (+ index_from) is not larger than indexTo
+               # In other terms, if the index is valid
+               assert index >= 0
+               assert (index + target._index_from) <= target._index_to
+               return target._items[index + target._index_from]
+       end
+
+       redef fun iterator: IndexedIterator[Char] do return new FlatStringIterator.with_pos(target, 0)
+
+end
+
 # Mutable strings of characters.
 class Buffer
        super AbstractString
@@ -685,6 +759,8 @@ class Buffer
 
        redef type OTHER: String
 
+       redef var chars: BufferCharView = new FlatBufferCharView(self)
+
        redef fun []=(index, item)
        do
                if index == length then
@@ -743,8 +819,8 @@ class Buffer
                var l1 = length
                var l2 = s.length
                while i < l1 and i < l2 do
-                       var c1 = self[i].ascii
-                       var c2 = s[i].ascii
+                       var c1 = self.chars[i].ascii
+                       var c2 = s.chars[i].ascii
                        if c1 < c2 then
                                return true
                        else if c2 < c1 then
@@ -801,6 +877,81 @@ class Buffer
        readable private var _capacity: Int
 end
 
+private class FlatBufferCharView
+       super BufferCharView
+       super StringCapable
+
+       redef type SELFTYPE: Buffer
+
+       init(tgt: Buffer)
+       do
+               self.target = tgt
+       end
+
+       redef fun [](index) do return target._items[index]
+
+       redef fun []=(index, item)
+       do
+               assert index >= 0 and index <= length
+               if index == length then
+                       add(item)
+                       return
+               end
+               target._items[index] = item
+       end
+
+       redef fun push(c)
+       do
+               target.add(c)
+       end
+
+       redef fun add(c)
+       do
+               target.add(c)
+       end
+
+       fun enlarge(cap: Int)
+       do
+               target.enlarge(cap)
+       end
+
+       redef fun append(s)
+       do
+               var my_items = target.items
+               var s_length = s.length
+               if target.capacity < s.length then enlarge(s_length + target.length)
+       end
+
+       redef fun iterator: IndexedIterator[Char] do return new FlatBufferIterator.with_pos(target, 0)
+
+end
+
+private class FlatBufferIterator
+       super IndexedIterator[Char]
+
+       var target: Buffer
+
+       var target_items: NativeString
+
+       var curr_pos: Int
+
+       init with_pos(tgt: Buffer, pos: Int)
+       do
+               target = tgt
+               target_items = tgt.items
+               curr_pos = pos
+       end
+
+       redef fun index do return curr_pos
+
+       redef fun is_ok do return curr_pos < target.length
+
+       redef fun item do return target_items[curr_pos]
+
+       redef fun next do curr_pos += 1
+
+end
+
 ###############################################################################
 # Refinement                                                                  #
 ###############################################################################
@@ -859,9 +1010,9 @@ redef class Int
                # Sign
                if self < 0 then
                        n = - self
-                       s[0] = '-'
+                       s.chars[0] = '-'
                else if self == 0 then
-                       s[0] = '0'
+                       s.chars[0] = '0'
                        return
                else
                        n = self
@@ -869,7 +1020,7 @@ redef class Int
                # Fill digits
                var pos = digit_count(base) - 1
                while pos >= 0 and n > 0 do 
-                       s[pos] = (n % base).to_c
+                       s.chars[pos] = (n % base).to_c
                        n = n / base # /
                        pos -= 1
                end
@@ -907,7 +1058,7 @@ redef class Float
                var len = str.length
                for i in [0..len-1] do
                        var j = len-1-i
-                       var c = str[j]
+                       var c = str.chars[j]
                        if c == '0' then
                                continue
                        else if c == '.' then
@@ -943,7 +1094,7 @@ redef class Float
                end
        end
 
-       fun to_precision_native(nb: Int): String import NativeString::to_s `{
+       fun to_precision_native(nb: Int): String import NativeString.to_s `{
                int size;
                char *str;
 
@@ -960,7 +1111,7 @@ redef class Char
        redef fun to_s
        do
                var s = new Buffer.with_capacity(1)
-               s[0] = self
+               s.chars[0] = self
                return s.to_s
        end
 
index 46bda9b..22d0bc9 100644 (file)
@@ -76,12 +76,12 @@ class BM_Pattern
                var j = from
                while j < n - m + 1 do
                        var i = m - 1 # Cursor in the pattern
-                       while i >= 0 and _motif[i] == s[i + j] do i -= 1
+                       while i >= 0 and _motif.chars[i] == s.chars[i + j] do i -= 1
                        if i < 0 then
                                return j
                        else
                                var gs = _gs[i] # Good shift
-                               var bc = bc(s[i+j]) - m + 1 + i # Bad char
+                               var bc = bc(s.chars[i+j]) - m + 1 + i # Bad char
                                # Both are true, do move to the best
                                if gs > bc then
                                        j += gs
@@ -142,7 +142,7 @@ class BM_Pattern
                var m = _length
                var i = 0
                while i < m - 1 do
-                       _bc_table[x[i]] = m - i - 1
+                       _bc_table[x.chars[i]] = m - i - 1
                        i += 1
                end
        end
@@ -162,7 +162,7 @@ class BM_Pattern
                        else
                                if i < g then g = i
                                f = i
-                               while g >= 0 and x[g] == x[g + m - 1 - f] do g -= 1
+                               while g >= 0 and x.chars[g] == x.chars[g + m - 1 - f] do g -= 1
                                suff[i] = f - g
                        end
                        i -= 1
@@ -239,7 +239,7 @@ redef class Char
        do
                var stop = s.length
                while from < stop do
-                       if s[from] == self then return from
+                       if s.chars[from] == self then return from
                        from += 1
                end
                return -1
@@ -265,7 +265,7 @@ redef class String
                var stop = s.length - length + 1
                while from < stop do
                        var i = length - 1
-                       while i >= 0 and self[i] == s[i + from] do i -= 1
+                       while i >= 0 and self.chars[i] == s.chars[i + from] do i -= 1
                        # Test if we found
                        if i < 0 then return from
                        # Not found so try next one
@@ -330,10 +330,10 @@ redef class String
        fun html_escape: String
        do
                var ret = self
-               if ret.has('&') then ret = ret.replace('&', "&amp;")
-               if ret.has('<') then ret = ret.replace('<', "&lt;")
-               if ret.has('>') then ret = ret.replace('>', "&gt;")
-               if ret.has('"') then ret = ret.replace('"', "&quot;")
+               if ret.chars.has('&') then ret = ret.replace('&', "&amp;")
+               if ret.chars.has('<') then ret = ret.replace('<', "&lt;")
+               if ret.chars.has('>') then ret = ret.replace('>', "&gt;")
+               if ret.chars.has('"') then ret = ret.replace('"', "&quot;")
                return ret
        end
 end
index 97a4afd..11ba1fe 100644 (file)
@@ -36,7 +36,7 @@ extern class TimeT `{time_t`}
 
        fun update `{ time(&recv); `}
 
-       fun ctime: String import NativeString::to_s_with_copy `{
+       fun ctime: String import NativeString.to_s_with_copy `{
                return NativeString_to_s_with_copy( ctime(&recv) );
        `}
 
@@ -85,10 +85,10 @@ extern class Tm `{struct tm *`}
        fun yday: Int `{ return recv->tm_yday; `}
        fun is_dst: Bool `{ return recv->tm_isdst; `}
 
-       fun asctime: String import NativeString::to_s_with_copy `{
+       fun asctime: String import NativeString.to_s_with_copy `{
                return NativeString_to_s_with_copy( asctime(recv) );
        `}
-       fun strftime(format: String): String import String::to_cstring, NativeString::to_s `{
+       fun strftime(format: String): String import String.to_cstring, NativeString.to_s `{
                char* buf, *c_format;
                size_t res;
 
index 62f7ec7..76aaa19 100644 (file)
@@ -21,6 +21,7 @@ import literal
 import typing
 import auto_super_init
 import frontend
+import common_ffi
 
 # Add compiling options
 redef class ToolContext
@@ -106,8 +107,14 @@ redef class ModelBuilder
                        cc_paths.append(path_env.split_with(':'))
                end
 
+               var compile_dir = toolcontext.opt_compile_dir.value
+               if compile_dir == null then compile_dir = ".nit_compile"
+               self.compile_dir = compile_dir
        end
 
+       # The compilation directory
+       var compile_dir: String
+
        protected fun write_and_make(compiler: AbstractCompiler)
        do
                var mainmodule = compiler.mainmodule
@@ -118,9 +125,6 @@ redef class ModelBuilder
                var time0 = get_time
                self.toolcontext.info("*** WRITING C ***", 1)
 
-               var compile_dir = toolcontext.opt_compile_dir.value
-               if compile_dir == null then compile_dir = ".nit_compile"
-
                compile_dir.mkdir
 
                if self.toolcontext.opt_stacktrace.value then compiler.build_c_to_nit_bindings
@@ -196,6 +200,14 @@ redef class ModelBuilder
 
                self.toolcontext.info("Total C source files to compile: {cfiles.length}", 2)
 
+               # FFI
+               for m in mainmodule.in_importation.greaters do if mmodule2nmodule.keys.has(m) then
+                       var amodule = mmodule2nmodule[m]
+                       if m.uses_ffi or amodule.uses_legacy_ni then
+                               compiler.finalize_ffi_for_module(amodule)
+                       end
+               end
+
                # Generate the Makefile
 
                var makename = "{mainmodule.name}.mk"
@@ -207,11 +219,18 @@ redef class ModelBuilder
                        p = orig_dir.join_path(p).simplify_path
                        cc_includes += " -I \"" + p + "\""
                end
-               if toolcontext.opt_no_stacktrace.value then
-                       makefile.write("CC = ccache cc\nCFLAGS = -g -O2\nCINCL = {cc_includes}\nLDFLAGS ?= \nLDLIBS  ?= -lm -lgc\n\n")
-               else
-                       makefile.write("CC = ccache cc\nCFLAGS = -g -O2\nCINCL = {cc_includes}\nLDFLAGS ?= \nLDLIBS  ?= -lunwind -lm -lgc\n\n")
+
+               var linker_options = new HashSet[String]
+               for m in mainmodule.in_importation.greaters do if mmodule2nmodule.keys.has(m) then
+                       var amod = mmodule2nmodule[m]
+                       linker_options.add(amod.c_linker_options)
                end
+
+               if not toolcontext.opt_no_stacktrace.value then
+                       linker_options.add("-lunwind")
+    end
+
+               makefile.write("CC = ccache cc\nCFLAGS = -g -O2\nCINCL = {cc_includes}\nLDFLAGS ?= \nLDLIBS  ?= -lm -lgc {linker_options.join(" ")}\n\n")
                makefile.write("all: {outpath}\n\n")
 
                var ofiles = new Array[String]
@@ -228,11 +247,13 @@ redef class ModelBuilder
 
                # Compile each required extern body into a specific .o
                for f in compiler.extern_bodies do
-                       var basename = f.filename.basename(".c")
-                       var o = "{basename}.extern.o"
-                       var ff = orig_dir.join_path(f.filename).simplify_path
-                       makefile.write("{o}: {ff}\n\t$(CC) $(CFLAGS) -D NONITCNI {f.cflags} -c -o {o} {ff}\n\n")
-                       ofiles.add(o)
+                       if f isa ExternCFile then
+                               var basename = f.filename.basename(".c")
+                               var o = "{basename}.extern.o"
+                               var ff = orig_dir.join_path(f.filename).simplify_path
+                               makefile.write("{o}: {ff}\n\t$(CC) $(CFLAGS) -D NONITCNI {f.cflags} -c -o {o} {ff}\n\n")
+                               ofiles.add(o)
+                       end
                end
 
                # Link edition
@@ -331,8 +352,7 @@ abstract class AbstractCompiler
        # Binds the generated C function names to Nit function names
        fun build_c_to_nit_bindings
        do
-               var compile_dir = modelbuilder.toolcontext.opt_compile_dir.value
-               if compile_dir == null then compile_dir = ".nit_compile"
+               var compile_dir = modelbuilder.compile_dir
 
                var stream = new OFStream.open("{compile_dir}/C_fun_names")
                stream.write("%\{\n#include \"c_functions_hash.h\"\n%\}\n")
@@ -372,19 +392,23 @@ abstract class AbstractCompiler
                self.header.add_decl("#include <gc_chooser.h>")
 
                compile_header_structs
+               compile_nitni_structs
 
                # Signal handler function prototype
                self.header.add_decl("void show_backtrace(int);")
 
-               # Global variable used by the legacy native interface
+               # Global variable used by intern methods
                self.header.add_decl("extern int glob_argc;")
                self.header.add_decl("extern char **glob_argv;")
                self.header.add_decl("extern val *glob_sys;")
        end
 
-       # Declaration of structures the live Nit types
+       # Declaration of structures for live Nit types
        protected fun compile_header_structs is abstract
 
+       # Declaration of structures for nitni undelying the FFI
+       protected fun compile_nitni_structs is abstract
+
        # Generate the main C function.
        # This function:
        #       * allocate the Sys object if it exists
@@ -505,8 +529,8 @@ abstract class AbstractCompiler
                v.add("\}")
        end
 
-       # List of additional .c files required to compile (native interface)
-       var extern_bodies = new Array[ExternCFile]
+       # List of additional files required to compile (FFI)
+       var extern_bodies = new Array[ExternFile]
 
        # This is used to avoid adding an extern file more than once
        private var seen_extern = new ArraySet[String]
@@ -602,6 +626,16 @@ abstract class AbstractCompiler
                if b == 0 then return "n/a"
                return ((a*10000/b).to_f / 100.0).to_precision(2)
        end
+
+       fun finalize_ffi_for_module(nmodule: AModule)
+       do
+               var visitor = new_visitor
+               nmodule.finalize_ffi(visitor, modelbuilder)
+               nmodule.finalize_nitni(visitor)
+       end
+
+       # Does this compiler support the FFI?
+       fun supports_ffi: Bool do return false
 end
 
 # A file unit (may be more than one file if
@@ -1192,14 +1226,6 @@ 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 MType
        # Return the C type associated to a given Nit static type
        fun ctype: String do return "val*"
@@ -2500,3 +2526,14 @@ redef class MModule
        end
        private var properties_cache: Map[MClass, Set[MProperty]] = new HashMap[MClass, Set[MProperty]]
 end
+
+redef class AModule
+       # Does this module use the legacy native interface?
+       fun uses_legacy_ni: Bool is abstract
+
+       # Write FFI results to file
+       fun finalize_ffi(v: AbstractCompilerVisitor, modelbuilder: ModelBuilder) is abstract
+
+       # Write nitni results to file
+       fun finalize_nitni(v: AbstractCompilerVisitor) is abstract
+end
index 663a059..e05f4bf 100644 (file)
@@ -45,7 +45,7 @@ class CCompilationUnit
        var body_impl : Writer = new Writer
 
        # files to compile TODO check is appropriate
-       #var files = new Array[String]
+       var files = new Array[String]
 
        fun add_local_function( efc : CFunction )
        do
diff --git a/src/common_ffi/c.nit b/src/common_ffi/c.nit
new file mode 100644 (file)
index 0000000..661928c
--- /dev/null
@@ -0,0 +1,167 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012-2014 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Support for nesting C code within a Nit program using its FFI
+module c
+
+import ffi_base
+
+redef class FFILanguageAssignationPhase
+       var c_language: FFILanguage = new CLanguage(self)
+end
+
+class CLanguage
+       super FFILanguage
+
+       redef fun identify_language(n) do return n.is_c
+
+       redef fun compile_module_block(block, ecc, nmodule)
+       do
+               if block.is_c_header then
+                       ecc.header_custom.add( block.location.as_line_pragma )
+                       ecc.header_custom.add( block.code )
+               else if block.is_c_body then
+                       ecc.body_custom.add( block.location.as_line_pragma )
+                       ecc.body_impl.add( block.code )
+               end
+       end
+
+       redef fun compile_extern_method(block, m, ecc, nmodule)
+       do
+               var fc = new ExternCFunction(m, nmodule.mmodule.as(not null))
+               fc.decls.add( block.location.as_line_pragma )
+               fc.exprs.add( block.code )
+               ecc.add_exported_function( fc )
+       end
+
+       redef fun compile_extern_class(block, m, ecc, nmodule) do end
+
+       redef fun get_ftype(block, m) do return new ForeignCType(block.code)
+
+       redef fun compile_callback(callback, nmodule, mmodule, ecc)
+       do
+               callback.compile_callback_to_c(mmodule, ecc)
+       end
+end
+
+redef class AExternCodeBlock
+       fun is_c: Bool do return language_name == null or
+               language_name_lowered == "c" or language_name_lowered.has_prefix( "c " )
+
+       fun is_c_body: Bool do return language_name == null or
+               language_name_lowered == "c" or language_name_lowered ==  "c body"
+
+       fun is_c_header: Bool do return language_name_lowered == "c header"
+end
+
+redef class Location
+       fun as_line_pragma: String do return "#line {line_start} \"{file.filename}\"\n"
+end
+
+redef class AModule
+       var c_compiler_options writable = ""
+       var c_linker_options writable = ""
+end
+
+# An extern C file to compile
+class ExternCFile
+       super ExternFile
+
+       init (filename, cflags: String)
+       do
+               super filename
+
+               self.cflags = cflags
+       end
+
+       # Additionnal specific CC compiler -c flags
+       var cflags: String
+
+       redef fun hash do return filename.hash
+       redef fun ==(o) do return o isa ExternCFile and filename == o.filename
+end
+
+class ForeignCType
+       super ForeignType
+
+       redef var ctype: String
+
+       init(ctype: String)
+       do
+               self.ctype = ctype
+       end
+end
+
+redef class NitniCallback
+       fun compile_callback_to_c(nmodule: MModule, ffi_ccu: CCompilationUnit) do end
+end
+
+redef class Object
+       # Context when calling user C code from generated code
+       fun to_c_call_context: ToCCallContext do return once new ToCCallContext
+
+       # Context when calling generated code from user C code
+       fun from_c_call_context: FromCCallContext do return once new FromCCallContext
+end
+
+redef class MExplicitCall
+       redef fun compile_callback_to_c(mmodule, ffi_ccu)
+       do
+               var mproperty = mproperty.as(MMethod)
+
+               var full_cname = mproperty.build_cname(recv_mtype, mmodule, null, long_signature)
+               var friendly_cname = mproperty.build_cname(recv_mtype, mmodule, null, short_signature)
+               ffi_ccu.body_decl.add("#define {friendly_cname} {full_cname}\n")
+       end
+end
+
+# Context when calling user C code from generated code
+class ToCCallContext
+       super CallContext
+
+       private init do end
+
+       redef fun name_mtype(mtype)
+       do
+               if mtype isa MClassType and mtype.mclass.kind == extern_kind then return "void *"
+               return mtype.cname
+       end
+end
+
+# Context when calling generated code from user C code
+class FromCCallContext
+       super CallContext
+
+       private init do end
+
+       redef fun name_mtype(mtype) do return mtype.cname
+end
+
+class ExternCFunction
+       super CFunction
+
+       var method: AExternPropdef
+
+       init (method: AExternPropdef, mmodule: MModule)
+       do
+               self.method = method
+
+               var recv_mtype = method.mpropdef.mclassdef.bound_mtype
+               var csignature = method.mpropdef.mproperty.build_csignature(recv_mtype, mmodule, "___impl", long_signature, from_c_call_context)
+
+               super( csignature )
+       end
+end
diff --git a/src/common_ffi/common_ffi.nit b/src/common_ffi/common_ffi.nit
new file mode 100644 (file)
index 0000000..24cbcda
--- /dev/null
@@ -0,0 +1,144 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# FFI concers common between the compilers and the interpreter.
+# Offers services to compile modules using foreign code. Mainly allows
+# to wrap foreign code in Nit methods.
+module common_ffi
+
+import parser
+import modelbuilder
+
+import nitni
+
+import ffi_base
+import extern_classes
+import header_dependency
+import c
+
+redef class MModule
+       # Does this module uses the FFI?
+       var uses_ffi: Bool = false
+end
+
+redef class AModule
+       # C compilation unit for the FFI files
+       private var ffi_ccu: nullable CCompilationUnit = null
+
+       # Foreign language used in this AModule
+       private var present_languages = new HashSet[FFILanguage]
+
+       # Callbacks used locally
+       var ffi_callbacks = new HashMap[FFILanguage, Set[NitniCallback]]
+
+       # Ensures all of the general foreign code of the module has been analyzed.
+       # Manages header blocks, extern class types and foreign dependancies between modules
+       fun ensure_compile_ffi_wrapper
+       do
+               if ffi_ccu != null then return
+
+               # ready extern code compiler
+               var ffi_ccu = new CCompilationUnit
+               self.ffi_ccu = ffi_ccu
+
+               # generate code
+               for block in n_extern_code_blocks do
+                       var language = block.language
+                       assert language != null
+                       present_languages.add(language)
+                       language.compile_module_block(block, ffi_ccu, self)
+               end
+
+               ffi_ccu.header_c_base.add( "#include \"{mmodule.name}._nitni.h\"\n" )
+
+               # include dependancies FFI
+               for mod in mmodule.header_dependencies do
+                       if mod.uses_ffi then ffi_ccu.header_custom.add("#include \"{mod.name}._ffi.h\"\n")
+               end
+
+               for nclassdef in n_classdefs do
+                       # Does it declares an extern type?
+                       if nclassdef isa AStdClassdef and nclassdef.n_extern_code_block != null then
+                               mmodule.uses_ffi = true
+                               var language = nclassdef.n_extern_code_block.language
+                               assert language != null
+                               present_languages.add(language)
+                               nclassdef.n_extern_code_block.language.compile_extern_class(
+                                       nclassdef.n_extern_code_block.as(not null), nclassdef, ffi_ccu, self)
+                       end
+               end
+       end
+
+       # Complete the compilation of the FFI code
+       fun finalize_ffi_wrapper(compdir: String, mainmodule: MModule)
+       do
+               ensure_compile_ffi_wrapper
+
+               for language in present_languages do if ffi_callbacks.keys.has(language) then
+                       for callback in ffi_callbacks[language] do
+                               language.compile_callback(callback, self, mainmodule, ffi_ccu.as(not null))
+                       end
+
+                       language.compile_to_files(self, compdir)
+               end
+
+               ffi_ccu.write_as_impl(self, compdir)
+               for filename in ffi_ccu.files do ffi_files.add(new ExternCFile(filename, self.c_compiler_options))
+       end
+end
+
+redef class AExternPropdef
+       private var ffi_has_been_compiled = false
+
+       # Compile the necessary wrapper around this extern method or constructor
+       fun compile_ffi_method(amodule: AModule)
+       do
+               assert n_extern_code_block != null
+
+               if ffi_has_been_compiled then return
+               ffi_has_been_compiled = true
+
+               amodule.ensure_compile_ffi_wrapper
+
+               var language = n_extern_code_block.language
+               assert language != null
+               amodule.present_languages.add(language)
+               n_extern_code_block.language.compile_extern_method(
+                       n_extern_code_block.as(not null), self, amodule.ffi_ccu.as(not null), amodule)
+       end
+end
+
+redef class VerifyNitniCallbacksPhase
+       redef fun process_npropdef(npropdef)
+       do
+               super
+
+               if not npropdef isa AExternPropdef then return
+
+               var code_block = npropdef.n_extern_code_block
+               if code_block == null then return
+
+               var lang = code_block.language
+               assert lang != null
+
+               # Associate callbacks used by an extern method to its foreign language
+               for callback in npropdef.foreign_callbacks.all do
+                       var map = npropdef.parent.parent.as(AModule).ffi_callbacks
+                       if not map.keys.has(lang) then map[lang] = new HashSet[NitniCallback]
+                       map[lang].add(callback)
+               end
+       end
+end
diff --git a/src/common_ffi/extern_classes.nit b/src/common_ffi/extern_classes.nit
new file mode 100644 (file)
index 0000000..0ab7b96
--- /dev/null
@@ -0,0 +1,134 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Manages all extern classes and their associated foreign type.
+module extern_classes
+
+import ffi_base
+
+redef class ToolContext
+       var extern_classes_typing_phase_ast: Phase = new ExternClassesTypingPhaseAst(self, [ffi_language_assignation_phase])
+
+       var extern_classes_typing_phase_model: Phase = new ExternClassesTypingPhaseModel(self, [extern_classes_typing_phase_ast, modelize_class_phase])
+end
+
+# Assigns the `ftype` to class definitions, work on the AST only
+private class ExternClassesTypingPhaseAst
+       super Phase
+
+       redef fun process_nclassdef(nclassdef)
+       do
+               if not nclassdef isa AStdClassdef then return
+
+               var code_block = nclassdef.n_extern_code_block
+               if code_block == null then return
+
+               if nclassdef.n_kwredef != null then
+                       # A redef cannot specifiy a different extern type
+                       toolcontext.error(nclassdef.location, "Only the introduction of a class can specify an extern type.")
+                       return
+               end
+
+               var ftype = code_block.language.get_ftype(code_block, nclassdef)
+               nclassdef.ftype_cache = ftype
+               nclassdef.ftype_computed = true
+       end
+end
+
+redef class AClassdef
+       private var ftype_cache: nullable ForeignType = null
+       private var ftype_computed = false
+
+       # Associated extern type when defined on this classdef
+       fun ftype: nullable ForeignType
+       do
+               return ftype_cache
+       end
+end
+
+private class ExternClassesTypingPhaseModel
+       super Phase
+
+       redef fun process_nclassdef(nclassdef)
+       do
+               if not nclassdef isa AStdClassdef then return
+
+               var mclassdef = nclassdef.mclassdef
+               var mclass = nclassdef.mclass
+
+               # We only need to do this once per class
+               if mclass.intro != mclassdef then return
+
+               if mclass.kind != extern_kind then return
+
+               mclass.compute_ftype(self)
+       end
+end
+
+redef class MClass
+       private var ftype_cache: nullable ForeignType = null
+       private var ftype_computed = false
+
+       # Extern type associated to this class according to specialisation
+       fun ftype: nullable ForeignType do return ftype_cache
+
+       redef fun ctype do return ftype_cache.ctype
+
+       # Type in C of the extern class
+       # If not defined in the intro of this class will look in super-classes
+       # FIXME this only supports type definition at intro, extend to superclasses by redef
+       private fun compute_ftype(v: ExternClassesTypingPhaseModel): nullable ForeignType
+       do
+               if ftype_computed then return ftype_cache
+               if kind != extern_kind then return null
+
+               # base case
+               if name == "Pointer" then
+                       ftype_cache = new ForeignType
+                       ftype_computed = true
+                       return ftype_cache
+               end
+
+               var intro_nclassdef = v.toolcontext.modelbuilder.mclassdef2nclassdef[intro]
+               var ftype = intro_nclassdef.ftype
+               if ftype == null then
+                       var ftype_b: nullable ForeignType = null # FIXME hack to circumvent bug where ftype is typed null
+
+                       # look in super classes
+                       for s in in_hierarchy(intro.mmodule).direct_greaters do
+                               var super_ftype = s.compute_ftype(v)
+                               if super_ftype != null then
+                                       if ftype_b == null then
+                                               ftype_b = super_ftype
+                                               continue
+                                       else
+                                               # detect conflict
+                                               if super_ftype != ftype_b then
+                                                       v.toolcontext.error(null, "Extern type conflict in {self}")
+                                                       return null
+                                               end
+                                       end
+                               end
+                       end
+
+                       ftype = ftype_b
+               end
+
+               ftype_cache = ftype
+               ftype_computed = true
+               return ftype
+       end
+end
diff --git a/src/common_ffi/ffi_base.nit b/src/common_ffi/ffi_base.nit
new file mode 100644 (file)
index 0000000..86f53ea
--- /dev/null
@@ -0,0 +1,209 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Tools and utilities for language targetted FFI implementations
+module ffi_base
+
+import c_tools
+import parser
+import modelbuilder
+import nitni
+
+redef class ToolContext
+       var ffi_language_assignation_phase: Phase = new FFILanguageAssignationPhase(self, null)
+end
+
+class FFILanguageAssignationPhase
+       super Phase
+
+       # All supported languages
+       var languages = new Array[FFILanguage]
+
+       redef fun process_nmodule(nmodule)
+       do
+               for block in nmodule.n_extern_code_blocks do
+                       verify_foreign_code_on_node( block )
+               end
+       end
+
+       redef fun process_npropdef(npropdef)
+       do
+               if npropdef isa AExternPropdef then
+                       var code_block = npropdef.n_extern_code_block
+                       if code_block != null then
+                               verify_foreign_code_on_node( code_block )
+                       end
+               end
+       end
+
+       redef fun process_nclassdef(nclassdef)
+       do
+               if nclassdef isa AStdClassdef and nclassdef.n_extern_code_block != null then
+                       verify_foreign_code_on_node( nclassdef.n_extern_code_block.as(not null) )
+               end
+       end
+
+       private fun verify_foreign_code_on_node(n: AExternCodeBlock)
+       do
+               var found = false
+               for v in languages do
+                       var identified = v.identify_language(n)
+                       if identified then
+                               if found and identified then
+                                       toolcontext.error(n.location, "Two languages identified as possible handlers.")
+                               end
+                               n.language = v
+                               found = true
+                       end
+               end
+
+               if not found then toolcontext.error(n.location, "Unsupported language.")
+       end
+end
+
+redef class AModule
+       var ffi_files = new Array[ExternFile]
+end
+
+redef class AExternCodeBlock
+       fun language_name: nullable String do
+               if n_in_language == null then return null
+               return n_in_language.n_string.without_quotes
+       end
+       fun language_name_lowered: nullable String do
+               if language_name == null then return null
+               return language_name.to_lower
+       end
+
+       fun code: String do return n_extern_code_segment.without_guard
+
+       var language: nullable FFILanguage = null
+end
+
+# Visitor for a specific languages. Works kinda like a `Phase` and is executed
+# by a `Phase`.
+class FFILanguage
+       init(ffi_language_assignation_phase: FFILanguageAssignationPhase)
+       do
+               ffi_language_assignation_phase.languages.add(self)
+       end
+
+       # Is this `block` written in this language?
+       fun identify_language(block: AExternCodeBlock ): Bool is abstract
+
+       # Generate wrapper code for this module/header code block
+       fun compile_module_block(block: AExternCodeBlock, ecc: CCompilationUnit, nmodule: AModule) is abstract
+
+       # Generate wrapper code for this extern method
+       fun compile_extern_method(block: AExternCodeBlock, m: AExternPropdef,
+               ecc: CCompilationUnit, nmodule: AModule) is abstract
+
+       # Generate wrapper code for this extern class
+       fun compile_extern_class(block: AExternCodeBlock, m: AClassdef,
+               ecc: CCompilationUnit, nmodule: AModule) is abstract
+
+       # Get the foreign type of this extern class definition
+       fun get_ftype(block: AExternCodeBlock, m: AClassdef): ForeignType is abstract
+
+       # Generate the code to offer this callback if foreign code
+       fun compile_callback(callback: NitniCallback, nmodule: AModule,
+               mainmmodule: MModule, ecc: CCompilationUnit) is abstract
+
+       # Complete compilation of generated code
+       fun compile_to_files(amodule: AModule, directory: String) do end
+end
+
+redef class TString
+       # Returns the content of this node without both of the surrounding "
+       fun without_quotes: String
+       do
+               assert text.length >= 2
+               return text.substring(1, text.length-2)
+       end
+end
+
+redef class TExternCodeSegment
+       # Returns the content of this node without the surrounding `{ and `}
+       fun without_guard: String
+       do
+               assert text.length >= 4
+               return text.substring(2, text.length-4)
+       end
+end
+
+# An extern file to compile
+class ExternFile
+       # The filename of the file
+       var filename: String
+
+       fun makefile_rule_name: String is abstract
+       fun makefile_rule_content: String is abstract
+end
+
+redef class CCompilationUnit
+       fun write_as_impl( amodule: AModule, compdir: String )
+       do
+               var base_name = "{amodule.mmodule.name}._ffi"
+
+               var h_file = "{base_name}.h"
+               var guard = "{amodule.cname.to_s.to_upper}_NIT_H"
+               write_header_to_file( amodule, "{compdir}/{h_file}", new Array[String], guard)
+
+               var c_file = "{base_name}.c"
+               write_body_to_file( amodule, "{compdir}/{c_file}", ["<stdlib.h>", "<stdio.h>", "\"{h_file}\""] )
+
+               files.add( "{compdir}/{c_file}" )
+       end
+
+       fun write_header_to_file(amodule: AModule, file: String, includes: Array[String], guard: String)
+       do
+               var stream = new OFStream.open( file )
+
+               # header comments
+               var module_info = "/*\n\tExtern implementation of Nit module {amodule.mmodule.name}\n*/\n"
+
+               stream.write( module_info )
+
+               stream.write( "#ifndef {guard}\n" )
+               stream.write( "#define {guard}\n\n" )
+
+               for incl in includes do stream.write( "#include {incl}\n" )
+
+               compile_header_core( stream )
+
+               # header file guard close
+               stream.write( "#endif\n" )
+               stream.close
+       end
+
+       fun write_body_to_file(amodule: AModule, file: String, includes: Array[String])
+       do
+               var stream = new OFStream.open(file)
+
+               var module_info = "/*\n\tExtern implementation of Nit module {amodule.mmodule.name}\n*/\n"
+
+               stream.write( module_info )
+               for incl in includes do stream.write( "#include {incl}\n" )
+
+               compile_body_core( stream )
+
+               stream.close
+       end
+end
+
+class ForeignType
+       fun ctype: String do return "void*"
+end
diff --git a/src/common_ffi/header_dependency.nit b/src/common_ffi/header_dependency.nit
new file mode 100644 (file)
index 0000000..de247e5
--- /dev/null
@@ -0,0 +1,77 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Tracks which modules has public header code that must be imported
+# by user modules.
+module header_dependency
+
+import ffi_base
+import c
+
+redef class ToolContext
+       var header_dependancy_phase: Phase = new HeaderDependancyPhase(self, [ffi_language_assignation_phase, modelize_class_phase])
+end
+
+redef class AModule
+       private fun has_public_c_header: Bool do
+               for code_block in n_extern_code_blocks do if code_block.is_c_header then return true
+               return false
+       end
+end
+
+redef class MModule
+       private var header_dependencies_cache: nullable Array[MModule] = null
+       fun header_dependencies: Array[MModule]
+       do
+               var cache = header_dependencies_cache
+               assert cache != null
+               return cache
+       end
+
+       private fun compute_header_dependencies(v: HeaderDependancyPhase)
+       do
+               if header_dependencies_cache != null then return
+
+               var header_dependencies = new Array[MModule]
+
+               # gather from importation
+               for m in in_importation.direct_greaters do
+                       m.compute_header_dependencies(v)
+
+                       # does the super module has inherited dependancies?
+                       var hd = m.header_dependencies
+                       if not hd.is_empty then 
+                               header_dependencies.add_all(hd)
+                       end
+
+                       # does the super module itself has extern dependancies?
+                       var amodule = v.toolcontext.modelbuilder.mmodule2nmodule[m]
+                       if amodule.has_public_c_header then header_dependencies.add(m)
+               end
+
+               header_dependencies_cache = header_dependencies
+       end
+end
+
+private class HeaderDependancyPhase
+       super Phase
+
+       redef fun process_nmodule(nmodule)
+       do
+               var mmodule = nmodule.mmodule
+               mmodule.compute_header_dependencies(self)
+       end
+end
diff --git a/src/compiler_ffi.nit b/src/compiler_ffi.nit
new file mode 100644 (file)
index 0000000..36c1453
--- /dev/null
@@ -0,0 +1,534 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# FFI support for the compilers
+module compiler_ffi
+
+intrude import abstract_compiler
+intrude import common_ffi
+import nitni
+
+redef class AModule
+       private var foreign_callbacks = new ForeignCallbackSet
+       var nitni_ccu: nullable CCompilationUnit = null
+
+       redef var uses_legacy_ni: Bool = false
+
+       redef fun finalize_ffi(v: AbstractCompilerVisitor, modelbuilder: ModelBuilder)
+       do
+               finalize_ffi_wrapper(v.compiler.modelbuilder.compile_dir, v.compiler.mainmodule)
+               for file in ffi_files do v.compiler.extern_bodies.add(file)
+       end
+
+       fun ensure_compile_nitni_base(v: AbstractCompilerVisitor)
+       do
+               if nitni_ccu != null then return
+
+               nitni_ccu = new CCompilationUnit
+       end
+
+       redef fun finalize_nitni(v: AbstractCompilerVisitor)
+       do
+               ensure_compile_nitni_base(v)
+
+               nitni_ccu.header_c_types.add("#include \"{mmodule.name}._ffi.h\"\n")
+
+               nitni_ccu.write_as_nitni(self, v.compiler.modelbuilder.compile_dir)
+
+               for file in nitni_ccu.files do
+                       v.compiler.extern_bodies.add(new ExternCFile(file, c_compiler_options))
+               end
+       end
+
+       var compiled_callbacks: Array[NitniCallback] = new Array[NitniCallback]
+
+       # Returns true if callbacks has yet to be generated and register it as being generated
+       fun check_callback_compilation(cb: NitniCallback): Bool
+       do
+               var compiled = compiled_callbacks.has(cb)
+               if not compiled then compiled_callbacks.add(cb)
+               return not compiled
+       end
+end
+
+redef class AExternPropdef
+       fun compile_ffi_support_to_c(v: AbstractCompilerVisitor)
+       do
+               var mmodule = mpropdef.mclassdef.mmodule
+               var amainmodule = v.compiler.modelbuilder.mmodule2nmodule[v.compiler.mainmodule]
+               var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule]
+               var mclass_type = mpropdef.mclassdef.bound_mtype
+
+               # Declare as extern
+               var csignature = mpropdef.mproperty.build_csignature(mclass_type, mmodule, "___impl", long_signature, internal_call_context)
+               v.declare_once("{csignature};")
+
+               # FFI part
+               compile_ffi_method(amodule)
+
+               # nitni - Compile missing callbacks
+               amodule.ensure_compile_nitni_base(v)
+               var ccu = amodule.nitni_ccu.as(not null)
+
+               for mtype in foreign_callbacks.types do
+                       if not mtype.is_cprimitive then
+                               mtype.compile_extern_type(v, ccu)
+
+                               # has callbacks already been compiled? (this may very well happen with global compilation)
+                               if amodule.check_callback_compilation(mtype) then mtype.compile_extern_helper_functions(v, ccu)
+                       end
+               end
+
+               # compile callbacks
+               for cb in foreign_callbacks.callbacks do if amainmodule.check_callback_compilation(cb) then
+                       cb.compile_extern_callback(v, ccu)
+               end
+
+               for cb in foreign_callbacks.supers do if amainmodule.check_callback_compilation(cb) then
+                       cb.compile_extern_callback(v, ccu)
+               end
+
+               for cb in foreign_callbacks.casts do if amainmodule.check_callback_compilation(cb) then
+                       cb.compile_extern_callbacks(v, ccu)
+               end
+
+               # manage nitni callback set
+               amodule.foreign_callbacks.join(foreign_callbacks)
+       end
+end
+
+redef class AExternMethPropdef
+       redef fun compile_to_c(v, mpropdef, arguments)
+       do
+               var mmodule = mpropdef.mclassdef.mmodule
+               var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule]
+
+               # if using the old native interface fallback on previous implementation
+               var nextern = self.n_extern
+               if nextern != null then
+                       amodule.uses_legacy_ni = true
+                       super
+                       return
+               end
+
+               if not v.compiler.supports_ffi then
+                       super
+                       return
+               end
+
+               amodule.mmodule.uses_ffi = true
+
+               var mclass_type = mpropdef.mclassdef.bound_mtype
+
+               # Outgoing code in compiler
+               var externname = mpropdef.mproperty.build_cname(mpropdef.mclassdef.bound_mtype, mmodule, "___impl", long_signature)
+               var recv_var: nullable RuntimeVariable = null
+               var return_mtype = mpropdef.msignature.return_mtype
+               if return_mtype != null then
+                       return_mtype = return_mtype.anchor_to(mmodule, mclass_type)
+                       recv_var = v.new_var(return_mtype)
+               end
+
+               v.adapt_signature(mpropdef, arguments)
+
+               var arguments_for_c = new Array[String]
+               for a in [0..arguments.length[ do
+                       var arg = arguments[a]
+                       var param_mtype: MType
+                       if a == 0 then
+                               param_mtype = mpropdef.mclassdef.mclass.mclass_type
+                       else param_mtype = mpropdef.msignature.mparameters[a-1].mtype
+
+                       param_mtype = param_mtype.anchor_to(mmodule, mclass_type)
+
+                       if param_mtype.is_cprimitive then
+                               arguments_for_c.add(arg.name)
+                       else
+                               v.add("struct nitni_instance* var_for_c_{a};")
+                               v.add("var_for_c_{a} = malloc(sizeof(struct nitni_instance));")
+                               v.add("var_for_c_{a}->value = {arg.name};")
+                               arguments_for_c.add("var_for_c_{a}")
+                       end
+               end
+
+               if recv_var == null then
+                       v.add("{externname}({arguments_for_c.join(", ")});")
+               else
+                       assert return_mtype != null
+                       if return_mtype.is_cprimitive then
+                               v.add("{recv_var} = {externname}({arguments_for_c.join(", ")});")
+                       else
+                               v.add("struct nitni_instance* ret_var;")
+                               v.add("ret_var = {externname}({arguments_for_c.join(", ")});")
+                               v.add("{recv_var} = ret_var->value;")
+                       end
+                       v.ret(recv_var)
+               end
+
+               compile_ffi_support_to_c(v)
+       end
+end
+
+redef class AExternInitPropdef
+       redef fun compile_to_c(v, mpropdef, arguments)
+       do
+               var mmodule = mpropdef.mclassdef.mmodule
+               var amodule = v.compiler.modelbuilder.mmodule2nmodule[mmodule]
+
+               # if using the old native interface fallback on previous implementation
+               var nextern = self.n_extern
+               if nextern != null then
+                       amodule.uses_legacy_ni = true
+                       super
+                       return
+               end
+
+               if not v.compiler.supports_ffi then
+                       super
+                       return
+               end
+
+               amodule.mmodule.uses_ffi = true
+
+               var mclass_type = mpropdef.mclassdef.bound_mtype
+
+               var externname = mpropdef.mproperty.build_cname(mpropdef.mclassdef.bound_mtype, mmodule, "___impl", long_signature)
+               var return_mtype = arguments.first.mtype
+               var recv_var = v.new_var(return_mtype)
+
+               v.adapt_signature(mpropdef, arguments)
+
+               arguments.shift
+
+               var arguments_for_c = new Array[String]
+               for a in [0..arguments.length[ do
+                       var arg = arguments[a]
+                       var param_mtype: MType
+                       param_mtype = mpropdef.msignature.mparameters[a].mtype
+                       param_mtype = param_mtype.anchor_to(mmodule, mclass_type)
+
+                       if param_mtype.is_cprimitive then
+                               arguments_for_c.add(arg.name)
+                       else
+                               v.add("struct nitni_instance* var_for_c_{a};")
+                               v.add("var_for_c_{a} = malloc(sizeof(struct nitni_instance));")
+                               v.add("var_for_c_{a}->value = {arg.name};")
+                               arguments_for_c.add("var_for_c_{a}")
+                       end
+               end
+
+               if return_mtype.is_cprimitive then
+                       v.add("{recv_var} = {externname}({arguments_for_c.join(", ")});")
+               else
+                       v.add("struct nitni_instance* ret_var;")
+                       v.add("ret_var = {externname}({arguments_for_c.join(", ")});")
+                       v.add("{recv_var} = ret_var->value;")
+               end
+               v.ret(recv_var)
+
+               compile_ffi_support_to_c(v)
+       end
+end
+
+redef class CCompilationUnit
+       fun write_as_nitni(amodule: AModule, compdir: String)
+       do
+               var base_name = "{amodule.mmodule.name}._nitni"
+
+               var h_file = "{base_name}.h"
+               write_header_to_file( amodule, "{compdir}/{h_file}", new Array[String],
+                       "{amodule.cname.to_s.to_upper}_NITG_NITNI_H")
+
+               var c_file = "{base_name}.c"
+               write_body_to_file( amodule, "{compdir}/{c_file}", ["\"{h_file}\""] )
+
+               files.add( "{compdir}/{c_file}" )
+       end
+end
+
+redef class AbstractCompilerVisitor
+       # Create a `RuntimeVariable` for this C variable originating from C user code
+       private fun var_from_c(name: String, mtype: MType): RuntimeVariable
+       do
+               if mtype.is_cprimitive then
+                       return new RuntimeVariable(name, mtype, mtype)
+               else
+                       return new RuntimeVariable("{name}->value", mtype, mtype)
+               end
+       end
+
+       # Return a `RuntimeVarible` to C user code
+       private fun ret_to_c(src: RuntimeVariable, mtype: MType)
+       do
+               if mtype.is_cprimitive then
+                       add("return {src};")
+               else
+                       add("struct nitni_instance* ret_for_c;")
+                       add("ret_for_c = malloc(sizeof(struct nitni_instance));")
+                       add("ret_for_c->value = {src};")
+                       add("return ret_for_c;")
+               end
+       end
+end
+
+redef class MType
+       fun compile_extern_type(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       do
+               assert not is_cprimitive
+
+               # define friendly type
+               ccu.header_c_types.add("#ifndef NIT_TYPE_{cname}\n")
+               ccu.header_c_types.add("#define NIT_TYPE_{cname} 1\n")
+               ccu.header_c_types.add("typedef struct nitni_instance *{cname};\n")
+               ccu.header_c_types.add("#endif\n")
+       end
+
+       fun compile_extern_helper_functions(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       do
+               # actually, we do not need to do anything when using the bohem garbage collector
+
+               # incr_ref
+               var nitni_visitor = v.compiler.new_visitor
+               ccu.header_decl.add("#define {mangled_cname}_incr_ref(from) while(0)\{\}\n")
+
+               # incr_ref
+               nitni_visitor = v.compiler.new_visitor
+               ccu.header_decl.add("#define {mangled_cname}_decr_ref(from) while(0)\{\}\n")
+       end
+end
+
+redef class MNullableType
+       redef fun compile_extern_helper_functions(v, ccu)
+       do
+               super
+
+               # In nitni files, declare internal function as extern 
+               var full_friendly_csignature = "{cname} {v.compiler.mainmodule.name}___null_{mtype.mangled_cname}()"
+               ccu.header_decl.add("extern {full_friendly_csignature};\n")
+
+               # In nitni files, #define friendly as extern
+               var base_cname = "null_{mtype.mangled_cname}"
+               ccu.header_decl.add("#define {base_cname} {v.compiler.mainmodule.name}___{base_cname}\n")
+
+               # Internally, implement internal function
+               var nitni_visitor = v.compiler.new_visitor
+               nitni_visitor.frame = v.frame
+               var full_internal_csignature = "{cname_blind} {v.compiler.mainmodule.name}___null_{mtype.mangled_cname}()"
+               nitni_visitor.add("#ifndef NIT_NULL_null_{mtype.mangled_cname}")
+               nitni_visitor.add("#define NIT_NULL_null_{mtype.mangled_cname}")
+               nitni_visitor.add("{full_internal_csignature} \{")
+               nitni_visitor.add("struct nitni_instance* ret_for_c;")
+               nitni_visitor.add("ret_for_c = malloc(sizeof(struct nitni_instance));")
+               nitni_visitor.add("ret_for_c->value = NULL;")
+               nitni_visitor.add("return ret_for_c;")
+               nitni_visitor.add("\}")
+               nitni_visitor.add("#endif")
+       end
+end
+
+redef class MExplicitCall
+       fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       do
+               var mproperty = mproperty
+               assert mproperty isa MMethod
+
+               # In nitni files, declare internal function as extern 
+               var full_friendly_csignature = mproperty.build_csignature(recv_mtype, v.compiler.mainmodule, null, long_signature, internal_call_context)
+               ccu.header_decl.add("extern {full_friendly_csignature};\n")
+
+               # Internally, implement internal function
+               var nitni_visitor = v.compiler.new_visitor
+               nitni_visitor.frame = v.frame
+               var msignature = mproperty.intro.msignature
+               var csignature_blind = mproperty.build_csignature(recv_mtype, v.compiler.mainmodule, null, long_signature, internal_call_context)
+
+               nitni_visitor.add_decl("/* nitni callback for {mproperty.full_name} */")
+               nitni_visitor.add_decl("{csignature_blind} \{")
+
+               var vars = new Array[RuntimeVariable]
+               var mtype: MType = recv_mtype
+               var recv_var = null
+               if mproperty.is_init then
+                       if recv_mtype.mclass.kind == extern_kind then
+                               recv_var = nitni_visitor.new_var(mtype)
+                       else
+                               var recv_mtype = recv_mtype
+                               recv_var = nitni_visitor.init_instance(recv_mtype)
+                               nitni_visitor.add("{mtype.ctype} recv /* var self: {mtype} */;")
+                               nitni_visitor.add("recv = {recv_var};")
+                       end
+               else
+                       mtype = mtype.anchor_to(v.compiler.mainmodule, recv_mtype)
+                       recv_var = nitni_visitor.var_from_c("recv", mtype)
+               end
+
+               vars.add(recv_var)
+
+               for p in msignature.mparameters do
+                       var arg_mtype = p.mtype.anchor_to(v.compiler.mainmodule, recv_mtype)
+                       var arg = nitni_visitor.var_from_c(p.name, arg_mtype)
+                       vars.add(arg)
+               end
+
+               var ret_var = nitni_visitor.send(mproperty, vars)
+
+               var return_mtype = msignature.return_mtype
+               if mproperty.is_init then
+                       if recv_mtype.mclass.kind != extern_kind then ret_var = recv_var
+                       return_mtype = recv_mtype
+               end
+               if return_mtype != null then
+                       assert ret_var != null
+                       return_mtype = return_mtype.anchor_to(v.compiler.mainmodule, recv_mtype)
+                       nitni_visitor.ret_to_c(ret_var, return_mtype)
+               end
+               nitni_visitor.add("\}")
+       end
+end
+
+redef class MExplicitSuper
+       fun compile_extern_callback(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       do
+               var mproperty = from.mproperty
+               assert mproperty isa MMethod
+               var mclass_type = from.mclassdef.mclass.mclass_type
+               var mmodule = from.mclassdef.mmodule
+
+               # In nitni files, declare internal function as extern
+               var internal_csignature = mproperty.build_csignature(mclass_type, v.compiler.mainmodule, null, long_signature, from_c_call_context)
+               ccu.header_decl.add("extern {internal_csignature};\n")
+
+               # In nitni files, #define friendly as extern
+               var friendly_cname = mproperty.build_cname(mclass_type, v.compiler.mainmodule, "___super", short_signature)
+               var internal_cname = mproperty.build_cname(mclass_type, v.compiler.mainmodule, "___super", long_signature)
+               ccu.header_decl.add("#define {friendly_cname} {internal_cname}\n")
+
+               # Internally, implement internal function
+               var nitni_visitor = v.compiler.new_visitor
+               nitni_visitor.frame = v.frame
+               var msignature = mproperty.intro.msignature
+
+               var csignature_blind = mproperty.build_csignature(mclass_type, v.compiler.mainmodule, "___super", long_signature, internal_call_context)
+
+               nitni_visitor.add_decl("/* nitni callback to super for {mproperty.full_name} */")
+               nitni_visitor.add_decl("{csignature_blind} \{")
+
+               var vars = new Array[RuntimeVariable]
+
+               var recv_var = nitni_visitor.var_from_c("recv", mclass_type)
+               vars.add(recv_var)
+
+               for p in msignature.mparameters do
+                       var arg_mtype = v.anchor(p.mtype)
+                       var arg = nitni_visitor.var_from_c(p.name, arg_mtype)
+                       vars.add(arg)
+               end
+
+               var ret_var = nitni_visitor.supercall(from.as(MMethodDef), mclass_type, vars)
+
+               var return_mtype = msignature.return_mtype
+               if return_mtype != null then
+                       assert ret_var != null
+                       return_mtype = v.anchor(return_mtype)
+                       nitni_visitor.ret_to_c(ret_var, return_mtype)
+               end
+               nitni_visitor.add("\}")
+       end
+end
+
+redef class MExplicitCast
+       fun compile_extern_callbacks(v: AbstractCompilerVisitor, ccu: CCompilationUnit)
+       do
+               var from = from
+               var to = to
+
+               #
+               ## check type
+               #
+
+               # In nitni files, declare internal function as extern 
+               var full_friendly_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind})"
+               ccu.header_decl.add("extern {full_friendly_csignature};\n")
+
+               # In nitni files, #define friendly as extern
+               ccu.header_decl.add("#define {check_cname} {v.compiler.mainmodule.name}___{check_cname}\n")
+
+               # Internally, implement internal function
+               var nitni_visitor = v.compiler.new_visitor
+               nitni_visitor.frame = v.frame
+
+               var full_internal_csignature = "int {v.compiler.mainmodule.name }___{from.mangled_cname}_is_a_{to.mangled_cname}({from.cname_blind} from)"
+               nitni_visitor.add_decl("/* nitni check for {from} to {to} */")
+               nitni_visitor.add_decl("{full_internal_csignature} \{")
+
+               var from_var = new RuntimeVariable("from->value", from, from)
+               var recv_var = nitni_visitor.type_test(from_var, to, "FFI isa")
+               nitni_visitor.add("return {recv_var};")
+
+               nitni_visitor.add("\}")
+
+               # special checks
+               if from == to.as_nullable then
+                       # format A_is_null
+                       ccu.header_decl.add("#define {from.mangled_cname}_is_null {from.mangled_cname}_is_a_{to.mangled_cname}\n")
+               end
+
+               #
+               ## cast
+               #
+
+               # In nitni files, declare internal function as extern
+               full_friendly_csignature = "{to.cname} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind})"
+               ccu.header_decl.add("extern {full_friendly_csignature};\n")
+
+               # In nitni files, #define friendly as extern
+               ccu.header_decl.add("#define {cast_cname} {v.compiler.mainmodule.name}___{cast_cname}\n")
+
+               # Internally, implement internal function
+               nitni_visitor = v.compiler.new_visitor
+               nitni_visitor.frame = v.frame
+
+               full_internal_csignature = "{to.cname_blind} {v.compiler.mainmodule.name }___{from.mangled_cname}_as_{to.mangled_cname}({from.cname_blind} from)"
+               nitni_visitor.add_decl("/* nitni cast for {from} to {to} */")
+               nitni_visitor.add_decl("{full_internal_csignature} \{")
+
+               from_var = nitni_visitor.var_from_c("from", from)
+
+               ## test type
+               var check = nitni_visitor.type_test(from_var, to, "FFI cast")
+               nitni_visitor.add("if (!{check}) \{")
+               nitni_visitor.add_abort("FFI cast failed")
+               nitni_visitor.add("\}")
+
+               ## internal cast
+               recv_var = nitni_visitor.autobox(from_var, to)
+
+               nitni_visitor.ret_to_c(recv_var, to)
+
+               nitni_visitor.add("\}")
+
+               # special casts
+               if from.as_nullable == to then
+                       # format A_as_nullable
+                       ccu.header_decl.add("#define {from.mangled_cname}_as_nullable {from.mangled_cname}_as_{to.mangled_cname}\n")
+               end
+
+               if from == to.as_nullable then
+                       # format A_as_nullable
+                       ccu.header_decl.add("#define {to.mangled_cname}_as_not_nullable {from.mangled_cname}_as_{to.mangled_cname}\n")
+               end
+       end
+end
index be9c26b..12d8b37 100644 (file)
@@ -596,7 +596,7 @@ class Debugger
                        print "\nEnd of current instruction \n"
                else if parts_of_command[1] == "stack" then
                        print self.stack_trace
-               else if parts_of_command[1].has('[') and parts_of_command[1].has(']') then
+               else if parts_of_command[1].chars.has('[') and parts_of_command[1].chars.has(']') then
                        process_array_command(parts_of_command)
                else
                        var instance = seek_variable(get_real_variable_name(parts_of_command[1]), frame)
@@ -832,7 +832,7 @@ class Debugger
                var trigger_string_escape = false
                var trigger_concat_in_string = false
 
-               for i in instruction do
+               for i in instruction.chars do
                        if trigger_char_escape then
                                if i == '\'' then trigger_char_escape = false
                        else if trigger_string_escape then
@@ -844,7 +844,7 @@ class Debugger
                                if i.is_alphanumeric or i == '_' then
                                        instruction_buffer.add(i)
                                else if i == '.' then
-                                       if instruction_buffer.is_numeric or (instruction_buffer[0] >= 'A' and instruction_buffer[0] <= 'Z') then
+                                       if instruction_buffer.is_numeric or (instruction_buffer.chars[0] >= 'A' and instruction_buffer.chars[0] <= 'Z') then
                                                instruction_buffer.clear
                                        else
                                                result_array.push(instruction_buffer.to_s)
@@ -858,13 +858,13 @@ class Debugger
                                        trigger_concat_in_string = false
                                        trigger_string_escape = true
                                else
-                                       if instruction_buffer.length > 0 and not instruction_buffer.is_numeric and not (instruction_buffer[0] >= 'A' and instruction_buffer[0] <= 'Z') then result_array.push(instruction_buffer.to_s)
+                                       if instruction_buffer.length > 0 and not instruction_buffer.is_numeric and not (instruction_buffer.chars[0] >= 'A' and instruction_buffer.chars[0] <= 'Z') then result_array.push(instruction_buffer.to_s)
                                        instruction_buffer.clear
                                end
                        end
                end
 
-               if instruction_buffer.length > 0 and not instruction_buffer.is_numeric and not (instruction_buffer[0] >= 'A' and instruction_buffer[0] <= 'Z') then result_array.push(instruction_buffer.to_s)
+               if instruction_buffer.length > 0 and not instruction_buffer.is_numeric and not (instruction_buffer.chars[0] >= 'A' and instruction_buffer.chars[0] <= 'Z') then result_array.push(instruction_buffer.to_s)
 
                return result_array
        end
@@ -876,7 +876,7 @@ class Debugger
                var buf = new Buffer
                var trigger_copy = false
 
-               for i in function do
+               for i in function.chars do
                        if i == ')' then break
                        if trigger_copy then buf.add(i)
                        if i == '(' then trigger_copy = true
@@ -1166,7 +1166,7 @@ class Debugger
 
                var last_was_opening_bracket = false
 
-               for i in braces do
+               for i in braces.chars do
                        if i == '[' then
                                if last_was_opening_bracket then
                                        return null
@@ -1344,7 +1344,7 @@ class Debugger
        fun get_char(value: String): nullable Instance
        do
                if value.length >= 1 then
-                       return char_instance(value[0])
+                       return char_instance(value.chars[0])
                else
                        return null
                end
diff --git a/src/full_boostrap b/src/full_boostrap
new file mode 100755 (executable)
index 0000000..aa6046b
--- /dev/null
@@ -0,0 +1,20 @@
+set -e
+set -x
+
+# Check c_src is up-to-date
+make -C ../c_src
+
+# Compile nitg
+time ../c_src/nitg nitg.nit
+
+# delete old c_src
+rm -rf ../c_src
+
+# Regenerate c_src
+./mkcsrc
+
+# Compile new c_src
+time make -C ../c_src
+
+# Remake all
+make
index 004c8a3..9b05fe5 100644 (file)
@@ -25,6 +25,7 @@ module global_compiler
 
 import abstract_compiler
 import rapid_type_analysis
+import compiler_ffi
 
 redef class ModelBuilder
        # Entry point to performs a global compilation on the AST of a complete program.
@@ -236,12 +237,18 @@ class GlobalCompiler
                v.add("res->value = value;")
                v.add("return (val*)res;")
                v.add("\}")
-
        end
 
        redef fun new_visitor do return new GlobalCompilerVisitor(self)
 
        private var collect_types_cache: HashMap[MType, Array[MClassType]] = new HashMap[MType, Array[MClassType]]
+
+       redef fun compile_nitni_structs
+       do
+               self.header.add_decl("struct nitni_instance \{ val *value; \};")
+       end
+
+       redef fun supports_ffi do return true
 end
 
 # A visitor on the AST of property definition that generate the C code.
@@ -269,6 +276,8 @@ class GlobalCompilerVisitor
                        end
                        self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
                        return res
+               else if value.mtype.cname_blind == "void*" and mtype.cname_blind == "void*" then
+                       return value
                else
                        # Bad things will appen!
                        var res = self.new_var(mtype)
index 668f72a..9daefcb 100644 (file)
@@ -90,7 +90,7 @@ redef class ACharExpr
                        v.toolcontext.error(self.hot_location, "Invalid character literal {txt}")
                        return
                end
-               self.value = txt[1]
+               self.value = txt.chars[1]
        end
 end
 
@@ -101,7 +101,7 @@ redef class AStringFormExpr
        do
                var txt = self.n_string.text
                var skip = 1
-               if txt[0] == txt[1] and txt.length >= 6 then skip = 3
+               if txt.chars[0] == txt.chars[1] and txt.length >= 6 then skip = 3
                self.value = txt.substring(skip, txt.length-(2*skip)).unescape_nit
        end
 end
index b3e8458..753acea 100644 (file)
@@ -174,7 +174,7 @@ class Location
                var line_start = l.file.line_starts[i-1]
                var line_end = line_start
                var string = l.file.string
-               while line_end+1 < string.length and string[line_end+1] != '\n' and string[line_end+1] != '\r' do
+               while line_end+1 < string.length and string.chars[line_end+1] != '\n' and string.chars[line_end+1] != '\r' do
                        line_end += 1
                end
                var lstart = string.substring(line_start, l.column_start - 1)
@@ -195,7 +195,7 @@ class Location
                end
                var indent = new Buffer
                for j in [line_start..line_start+l.column_start-1[ do
-                       if string[j] == '\t' then
+                       if string.chars[j] == '\t' then
                                indent.add '\t'
                        else
                                indent.add ' '
index 2d2b6e4..d4b7a81 100644 (file)
@@ -51,7 +51,7 @@ private class Doc2Mdwn
                        # Count the number of spaces
                        lastindent = indent
                        indent = 0
-                       while text.length > indent and text[indent] == ' ' do indent += 1
+                       while text.length > indent and text.chars[indent] == ' ' do indent += 1
 
                        # Is codeblock? Then just collect them
                        if indent > 4 then
index 6425517..b3b6069 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 cd ..
-out=c_src2
+out=c_src
 rm -r "$out/" 2> /dev/null
 set -e
 set -x
index ff211ea..ad1c325 100644 (file)
@@ -1561,37 +1561,7 @@ abstract class MProperty
                end
 
                # Second, filter the most specific ones
-               var res = new Array[MPROPDEF]
-               for pd1 in candidates do
-                       var cd1 = pd1.mclassdef
-                       var c1 = cd1.mclass
-                       var keep = true
-                       for pd2 in candidates do
-                               if pd2 == pd1 then continue # do not compare with self!
-                               var cd2 = pd2.mclassdef
-                               var c2 = cd2.mclass
-                               if c2.mclass_type == c1.mclass_type then
-                                       if cd2.mmodule.in_importation <= cd1.mmodule then
-                                               # cd2 refines cd1; therefore we skip pd1
-                                               keep = false
-                                               break
-                                       end
-                               else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
-                                       # cd2 < cd1; therefore we skip pd1
-                                       keep = false
-                                       break
-                               end
-                       end
-                       if keep then
-                               res.add(pd1)
-                       end
-               end
-               if res.is_empty then
-                       print "All lost! {candidates.join(", ")}"
-                       # FIXME: should be abort!
-               end
-               self.lookup_definitions_cache[mmodule, mtype] = res
-               return res
+               return select_most_specific(mmodule, candidates)
        end
 
        private var lookup_definitions_cache: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
@@ -1604,13 +1574,13 @@ abstract class MProperty
        # If you want the really most specific property, then look at `lookup_next_definition`
        #
        # FIXME: Move to `MPropDef`?
-       fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPropDef]
+       fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
                if mtype isa MNullableType then mtype = mtype.mtype
 
                # First, select all candidates
-               var candidates = new Array[MPropDef]
+               var candidates = new Array[MPROPDEF]
                for mpropdef in self.mpropdefs do
                        # If the definition is not imported by the module, then skip
                        if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
@@ -1625,7 +1595,14 @@ abstract class MProperty
                if candidates.length <= 1 then return candidates
 
                # Second, filter the most specific ones
-               var res = new Array[MPropDef]
+               return select_most_specific(mmodule, candidates)
+       end
+
+       # Return an array containing olny the most specific property definitions
+       # This is an helper function for `lookup_definitions` and `lookup_super_definitions`
+       private fun select_most_specific(mmodule: MModule, candidates: Array[MPROPDEF]): Array[MPROPDEF]
+       do
+               var res = new Array[MPROPDEF]
                for pd1 in candidates do
                        var cd1 = pd1.mclassdef
                        var c1 = cd1.mclass
@@ -1635,12 +1612,12 @@ abstract class MProperty
                                var cd2 = pd2.mclassdef
                                var c2 = cd2.mclass
                                if c2.mclass_type == c1.mclass_type then
-                                       if cd2.mmodule.in_importation <= cd1.mmodule then
+                                       if cd2.mmodule.in_importation < cd1.mmodule then
                                                # cd2 refines cd1; therefore we skip pd1
                                                keep = false
                                                break
                                        end
-                               else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
+                               else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) and cd2.bound_mtype != cd1.bound_mtype then
                                        # cd2 < cd1; therefore we skip pd1
                                        keep = false
                                        break
index 7e83e4b..d946c12 100644 (file)
@@ -158,6 +158,10 @@ redef class MClass
        var inherit_init_from: nullable MClass = null
 end
 
+redef class MClassDef
+       private var propdef_names = new HashSet[String]
+end
+
 redef class AClassdef
        var build_properties_is_done: Bool = false
        # The list of super-constructor to call at the start of the free constructor
@@ -392,6 +396,20 @@ redef class AMethPropdef
 
                var mpropdef = new MMethodDef(mclassdef, mprop, self.location)
 
+               if mclassdef.propdef_names.has(mprop.name) then
+                       var loc: nullable Location = null
+                       for i in mclassdef.mpropdefs do
+                               if i.mproperty.name == mprop.name then
+                                       loc = i.location
+                                       break
+                               end
+                       end
+                       if loc == null then abort
+                       modelbuilder.error(self, "Error: a property {mprop} is already defined in class {mclassdef.mclass} at {loc}")
+               end
+
+               mclassdef.propdef_names.add(mpropdef.mproperty.name)
+
                self.mpropdef = mpropdef
                modelbuilder.mpropdef2npropdef[mpropdef] = self
                if mpropdef.is_intro then
@@ -507,9 +525,9 @@ redef class AMethPropdef
                                for i in [0..mysignature.arity[ do
                                        var myt = mysignature.mparameters[i].mtype
                                        var prt = msignature.mparameters[i].mtype
-                                       if not myt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, prt) and
+                                       if not myt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, prt) or
                                                        not prt.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, myt) then
-                                               modelbuilder.error(nsig.n_params[i], "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt}.")
+                                               modelbuilder.error(nsig.n_params[i], "Redef Error: Wrong type for parameter `{mysignature.mparameters[i].name}'. found {myt}, expected {prt} as in {mpropdef.mproperty.intro}.")
                                        end
                                end
                        end
@@ -518,7 +536,7 @@ redef class AMethPropdef
                                        # Inherit the return type
                                        ret_type = precursor_ret_type
                                else if not ret_type.is_subtype(mmodule, nclassdef.mclassdef.bound_mtype, precursor_ret_type) then
-                                       modelbuilder.error(nsig.n_type.as(not null), "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type}.")
+                                       modelbuilder.error(nsig.n_type.as(not null), "Redef Error: Wrong return type. found {ret_type}, expected {precursor_ret_type} as in {mpropdef.mproperty.intro}.")
                                end
                        end
                end
index 49b83a9..b5139f1 100644 (file)
@@ -751,13 +751,13 @@ redef class AInternMethPropdef
                                if arg1 >= recvval.length or arg1 < 0 then
                                        debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
                                end
-                               return v.char_instance(recvval[arg1])
+                               return v.char_instance(recvval.chars[arg1])
                        else if pname == "[]=" then
                                var arg1 = args[1].to_i
                                if arg1 >= recvval.length or arg1 < 0 then
                                        debug("Illegal access on {recvval} for element {arg1}/{recvval.length}")
                                end
-                               recvval[arg1] = args[2].val.as(Char)
+                               recvval.chars[arg1] = args[2].val.as(Char)
                                return null
                        else if pname == "copy_to" then
                                # sig= copy_to(dest: NativeString, length: Int, from: Int, to: Int)
index fc6dc36..cac7dd5 100755 (executable)
@@ -167,7 +167,7 @@ redef class Stdin
        do
                var loc_buf = new Buffer
                if connection.ready_to_read(0) then buf.append(connection.read)
-               for i in [buf_pos .. buf.length-1] do loc_buf.add(buf[i])
+               for i in [buf_pos .. buf.length-1] do loc_buf.add(buf.chars[i])
                buf.clear
                buf_pos = 0
                return loc_buf.to_s
@@ -185,7 +185,7 @@ redef class Stdin
                        buf.append(connection.read)
                end
                buf_pos += 1
-               return buf[buf_pos-1].ascii
+               return buf.chars[buf_pos-1].ascii
        end
 
        # Reads a line on the network if available
@@ -204,8 +204,8 @@ redef class Stdin
                                buf.append(connection.read)
                        end
                        buf_pos += 1
-                       if buf[buf_pos-1] == '\n' then break
-                       line_buf.add(buf[buf_pos-1])
+                       if buf.chars[buf_pos-1] == '\n' then break
+                       line_buf.add(buf.chars[buf_pos-1])
                end
                return line_buf.to_s
        end
diff --git a/src/nitni/nitni.nit b/src/nitni/nitni.nit
new file mode 100644 (file)
index 0000000..5778e5a
--- /dev/null
@@ -0,0 +1,25 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Native interface related services (used underneath the FFI)
+#
+# All nitni properties may not be visible to the user but they are
+# shared between engines
+module nitni
+
+import nitni_base
+import nitni_callbacks
+import nitni_utilities
diff --git a/src/nitni/nitni_base.nit b/src/nitni/nitni_base.nit
new file mode 100644 (file)
index 0000000..69f64f3
--- /dev/null
@@ -0,0 +1,149 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Native interface related services (used underneath the FFI)
+#
+# All nitni properties may not be visible to the user but they are
+# shared between engines
+module nitni_base
+
+import parser
+import modelbuilder # builder only for externcalls
+
+redef class MMethod
+       # Short name of this method in C (without the class name)
+       fun short_cname: String do
+               var nit_name = name
+
+               if nit_name == "+" then return "_plus"
+               if nit_name == "-" then return "_minus"
+               if nit_name == "*" then return "_star"
+               if nit_name == "/" then return "_slash"
+               if nit_name == "%" then return "_percent"
+               if nit_name == "[]" then return "_index"
+               if nit_name == "[]=" then return "_index_assign"
+               if nit_name == "==" then return "_equal"
+               if nit_name == "<" then return "_less"
+               if nit_name == ">" then return "_geater"
+               if nit_name == "<=" then return "_less_or_equal"
+               if nit_name == ">=" then return "_greater_or_equal"
+               if nit_name == "!=" then return "_not_equal"
+               if nit_name == "<<" then return "_left"
+               if nit_name == ">>" then return "_right"
+               if nit_name == "<=>" then return "_starship"
+
+               if nit_name.last == '=' then return "{nit_name.substring(0, nit_name.length-1)}__assign"
+               return nit_name
+       end
+end
+
+redef class AModule
+       # Mangled name of this module in C
+       fun cname: String do return mmodule.name
+end
+
+redef class MMethodDef
+       # Name of the function to callback this method from C,
+       # also used in other functions names used for this method.
+       fun cname: String do return "{mclassdef.mclass.name}_{mproperty.short_cname}"
+end
+
+redef class MType
+       # Representation of this type in pure C on the FFI extern side
+       #   Object -> Object
+       #   Pointer -> void*
+       fun cname: String is abstract
+
+       # Representation of this type in C for the internal of the system
+       # Hides extern types.
+       fun cname_blind: String is abstract
+
+       # Representation of this type in mangled C
+       #   Object -> Object
+       #   Pointer -> Pointer
+       fun mangled_cname: String is abstract
+
+       # Does this types has a primitive reprensentation
+       #   type Object is_primitive? false
+       #   type Pointer is_primitive? true
+       fun is_cprimitive: Bool is abstract
+end
+
+redef class MClassType
+       redef fun cname
+       do
+               var name = mclass.name
+               if name == "Bool" then return "int"
+               if name == "Char" then return "char"
+               if name == "Float" then return "double"
+               if name == "Int" then return "int"
+               if name == "NativeString" then return "char*"
+               if mclass.kind == extern_kind then
+                       var ctype = mclass.ctype
+                       assert ctype != null
+                       return ctype
+               end
+               return mangled_cname
+       end
+
+       redef fun cname_blind do
+               var name = mclass.name
+               if name == "Bool" then return "int"
+               if name == "Char" then return "char"
+               if name == "Float" then return "double"
+               if name == "Int" then return "int"
+               if name == "NativeString" then return "char*"
+               if mclass.kind == extern_kind then return "void*"
+               return "struct nitni_instance *"
+       end
+
+       redef fun mangled_cname do return mclass.name
+
+       redef fun is_cprimitive do return mclass.kind == extern_kind or
+                       (once ["Bool", "Char", "Float", "Int", "NativeString"]).has(mclass.name)
+end
+
+redef class MNullableType
+       redef fun cname do return mangled_cname
+       redef fun cname_blind do return "struct nitni_instance *"
+       redef fun mangled_cname do return "nullable_{mtype.mangled_cname}"
+       redef fun is_cprimitive do return false
+end
+
+redef class MVirtualType
+       redef fun mangled_cname: String do return to_s
+end
+
+redef class MGenericType
+       redef fun cname do return mangled_cname
+       redef fun mangled_cname
+       do
+               var base = super
+
+               var params = new Array[String]
+               for arg in arguments do params.add(arg.mangled_cname)
+
+               return "{base}_of_{params.join("_")}"
+       end
+end
+
+redef class MClass
+       fun ctype: nullable String
+       do
+               assert kind == extern_kind
+               return "void*"
+       end
+end
diff --git a/src/nitni/nitni_callbacks.nit b/src/nitni/nitni_callbacks.nit
new file mode 100644 (file)
index 0000000..5cf389f
--- /dev/null
@@ -0,0 +1,423 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# nitni services related to callbacks (used underneath the FFI)
+module nitni_callbacks
+
+import modelbuilder
+intrude import rapid_type_analysis
+
+import nitni_base
+
+redef class ToolContext
+       var verify_nitni_callback_phase: Phase = new VerifyNitniCallbacksPhase(self, [typing_phase])
+end
+
+# * checks for the validity of callbacks
+# * store the callbacks on each method
+class VerifyNitniCallbacksPhase
+       super Phase
+
+       redef fun process_npropdef(npropdef)
+       do
+               if not npropdef isa AExternPropdef then return
+
+               npropdef.verify_nitni_callbacks(toolcontext)
+       end
+end
+
+# Provides a better API but mainly the same content as AExternCalls
+class ForeignCallbackSet
+       # set of imported functions, cached to avoid repetitions
+       var callbacks: Set[ MExplicitCall ] = new HashSet[ MExplicitCall ]
+
+       # set of imported functions, cached to avoid repetitions
+       var supers: Set[ MExplicitSuper ] = new HashSet[ MExplicitSuper ]
+
+       # set of relevant types, cached to avoid repetitions
+       var types: Set[ MType ] = new HashSet[ MType ]
+
+       # set of imported casts and as, cached to avoid repetitions
+       var casts: Set[ MExplicitCast ] = new HashSet[ MExplicitCast ]
+
+       # Utility function, must be called only when all other maps are filled
+       private var all_cached: nullable Set[NitniCallback] = null
+       fun all: Set[NitniCallback]
+       do
+               var cached = all_cached
+               if cached != null then return cached
+
+               var set = new HashSet[NitniCallback]
+               set.add_all(callbacks)
+               set.add_all(supers)
+               set.add_all(types)
+               set.add_all(casts)
+               
+               self.all_cached = set
+               return set
+       end
+
+       # Integrate content from the `other` set into this one
+       fun join(other: ForeignCallbackSet)
+       do
+               callbacks.add_all( other.callbacks )
+               supers.add_all( other.supers )
+               types.add_all( other.types )
+               casts.add_all( other.casts )
+       end
+end
+
+redef class AExternPropdef
+       private var foreign_callbacks_cache: nullable ForeignCallbackSet = null
+
+       # All foreign callbacks from this method
+       fun foreign_callbacks: ForeignCallbackSet
+       do
+               var fcs = foreign_callbacks_cache
+               assert fcs != null else print "Error: attempting to access nitni callbacks before phase 'verify_nitni_callback_phase'."
+               return fcs
+       end
+
+       # Verifiy the validity of the explicit callbacks to Nit
+       # also fills the set returned by foreign_callbacks
+       fun verify_nitni_callbacks(toolcontext: ToolContext)
+       do
+               if foreign_callbacks_cache != null then return
+
+               var fcs = new ForeignCallbackSet
+
+               var mmodule = mpropdef.mclassdef.mmodule
+
+               # receiver
+               var recv_type = mpropdef.mclassdef.bound_mtype
+               fcs.types.add(recv_type)
+
+               # return type
+               var rmt = mpropdef.msignature.return_mtype
+               if rmt != null then
+                       if rmt isa MParameterType or rmt isa MVirtualType then
+                               var mclass_type = mpropdef.mclassdef.bound_mtype
+                               rmt = rmt.anchor_to(mmodule, mclass_type)
+                       end
+                       var mtype = rmt.resolve_for(recv_type, recv_type, mmodule, true)
+                       fcs.types.add(mtype)
+               end
+
+               # params
+               for p in mpropdef.msignature.mparameters do
+                       var mtype = p.mtype.resolve_for(recv_type, recv_type, mmodule, true)
+                       if mtype isa MParameterType or mtype isa MVirtualType then
+                               var mclass_type = mpropdef.mclassdef.bound_mtype
+                               mtype = mtype.anchor_to(mmodule, mclass_type)
+                       end
+                       fcs.types.add( mtype )
+               end
+
+               # explicit callbacks
+               if n_extern_calls != null then
+                       for ec in n_extern_calls.n_extern_calls do
+                               ec.verify_and_collect(self, fcs, toolcontext)
+                       end
+               end
+
+               # store result
+               foreign_callbacks_cache = fcs
+       end
+
+       redef fun accept_rapid_type_visitor(v)
+       do
+               for cb in foreign_callbacks.callbacks do v.add_send(cb.recv_mtype, cb.mproperty.as(MMethod))
+               for cast in foreign_callbacks.casts do v.add_cast_type(cast.to)
+               for sup in foreign_callbacks.supers do
+                       v.analysis.add_super_send(sup.from.mclassdef.mclass.mclass_type, sup.from.as(MMethodDef))
+               end
+               for t in foreign_callbacks.types do if t isa MClassType then v.add_type t
+       end
+end
+
+# Classification for all nitni callbacks
+interface NitniCallback
+end
+
+redef class MType
+       super NitniCallback
+end
+
+# A prossible call from C, declared explictly after the `import` keyword
+class MExplicitCall
+       super NitniCallback
+
+       # Previously resolved mtype
+       var recv_mtype: MClassType
+       var mproperty: MProperty
+       var from_mmodule: MModule
+
+       fun fill_type_for( callback_set: ForeignCallbackSet, from: MModule )
+       do
+               var first = mproperty.lookup_first_definition( from, recv_mtype )
+               var mclassdef = first.mclassdef
+               var bound_mtype = mclassdef.bound_mtype
+
+               # receiver / constructor return
+               recv_mtype = recv_mtype.resolve_for(bound_mtype, bound_mtype, from, true)
+               recv_mtype = recv_mtype.anchor_to(from, bound_mtype)
+               callback_set.types.add( recv_mtype )
+
+               if first isa MMethodDef then
+                       var rmt = first.msignature.return_mtype
+                       if rmt != null then
+                               rmt = rmt.resolve_for(bound_mtype, bound_mtype, from, true)
+                               rmt = rmt.anchor_to(from, bound_mtype)
+                               callback_set.types.add( rmt )
+                       end
+
+                       for p in first.msignature.mparameters do
+                               var param_mtype = p.mtype.resolve_for(recv_mtype, recv_mtype, from, true)
+                               param_mtype = param_mtype.resolve_for(bound_mtype, bound_mtype, from, true)
+                               param_mtype = param_mtype.anchor_to(from, bound_mtype)
+                               callback_set.types.add( param_mtype )
+                       end
+               end
+       end
+
+       # Signature of this call in C as seen by user
+       fun csignature: String
+       do
+               var mproperty = self.mproperty
+               if mproperty isa MMethod then
+                       var signature = mproperty.intro.msignature
+                       assert signature != null
+
+                       var creturn_type
+                       if mproperty.is_init then
+                               creturn_type = recv_mtype.cname
+                       else if signature.return_mtype != null then
+                               var ret_mtype = signature.return_mtype
+                               ret_mtype = ret_mtype.resolve_for(recv_mtype, recv_mtype, from_mmodule, true)
+                               creturn_type = ret_mtype.cname
+                       else
+                               creturn_type = "void"
+                       end
+
+                       var cname
+                       if mproperty.is_init then
+                               if mproperty.name == "init" or mproperty.name == "new" then
+                                       cname = "new_{recv_mtype.mangled_cname}"
+                               else
+                                       cname = "new_{recv_mtype.mangled_cname}_{mproperty.short_cname}"
+                               end
+                       else
+                               cname = "{recv_mtype.mangled_cname}_{mproperty.short_cname}"
+                       end
+
+                       var cparams = new List[String]
+                       if not mproperty.is_init then
+                               cparams.add( "{recv_mtype.cname} self" )
+                       end
+                       for p in signature.mparameters do
+                               var param_mtype = p.mtype.resolve_for(recv_mtype, recv_mtype, from_mmodule, true)
+                               cparams.add( "{param_mtype.cname} {p.name}" )
+                       end
+
+                       return "{creturn_type} {cname}( {cparams.join(", ")} )"
+               else
+                       print "Type of callback from foreign code not yet supported."
+                       abort
+               end
+       end
+
+       redef fun hash do return recv_mtype.hash + 1024 * mproperty.hash
+       redef fun ==(o) do return o isa MExplicitCall and recv_mtype == o.recv_mtype and mproperty == o.mproperty
+end
+
+class MExplicitSuper
+       super NitniCallback
+
+       var from: MPropDef
+
+       redef fun hash do return from.hash
+       redef fun ==(o) do return o isa MExplicitSuper and from == o.from
+end
+
+class MExplicitCast
+       super NitniCallback
+
+       var from: MType
+       var to: MType
+
+       fun check_cname: String do return "{from.mangled_cname}_is_a_{to.mangled_cname}"
+
+       fun cast_cname: String do return "{from.mangled_cname}_as_{to.mangled_cname}"
+
+       redef fun hash do return from.hash + 1024 * to.hash
+       redef fun ==(o) do return o isa MExplicitCast and from == o.from and to == o.to
+end
+
+redef class AExternCall
+       # Verify this explicit declaration of call from C and collect all relevant callbacks
+       fun verify_and_collect(npropdef: AExternPropdef, callback_set: ForeignCallbackSet,
+               toolcontext: ToolContext) is abstract
+end
+
+redef class ALocalPropExternCall
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               var mmodule = npropdef.mpropdef.mclassdef.mmodule
+               var mclass_type = npropdef.mpropdef.mclassdef.bound_mtype
+               var m_name = n_methid.collect_text
+               var method = toolcontext.modelbuilder.try_get_mproperty_by_name2( self,
+                       mmodule, mclass_type, m_name )
+
+               if method == null then
+                       toolcontext.error(location, "Local method {m_name} not found.")
+                       return
+               end
+
+               var explicit_call = new MExplicitCall(mclass_type, method, mmodule)
+               callback_set.callbacks.add(explicit_call)
+
+               explicit_call.fill_type_for(callback_set, mmodule)
+       end
+end
+
+redef class AFullPropExternCall
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               var mmodule = npropdef.mpropdef.mclassdef.mmodule
+               var mclassdef = npropdef.mpropdef.mclassdef
+               var nclassdef = toolcontext.modelbuilder.mclassdef2nclassdef[mclassdef]
+               var mclass_type = mclassdef.bound_mtype
+               var mtype = toolcontext.modelbuilder.resolve_mtype(nclassdef, n_type)
+
+               if mtype == null then return
+
+               if mtype isa MParameterType or mtype isa MVirtualType then
+                       mtype = mtype.anchor_to(mmodule, mclass_type)
+               end
+
+               if mtype isa MNullableType then
+                       toolcontext.error(location, "Type {n_type.collect_text} is nullable and thus cannot be the receiver." )
+                       return
+               end
+
+               var m_name = n_methid.collect_text
+               var method = toolcontext.modelbuilder.try_get_mproperty_by_name2( self,
+                       mmodule, mtype, m_name )
+
+               if method == null then
+                       toolcontext.error(location, "Method {m_name} not found in {n_type.collect_text}." )
+                       return
+               end
+
+               var explicit_call = new MExplicitCall(mtype.as(MClassType), method, mmodule)
+               callback_set.callbacks.add(explicit_call)
+               explicit_call.fill_type_for(callback_set, mmodule)
+       end
+end
+
+redef class AInitPropExternCall
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               var mmodule = npropdef.mpropdef.mclassdef.mmodule
+               var mclassdef = npropdef.mpropdef.mclassdef
+               var nclassdef = toolcontext.modelbuilder.mclassdef2nclassdef[mclassdef]
+               var mtype = toolcontext.modelbuilder.resolve_mtype(nclassdef, n_type)
+               if mtype == null then return
+
+               if not mtype isa MClassType then
+                       toolcontext.error(location, "Type {n_type.collect_text} is not a class and thus cannot be used to instanciate a new instance." )
+                       return
+               end
+
+               var meth_name = "init"
+               var meth = toolcontext.modelbuilder.try_get_mproperty_by_name2( self,
+                       mmodule, mtype, meth_name )
+
+               if meth == null then
+                       toolcontext.error(location, "Method {meth_name} not found in {n_type.collect_text}." )
+                       return
+               end
+
+               var explicit_call = new MExplicitCall(mtype, meth, mmodule)
+               callback_set.callbacks.add(explicit_call)
+               explicit_call.fill_type_for(callback_set, mmodule)
+       end
+end
+
+redef class ASuperExternCall
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               callback_set.supers.add( new MExplicitSuper( npropdef.mpropdef.as(not null) ) )
+               callback_set.types.add( npropdef.mpropdef.mclassdef.mclass.mclass_type )
+       end
+end
+
+redef class ACastExternCall
+       fun from_mtype: MType is abstract
+       fun to_mtype: MType is abstract
+
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               var from = from_mtype
+               var to = to_mtype
+
+               callback_set.types.add(from)
+               callback_set.types.add(to)
+
+               callback_set.casts.add(new MExplicitCast(from, to))
+       end
+end
+
+redef class ACastAsExternCall
+       redef fun from_mtype do return n_from_type.mtype.as(not null)
+       redef fun to_mtype do return n_to_type.mtype.as(not null)
+
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               var parent_aclassdef = npropdef.parent.as(AClassdef)
+               toolcontext.modelbuilder.resolve_mtype_unchecked(parent_aclassdef, n_from_type, true)
+               toolcontext.modelbuilder.resolve_mtype_unchecked(parent_aclassdef, n_to_type, true)
+               super
+       end
+end
+
+redef class AAsNullableExternCall
+       redef fun from_mtype do return n_type.mtype.as(not null)
+       redef fun to_mtype do return n_type.mtype.as_nullable
+
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               var parent_aclassdef = npropdef.parent.as(AClassdef)
+               toolcontext.modelbuilder.resolve_mtype_unchecked(parent_aclassdef, n_type, true)
+               super
+       end
+end
+
+redef class AAsNotNullableExternCall
+       redef fun from_mtype do return n_type.mtype.as_nullable
+       redef fun to_mtype do
+               var mtype = n_type.mtype.as(not null)
+               if mtype isa MNullableType then return mtype.mtype
+               return mtype
+       end
+
+       redef fun verify_and_collect(npropdef, callback_set, toolcontext)
+       do
+               var parent_aclassdef = npropdef.parent.as(AClassdef)
+               toolcontext.modelbuilder.resolve_mtype_unchecked(parent_aclassdef, n_type, true)
+               super
+       end
+end
diff --git a/src/nitni/nitni_utilities.nit b/src/nitni/nitni_utilities.nit
new file mode 100644 (file)
index 0000000..80c6691
--- /dev/null
@@ -0,0 +1,150 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# 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.
+
+# Support utilities to use nitni and the FFI
+import nitni_base
+
+redef class MMethod
+       # Build a C function name for the FFI implementation (uses friendly naming).
+       # * On a specific static receiver mype `recv_mtype` 
+       # * In referene to the module `from_module` (used for type resolving and as a possible prefix)
+       # * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
+       # * With a specified length indicating whether it uses the sort name or the long name with
+       #   the module name as prefix
+       fun build_cname(recv_mtype: MClassType, from_mmodule: MModule, suffix: nullable String, length: SignatureLength): String
+       do
+               var cname
+               if self.is_init then
+                       if self.name == "init" or self.name == "new" then
+                               cname = "new_{recv_mtype.mangled_cname}"
+                       else
+                               cname = "new_{recv_mtype.mangled_cname}_{self.short_cname}"
+                       end
+               else
+                       cname = "{recv_mtype.mangled_cname}_{self.short_cname}"
+               end
+
+               if suffix != null then cname = "{cname}{suffix}"
+
+               if length.long then cname = "{from_mmodule.name}___{cname}"
+
+               return cname
+       end
+
+       # Build a C function signature for the FFI implementation (uses friendly naming).
+       # * On a specific static receiver mype `recv_mtype` 
+       # * In referene to the module `from_module` (used for type resolving and as a possible prefix)
+       # * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
+       # * With a specified length indicating whether it uses the sort name or the long name with
+       #   the module name as prefix
+       # * The `call_context` identifying which types and casts to use (see `CallContext` and its instances)
+       fun build_csignature(recv_mtype: MClassType, from_mmodule: MModule, suffix: nullable String, length: SignatureLength, call_context: CallContext): String
+       do
+               var signature = self.intro.msignature
+               assert signature != null
+
+               var creturn_type
+               if self.is_init then
+                       creturn_type = call_context.name_mtype(recv_mtype)
+               else if signature.return_mtype != null then
+                       var ret_mtype = signature.return_mtype
+                       ret_mtype = ret_mtype.resolve_for(recv_mtype, recv_mtype, from_mmodule, true)
+                       creturn_type = call_context.name_mtype(ret_mtype)
+               else
+                       creturn_type = "void"
+               end
+
+               var cname = build_cname(recv_mtype, from_mmodule, suffix, length)
+
+               var cparams = new List[String]
+               if not self.is_init then
+                       cparams.add( "{call_context.name_mtype(recv_mtype)} recv" )
+               end
+               for p in signature.mparameters do
+                       var param_mtype = p.mtype.resolve_for(recv_mtype, recv_mtype, from_mmodule, true)
+                       cparams.add( "{call_context.name_mtype(param_mtype)} {p.name}" )
+               end
+
+               return "{creturn_type} {cname}( {cparams.join(", ")} )"
+       end
+
+       # Build a C function call for the FFI implementation (uses friendly naming).
+       # * On a specific static receiver mype `recv_mtype` 
+       # * In referene to the module `from_module` (used for type resolving and as a possible prefix)
+       # * Has a possible `suffix` to the method name (may be "__super", "__impl", null, etc.)
+       # * With a specified length indicating whether it uses the sort name or the long name with
+       #   the module name as prefix
+       # * The `call_context` identifying which types and casts to use (see `CallContext` and its instances)
+       # * Possible suffix to the parameters `param_suffix`
+       fun build_ccall(recv_mtype: MClassType, from_mmodule: MModule, suffix: nullable String, length: SignatureLength, call_context: CallContext, param_suffix: nullable String): String
+       do
+               if param_suffix == null then param_suffix = ""
+
+               var signature = self.intro.msignature
+               assert signature != null
+
+               var return_mtype = null
+               if self.is_init then
+                       return_mtype = recv_mtype
+               else if signature.return_mtype != null then
+                       return_mtype = signature.return_mtype
+               end
+
+               var cname = build_cname(recv_mtype, from_mmodule, suffix, length)
+
+               var cparams = new List[String]
+               if not self.is_init then
+                       cparams.add(call_context.cast_to(recv_mtype, "recv{param_suffix}"))
+               end
+
+               for p in signature.mparameters do
+                       cparams.add(call_context.cast_to(p.mtype, "{p.name}{param_suffix}"))
+               end
+
+               var joined_cparams = cparams.join(", ")
+               var ccall = "{cname}({joined_cparams})"
+               if return_mtype != null then
+                       return "return {call_context.cast_from(return_mtype, ccall)};"
+               else
+                       return "{ccall};"
+               end
+       end
+end
+
+# Describes the context of the code to be generated by `build_ccall` and `build_csignature`
+class CallContext
+       # Which C name to use for type `mtype`
+       fun name_mtype(mtype: MType): String do return mtype.cname_blind
+
+       # How to cast a returned C variable named `name` of type `mtype`
+       fun cast_from(mtype: MType, name: String): String do return name
+
+       # How to cast a C argument named `name` of type `mtype`
+       fun cast_to(mtype: MType, name: String): String do return name
+end
+
+redef class Object
+       # Call context to use
+       protected fun internal_call_context: CallContext do return new CallContext
+       protected fun long_signature: SignatureLength do return once new SignatureLength(true)
+       protected fun short_signature: SignatureLength do return once new SignatureLength(false)
+end
+
+# Length of the signature of a C function (long version hase the module name as prefix)
+class SignatureLength
+       private var long: Bool
+       private init(long: Bool) do self.long = long
+end
index 84c0815..c073793 100644 (file)
@@ -159,7 +159,7 @@ class NitIndex
                else
                        var category = parts[0]
                        var keyword = parts[1]
-                       if keyword.first == ' ' then keyword = keyword.substring_from(1)
+                       if keyword.chars.first == ' ' then keyword = keyword.substring_from(1)
                        return new IndexQueryPair(str, keyword, category)
                end
        end
@@ -863,7 +863,7 @@ redef class String
        private fun escape: String
        do
                var b = new Buffer
-               for c in self do
+               for c in self.chars do
                        if c == '\n' then
                                b.append("\\n")
                        else if c == '\0' then
index 5e230dc..614a11e 100644 (file)
@@ -1297,7 +1297,7 @@ class Lexer
                        if sp >= string_len then
                                dfa_state = -1
                        else
-                               var c = string[sp].ascii
+                               var c = string.chars[sp].ascii
                                sp += 1
 
                                var cr = _cr
index 6a4d1d0..7784714 100644 (file)
@@ -107,7 +107,7 @@ $ end foreach
                        if sp >= string_len then
                                dfa_state = -1
                        else
-                               var c = string[sp].ascii
+                               var c = string.chars[sp].ascii
                                sp += 1
 
                                var cr = _cr
index e553259..981c0d8 100644 (file)
@@ -19,6 +19,7 @@ import abstract_compiler
 import layout_builders
 import rapid_type_analysis
 import collect_super_sends
+import compiler_ffi
 
 # Add separate compiler specific options
 redef class ToolContext
@@ -894,6 +895,17 @@ class SeparateCompiler
                end
                print "\t{total}\t{holes}"
        end
+
+       redef fun compile_nitni_structs
+       do
+               self.header.add_decl("struct nitni_instance \{struct instance *value;\};")
+       end
+       
+       redef fun finalize_ffi_for_module(nmodule)
+       do
+               self.mainmodule = nmodule.mmodule.as(not null)
+               super
+       end
 end
 
 # A visitor on the AST of property definition that generate the C code of a separate compilation process.
@@ -936,6 +948,8 @@ class SeparateCompilerVisitor
                        end
                        self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
                        return res
+               else if value.mtype.cname_blind == "void*" and mtype.cname_blind == "void*" then
+                       return value
                else
                        # Bad things will appen!
                        var res = self.new_var(mtype)
index 91851ba..674753c 100644 (file)
@@ -45,7 +45,7 @@ var only_lexer = false
 var need_help = false
 var no_file = false
 
-while not args.is_empty and args.first.first == '-' do
+while not args.is_empty and args.first.chars.first == '-' do
        if args.first == "-n" then
                no_print = true
        else if args.first == "-l" then
index be0b742..719fae2 100644 (file)
@@ -1438,7 +1438,6 @@ redef class ASuperExpr
                end
                # FIXME: covariance of return type in linear extension?
                var superprop = superprops.first
-               assert superprop isa MMethodDef
 
                var msignature = v.resolve_signature_for(superprop, recvtype, true)
                var args = self.n_args.to_a
diff --git a/tests/base_error_doubledef.nit b/tests/base_error_doubledef.nit
new file mode 100644 (file)
index 0000000..a0961db
--- /dev/null
@@ -0,0 +1,29 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import end
+
+class A
+       fun foo do end
+end
+
+class B
+       super A
+
+       redef fun foo do end
+
+       redef fun foo do end
+
+end
+
index 4ff4c8e..8251428 100644 (file)
@@ -17,7 +17,7 @@ import string
 redef class String
        redef fun output
        do
-               for c in self do c.output
+               for c in self.chars do c.output
        end
 end
 
index 9f5944f..6a2d643 100644 (file)
@@ -48,7 +48,7 @@ print(i)
 
 i = 0
 for k in [0..s.length[ do
-       var c = s[k]
+       var c = s.chars[k]
        if c >= 'a' and c <= 'z' then
                i = i + 1
        end
index 069ed21..a78d01f 100644 (file)
@@ -20,8 +20,8 @@ fun first_word(s: String): String
 do
        var result = new Buffer
        var i = 0
-       while i < s.length and s[i] != ' ' do
-               result.add(s[i])
+       while i < s.length and s.chars[i] != ' ' do
+               result.add(s.chars[i])
                i = i + 1
        end
        return result.to_s
diff --git a/tests/sav/base_error_doubledef.res b/tests/sav/base_error_doubledef.res
new file mode 100644 (file)
index 0000000..ed17cab
--- /dev/null
@@ -0,0 +1 @@
+base_error_doubledef.nit:26,12--14: Error: a property foo is already defined in class B at base_error_doubledef.nit:24,2--21
index b005476..44d3647 100644 (file)
@@ -1 +1 @@
-error_ref_param.nit:20,14--17: Redef error: Expected B, as in C::r.
+error_ref_param.nit:20,14--17: Redef Error: Wrong type for parameter `x'. found C, expected B as in module_simple#C#r.
index b5bc984..afb9bdb 100644 (file)
@@ -1 +1 @@
-error_ref_ret.nit:20,15--17: Redef Error: Wrong return type. found Int, expected B.
+error_ref_ret.nit:20,15--17: Redef Error: Wrong return type. found Int, expected B as in module_simple#C#s.
index 5a89161..c440f90 100644 (file)
@@ -1 +1 @@
-error_spe_param.nit:24,16--24: Redef error: Expected Int, as in A::toto.
+error_spe_param.nit:24,16--24: Redef Error: Wrong type for parameter `c'. found Object, expected Int as in error_spe_param#A#toto.
index 9b57ac5..733cf4f 100644 (file)
@@ -1 +1 @@
-error_spe_param2.nit:24,16--22: Redef Error: Wrong type for parameter `c'. found Char, expected Int.
+error_spe_param2.nit:24,16--22: Redef Error: Wrong type for parameter `c'. found Char, expected Int as in error_spe_param2#A#toto.
index 4e85242..7c1a5f8 100644 (file)
@@ -1 +1 @@
-error_spe_ret.nit:23,17--20: Redef Error: Wrong return type. found Char, expected Int.
+error_spe_ret.nit:23,17--20: Redef Error: Wrong return type. found Char, expected Int as in error_spe_ret#A#toto.
diff --git a/tests/sav/fixme/error_ref_param.res b/tests/sav/fixme/error_ref_param.res
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tests/sav/fixme/error_spe_param.res b/tests/sav/fixme/error_spe_param.res
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/tests/sav/fixme/test_multiconstraint_inh.res b/tests/sav/fixme/test_multiconstraint_inh.res
deleted file mode 100644 (file)
index 0cfbf08..0000000
+++ /dev/null
@@ -1 +0,0 @@
-2
index cd69487..ec31f82 100644 (file)
@@ -1 +1 @@
-test_multiconstraint_inh.nit:39,18--21: Redef error: Expected I[A], as in G::baz.
+test_multiconstraint_inh.nit:39,18--21: Redef Error: Wrong type for parameter `e'. found J, expected I[G#0] as in test_multiconstraint_inh#G#baz.
index ea32fbf..f2d3216 100644 (file)
@@ -196,7 +196,7 @@ Start ../src/test_parser.nit:17,1--110,1
               TKwfalse "false" ../src/test_parser.nit:46,15--19
           AWhileExpr ../src/test_parser.nit:48,1--64,3
             TKwwhile "while" ../src/test_parser.nit:48,1--5
-            AAndExpr ../src/test_parser.nit:48,7--51
+            AAndExpr ../src/test_parser.nit:48,7--57
               ANotExpr ../src/test_parser.nit:48,7--23
                 TKwnot "not" ../src/test_parser.nit:48,7--9
                 ACallExpr ../src/test_parser.nit:48,11--23
@@ -206,20 +206,23 @@ Start ../src/test_parser.nit:17,1--110,1
                     AListExprs ../src/test_parser.nit:48,14
                   TId "is_empty" ../src/test_parser.nit:48,16--23
                   AListExprs ../src/test_parser.nit:48,23
-              AEqExpr ../src/test_parser.nit:48,29--51
-                ACallExpr ../src/test_parser.nit:48,29--44
-                  ACallExpr ../src/test_parser.nit:48,29--38
-                    ACallExpr ../src/test_parser.nit:48,29--32
-                      AImplicitSelfExpr ../src/test_parser.nit:48,29
-                      TId "args" ../src/test_parser.nit:48,29--32
-                      AListExprs ../src/test_parser.nit:48,32
-                    TId "first" ../src/test_parser.nit:48,34--38
-                    AListExprs ../src/test_parser.nit:48,38
-                  TId "first" ../src/test_parser.nit:48,40--44
-                  AListExprs ../src/test_parser.nit:48,44
-                ACharExpr ../src/test_parser.nit:48,49--51
-                  TChar "\'-\'" ../src/test_parser.nit:48,49--51
-            TKwdo "do" ../src/test_parser.nit:48,53--54
+              AEqExpr ../src/test_parser.nit:48,29--57
+                ACallExpr ../src/test_parser.nit:48,29--50
+                  ACallExpr ../src/test_parser.nit:48,29--44
+                    ACallExpr ../src/test_parser.nit:48,29--38
+                      ACallExpr ../src/test_parser.nit:48,29--32
+                        AImplicitSelfExpr ../src/test_parser.nit:48,29
+                        TId "args" ../src/test_parser.nit:48,29--32
+                        AListExprs ../src/test_parser.nit:48,32
+                      TId "first" ../src/test_parser.nit:48,34--38
+                      AListExprs ../src/test_parser.nit:48,38
+                    TId "chars" ../src/test_parser.nit:48,40--44
+                    AListExprs ../src/test_parser.nit:48,44
+                  TId "first" ../src/test_parser.nit:48,46--50
+                  AListExprs ../src/test_parser.nit:48,50
+                ACharExpr ../src/test_parser.nit:48,55--57
+                  TChar "\'-\'" ../src/test_parser.nit:48,55--57
+            TKwdo "do" ../src/test_parser.nit:48,59--60
             ABlockExpr ../src/test_parser.nit:49,2--64,3
               AIfExpr ../src/test_parser.nit:49,2--62,4
                 TKwif "if" ../src/test_parser.nit:49,2--3
index af40e9f..f647540 100644 (file)
@@ -212,11 +212,13 @@ Read token at ../src/test_parser.nit:48,29--32 text='args'
 Read token at ../src/test_parser.nit:48,33 text='.'
 Read token at ../src/test_parser.nit:48,34--38 text='first'
 Read token at ../src/test_parser.nit:48,39 text='.'
-Read token at ../src/test_parser.nit:48,40--44 text='first'
-Read token at ../src/test_parser.nit:48,46--47 text='=='
-Read token at ../src/test_parser.nit:48,49--51 text=''-''
-Read token at ../src/test_parser.nit:48,53--54 text='do'
-Read token at ../src/test_parser.nit:48,55--49,0 text='
+Read token at ../src/test_parser.nit:48,40--44 text='chars'
+Read token at ../src/test_parser.nit:48,45 text='.'
+Read token at ../src/test_parser.nit:48,46--50 text='first'
+Read token at ../src/test_parser.nit:48,52--53 text='=='
+Read token at ../src/test_parser.nit:48,55--57 text=''-''
+Read token at ../src/test_parser.nit:48,59--60 text='do'
+Read token at ../src/test_parser.nit:48,61--49,0 text='
 '
 Read token at ../src/test_parser.nit:49,2--3 text='if'
 Read token at ../src/test_parser.nit:49,5--8 text='args'
diff --git a/tests/sav/test_ropes.res b/tests/sav/test_ropes.res
deleted file mode 100644 (file)
index ce6b816..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-Je suis ici.
-Je suis ici.Je suis ici.Je suis ici.
-Je suis ici.Je suis ici.Je suis ici.Je suis ici.Je suis ici.
-Je suis ici.Je suis ici.
-Je su
-je suis ici.hi !je suis ici.hi !
-JE SUIS ICI.HI !JE SUIS ICI.HI !
index b84da54..b0ecf41 100644 (file)
@@ -19,13 +19,13 @@ do
        var count = 0
        var array = new Buffer.with_capacity(n)
        for i in [0..n[ do
-               array[i] = 'o'
+               array.chars[i] = 'o'
        end
        for i in [2..n[ do
-               if array[i] == 'o' then
+               if array.chars[i] == 'o' then
                        var j = i * 2
                        while j < n do
-                               array[j] = 'x'
+                               array.chars[j] = 'x'
                                j = j + i
                        end
                        count = count + 1
index 70977d8..2f8e168 100644 (file)
@@ -28,7 +28,7 @@ class StringTest
                referenced_str = null
        end
 
-       fun get_c_string import String::items, NativeString::to_s, NativeString::to_s_with_copy, StringTest::ref_test, StringTest::copy_test `{
+       fun get_c_string import String.items, NativeString.to_s, NativeString.to_s_with_copy, StringTest.ref_test, StringTest.copy_test `{
                char* string = "This is a test string";
 
                String ref_string = NativeString_to_s(string);
index dbe69c5..ad76c0a 100644 (file)
@@ -19,19 +19,19 @@ class A
        var w : String = "w"
        var rw : String = "rw"
 
-       fun print_all import String::to_cstring, r, rw `{
+       fun print_all import String.to_cstring, r, rw `{
                printf( "%s %s\n",
                        String_to_cstring( A_r( recv ) ),
                        String_to_cstring( A_rw( recv ) ) );
        `}
-       fun modify import NativeString::to_s, w=, rw= `{
+       fun modify import NativeString.to_s, w=, rw= `{
                A_w__assign( recv, NativeString_to_s( "w set from native" ) );
                A_rw__assign( recv, NativeString_to_s( "rw set from native" ) );
        `}
 end
 
 class B
-       fun print_and_modify( a : A ) import A::rw, A::rw=, String::to_cstring, NativeString::to_s `{
+       fun print_and_modify( a : A ) import A.rw, A.rw=, String.to_cstring, NativeString.to_s `{
                printf( "%s\n", String_to_cstring( A_rw( a ) ) );
                A_rw__assign( a, NativeString_to_s( "set from native" ) );
                printf( "%s\n", String_to_cstring( A_rw( a ) ) );
index 1e1e0c5..477dfc1 100644 (file)
@@ -29,7 +29,7 @@ extern Test
         return foobar;
     `}
 
-    fun test_me is extern import Test::foo, NativeString::to_s `{
+    fun test_me is extern import Test.foo, NativeString.to_s `{
         int i;
         for(i = 0; i < 2000; ++i) {
             printf("%d\n", i);
index b4b7cd5..fee35a5 100644 (file)
@@ -24,7 +24,7 @@ fun call_a_fun import foo `{
        Object_foo(recv);
 `}
 
-fun call_a_constructor import A, A::bar `{
+fun call_a_constructor import A, A.bar `{
        A a = new_A();
        A_bar(a);
 `}
index 5646cb0..1511348 100644 (file)
@@ -32,7 +32,7 @@ redef class Int
        redef fun foo do print self
 end
 
-fun callbacks_with_as_casts(a: A, b: B) import B::foo, A::foo, B as(A), A as(B) `{
+fun callbacks_with_as_casts(a: A, b: B) import B.foo, A.foo, B.as(A), A.as(B) `{
        A_foo(a);
        B_foo(b);
 
@@ -47,7 +47,7 @@ fun callbacks_with_as_casts(a: A, b: B) import B::foo, A::foo, B as(A), A as(B)
        B_foo(bb);
 `}
 
-fun callbacks_with_nullable_casts(a: A, b: nullable B) import B as not nullable, A as nullable, A as(nullable B), B::foo `{
+fun callbacks_with_nullable_casts(a: A, b: nullable B) import B as not nullable, A as nullable, A.as(nullable B), B.foo `{
        if (!nullable_B_is_a_B(b)) {
                printf("Instance b is not a B (it is null)\n");
        } else {
@@ -63,7 +63,7 @@ fun callbacks_with_nullable_casts(a: A, b: nullable B) import B as not nullable,
        }
 `}
 
-fun callbacks_with_failed_checks(a: A, b: nullable B) import B as not nullable, B as nullable, A as(B), B as (A) `{
+fun callbacks_with_failed_checks(a: A, b: nullable B) import B as not nullable, B as nullable, A.as(B), B.as(A) `{
        if (!A_is_a_B(a)) {
                printf("Instance of A is not a B.\n");
        }
@@ -72,7 +72,7 @@ fun callbacks_with_failed_checks(a: A, b: nullable B) import B as not nullable,
        }
 `}
 
-fun callbacks_with_primitives(o: Object, i: Int, ni: nullable Int) import Object as(Int), Int as(Object), nullable Int as(Int), Int::foo, Object::foo `{
+fun callbacks_with_primitives(o: Object, i: Int, ni: nullable Int) import Object.as(Int), Int.as(Object), nullable Int.as(Int), Int.foo, Object.foo `{
        Object_foo(o);
        Int_foo(i);
 
index daac6f2..9b90564 100644 (file)
@@ -27,7 +27,7 @@ class ToBePreserved
 end
 
 class A
-       fun save_as_global( tbp : ToBePreserved, i : Int ) import ToBePreserved::output `{
+       fun save_as_global( tbp : ToBePreserved, i : Int ) import ToBePreserved.output `{
                if ( global_tbps[i] != NULL )
                        ToBePreserved_decr_ref( global_tbps[i] );
 
index e795227..04d82a9 100644 (file)
@@ -38,11 +38,11 @@ extern A
 
        fun m : Int is extern `{ return 10; `}
 
-       fun n : String is extern import NativeString::to_s `{
+       fun n : String is extern import NativeString.to_s `{
                return NativeString_to_s( "allo" );
        `}
 
-       fun o ( str : String ) is extern import String::to_cstring `{
+       fun o ( str : String ) is extern import String.to_cstring `{
                f( String_to_cstring( str ) );
        `}
 
index 9a25f36..6be81fe 100644 (file)
@@ -31,7 +31,7 @@ end
 fun in1(i: Int) do print "Back in Nit: in1 {i}"
 fun in2(i: Float) do print "Back in Nit: in2"
 
-fun out(i: Int, f: Float): Int import in1, in2, A, A::alt, A::to_i `{
+fun out(i: Int, f: Float): Int import in1, in2, A, A.alt, A.to_i `{
        printf("From C, beginning out: %ld\n", i);
        Object_in1(recv, i);
        A a = new_A();
index 4c89e6a..3174cb7 100644 (file)
@@ -45,7 +45,7 @@ class A
                return new_A( s / by );
        `}
 
-       redef fun ==( other ) import value, nullable Object as(A) `{
+       redef fun ==( other ) import value, nullable Object.as(A) `{
                if ( nullable_Object_is_a_A( other ) &&
                         A_value( nullable_Object_as_A(other) ) == A_value( recv ) )
                        return 1;
index aad8b05..e4d3fe2 100644 (file)
@@ -22,11 +22,11 @@ fun get_cstring: NativeString `{
        return "char* from C";
 `}
 
-fun print_string(str: String) import String::to_cstring `{
+fun print_string(str: String) import String.to_cstring `{
        printf("str-> %s\n", String_to_cstring(str) );
 `}
 
-fun get_string: String import NativeString::to_s, String::output `{
+fun get_string: String import NativeString.to_s, String.output `{
        String str = NativeString_to_s("Nit string from C");
        String_output(str);
        printf("\n");
index 68c20f8..8b241ff 100644 (file)
@@ -21,7 +21,7 @@ end
 class B
        super A
 
-       redef fun id : String import super, NativeString::to_s, String::to_cstring `{
+       redef fun id : String import super, NativeString.to_s, String.to_cstring `{
                char *new_name;
                char *prefix = "B special ";
                char *super_name = String_to_cstring( B_id___super( recv ) );
diff --git a/tests/test_ropes.nit b/tests/test_ropes.nit
deleted file mode 100644 (file)
index 86a0cd7..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-# 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 if 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 as a part of
-# another product.
-
-module test_ropes
-
-var str_part_1 = "Je"
-
-var str_part_2 = "suis"
-
-var str_part_3 = "ici"
-
-var str_part_4 = "."
-
-var space = " "
-
-var test = "Je suis ici."
-
-var rope_uniq_test = new ImmutableRope.with_string("zzzzzzzzzzzzzzzzzzzzzzzzzzzz")
-
-var not_rope_uniq_test = new ImmutableRope.with_string("zzzzzzzzzzzzzezzzzzzzzzzzzzz")
-
-################################
-#      Rope methods tests      #
-################################
-
-var buf = new Buffer
-
-buf.append(str_part_1)
-buf.append(space)
-buf.append(str_part_2)
-buf.append(space)
-buf.append(str_part_3)
-buf.append(str_part_4)
-
-print buf
-
-var buf_rope = new BufferRope
-
-buf_rope.append_multi(str_part_1,space,str_part_2,space,str_part_3,str_part_4)
-
-var buf_rope_with_str = new BufferRope.with_string(test)
-
-print buf_rope*3
-
-print buf_rope_with_str*5
-
-print buf_rope + buf_rope_with_str
-
-assert buf_rope.length == buf_rope_with_str.length
-
-assert buf_rope == buf_rope_with_str
-
-assert buf_rope.multi_concat(buf_rope, buf_rope) == buf_rope * 3
-
-print buf_rope.subrope(0, 5)
-
-assert buf_rope.subrope(0, 5) == "Je su"
-
-buf_rope.append("Hi !")
-
-assert buf_rope > buf_rope_with_str
-
-assert buf_rope == buf_rope.chars.to_s
-
-assert buf_rope.chars.to_s == buf_rope
-
-assert buf == buf_rope_with_str
-
-######################################
-#      BufferRope methods tests      #
-######################################
-
-assert buf_rope + buf_rope == buf_rope.concat(buf_rope)
-
-assert buf_rope == buf_rope.freeze
-
-######################################
-#      Rope.chars methods tests      #
-######################################
-
-assert buf_rope.chars[3] == 's'
-
-assert buf_rope.chars.index_of('k') == -1
-
-assert buf_rope.chars.index_of('s') == 3
-
-assert buf_rope.chars.count('s') == 4
-
-assert buf_rope.chars.last == '!'
-
-assert rope_uniq_test.chars.has_only('z')
-
-assert not not_rope_uniq_test.chars.has_only('z')
-
-assert (new BufferRope).chars.has_only('l')
-
-print buf_rope.to_lower
-
-print buf_rope.to_upper
-
-
index 1401821..82e2527 100644 (file)
@@ -15,9 +15,9 @@
 fun test(s: String)
 do
        print s.length
-       print s.first
-       print s.last
-       print s[2]
+       print s.chars.first
+       print s.chars.last
+       print s.chars[2]
        print s.substring(1, 2)
        print s.substring(-1, 2)
        print s.substring(1, 0)
index 94324a3..1b59ba8 100644 (file)
@@ -23,8 +23,8 @@ var i = 0
 while i < 5000 do
     var j = 0
     while j < s.length do
-        r.add(s[j])
-        r2.add(s[j])
+        r.add(s.chars[j])
+        r2.add(s.chars[j])
         j = j + 1
     end
     i = i + 1
index 9a576c7..9dee4a7 100644 (file)
@@ -17,5 +17,5 @@
 var a = "éè"
 print(a.length)
 for i in [0..a.length[ do
-       print("{i} is {a[i]} ({a[i].ascii})")
+       print("{i} is {a.chars[i]} ({a.chars[i].ascii})")
 end
index 28eb4f3..c2393aa 100644 (file)
@@ -34,10 +34,10 @@ print("has_suffix: {s.has_suffix(p)}")
 
 var test = "test"
 
-print("test[0] == 't' => {test[0] == 't'}")
-print("test[1] == 'e' => {test[1] == 'e'}")
-print("test[2] == 's' => {test[2] == 's'}")
-print("test[3] == 't' => {test[3] == 't'}")
+print("test[0] == 't' => {test.chars[0] == 't'}")
+print("test[1] == 'e' => {test.chars[1] == 'e'}")
+print("test[2] == 's' => {test.chars[2] == 's'}")
+print("test[3] == 't' => {test.chars[3] == 't'}")
 
 print("test.substring(0,1) == \"t\" => {test.substring(0,1) == "t"}")
 print("test.substring(0,2) == \"te\" => {test.substring(0,2) == "te"}")