Merge remote-tracking branch 'origin/master' into init_auto
authorJean Privat <jean@pryen.org>
Thu, 31 Mar 2016 17:43:26 +0000 (13:43 -0400)
committerJean Privat <jean@pryen.org>
Thu, 31 Mar 2016 17:43:26 +0000 (13:43 -0400)
1  2 
src/compiler/abstract_compiler.nit
src/interpreter/naive_interpreter.nit
src/modelize/modelize_property.nit
src/nitni/nitni_utilities.nit
src/semantize/typing.nit

@@@ -668,7 -668,9 +668,9 @@@ abstract class AbstractCompile
                self.header.add_decl("  #define be32toh(val) ((be16toh((val) << 16) | (be16toh((val) >> 16))))")
                self.header.add_decl("#endif")
                self.header.add_decl("#ifdef ANDROID")
-               self.header.add_decl("  #define be32toh(val) betoh32(val)")
+               self.header.add_decl("  #ifndef be32toh")
+               self.header.add_decl("          #define be32toh(val) betoh32(val)")
+               self.header.add_decl("  #endif")
                self.header.add_decl("  #include <android/log.h>")
                self.header.add_decl("  #define PRINT_ERROR(...) (void)__android_log_print(ANDROID_LOG_WARN, \"Nit\", __VA_ARGS__)")
                self.header.add_decl("#else")
@@@ -1162,6 -1164,29 +1164,6 @@@ abstract class AbstractCompilerVisito
        fun compile_callsite(callsite: CallSite, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
                if callsite.is_broken then return null
 -              var initializers = callsite.mpropdef.initializers
 -              if not initializers.is_empty then
 -                      var recv = arguments.first
 -
 -                      var i = 1
 -                      for p in initializers do
 -                              if p isa MMethod then
 -                                      var args = [recv]
 -                                      for x in p.intro.msignature.mparameters do
 -                                              args.add arguments[i]
 -                                              i += 1
 -                                      end
 -                                      self.send(p, args)
 -                              else if p isa MAttribute then
 -                                      self.write_attribute(p, recv, arguments[i])
 -                                      i += 1
 -                              else abort
 -                      end
 -                      assert i == arguments.length
 -
 -                      return self.send(callsite.mproperty, [recv])
 -              end
 -
                return self.send(callsite.mproperty, arguments)
        end
  
        # of runtime variables to use in the call.
        fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: RuntimeVariable, args: SequenceRead[AExpr]): Array[RuntimeVariable]
        do
 -              var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
 +              var msignature = mpropdef.msignature.as(not null)
                var res = new Array[RuntimeVariable]
                res.add(recv)
  
        do
                mtype = self.anchor(mtype)
                var valmtype = value.mcasttype
+               # Do nothing if useless autocast
                if valmtype.is_subtype(self.compiler.mainmodule, null, mtype) then
                        return value
                end
  
+               # Just as_not_null if the target is not nullable.
+               #
+               # eg `nullable PreciseType` adapted to `Object` gives precisetype.
                if valmtype isa MNullableType and valmtype.mtype.is_subtype(self.compiler.mainmodule, null, mtype) then
-                       var res = new RuntimeVariable(value.name, valmtype, valmtype.mtype)
-                       return res
-               else
-                       var res = new RuntimeVariable(value.name, valmtype, mtype)
-                       return res
+                       mtype = valmtype.mtype
                end
+               var res = new RuntimeVariable(value.name, value.mtype, mtype)
+               return res
        end
  
        # Generate a super call from a method definition
  
        # Checks
  
+       # Can value be null? (according to current knowledge)
+       fun maybenull(value: RuntimeVariable): Bool
+       do
+               return value.mcasttype isa MNullableType or value.mcasttype isa MNullType
+       end
        # Add a check and an abort for a null receiver if needed
        fun check_recv_notnull(recv: RuntimeVariable)
        do
                if self.compiler.modelbuilder.toolcontext.opt_no_check_null.value then return
  
-               var maybenull = recv.mcasttype isa MNullableType or recv.mcasttype isa MNullType
-               if maybenull then
+               if maybenull(recv) then
                        self.add("if (unlikely({recv} == NULL)) \{")
                        self.add_abort("Receiver is null")
                        self.add("\}")
@@@ -2021,6 -2055,8 +2032,8 @@@ redef class MMethodDe
                else if node isa AClassdef then
                        # Automatic free init is always inlined since it is empty or contains only attribtes assigments
                        return true
+               else if node == null then
+                       return true
                else
                        abort
                end
@@@ -3069,7 -3105,18 +3082,18 @@@ redef class AAttrPropde
                        v.assign(v.frame.returnvar.as(not null), res)
                else if mpropdef == mwritepropdef then
                        assert arguments.length == 2
-                       v.write_attribute(self.mpropdef.mproperty, arguments.first, arguments[1])
+                       var recv = arguments.first
+                       var arg = arguments[1]
+                       if is_optional and v.maybenull(arg) then
+                               var value = v.new_var(self.mpropdef.static_mtype.as(not null))
+                               v.add("if ({arg} == NULL) \{")
+                               v.assign(value, evaluate_expr(v, recv))
+                               v.add("\} else \{")
+                               v.assign(value, arg)
+                               v.add("\}")
+                               arg = value
+                       end
+                       v.write_attribute(self.mpropdef.mproperty, arguments.first, arg)
                        if is_lazy then
                                var ret = self.mtype
                                var useiset = not ret.is_c_primitive and not ret isa MNullableType
@@@ -3150,32 -3197,6 +3174,32 @@@ redef class AClassde
                                v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
                        end
                        return
 +              else if mclassdef.auto_init == mpropdef then
 +                      var recv = arguments.first
 +                      var initializers = mpropdef.initializers
 +                      var no_init = false
 +                      if not initializers.is_empty then
 +
 +                              var i = 1
 +                              for p in initializers do
 +                                      if p isa MMethod then
 +                                              var args = [recv]
 +                                              for x in p.intro.msignature.mparameters do
 +                                                      args.add arguments[i]
 +                                                      i += 1
 +                                              end
 +                                              v.send(p, args)
 +                                              if p.intro.is_calling_init then no_init = true
 +                                      else if p isa MAttribute then
 +                                              v.write_attribute(p, recv, arguments[i])
 +                                              i += 1
 +                                      else abort
 +                              end
 +                              assert i == arguments.length
 +
 +                      end
 +                      if not no_init then v.send(mclass.the_root_init_mmethod.as(not null), [recv])
 +                      return
                else
                        abort
                end
@@@ -3508,6 -3529,9 +3532,9 @@@ redef class AOrElseExp
        do
                var res = v.new_var(self.mtype.as(not null))
                var i1 = v.expr(self.n_expr, null)
+               if not v.maybenull(i1) then return i1
                v.add("if ({i1}!=NULL) \{")
                v.assign(res, i1)
                v.add("\} else \{")
@@@ -3537,7 -3561,11 +3564,11 @@@ redef class AFloatExp
  end
  
  redef class ACharExpr
-       redef fun expr(v) do return v.char_instance(self.value.as(not null))
+       redef fun expr(v) do
+               if is_ascii then return v.byte_instance(value.as(not null).ascii)
+               if is_code_point then return v.int_instance(value.as(not null).code_point)
+               return v.char_instance(self.value.as(not null))
+       end
  end
  
  redef class AArrayExpr
@@@ -3690,7 -3718,7 +3721,7 @@@ redef class AAsNotnullExp
                var i = v.expr(self.n_expr, null)
                if v.compiler.modelbuilder.toolcontext.opt_no_check_assert.value then return i
  
-               if i.mtype.is_c_primitive then return i
+               if not v.maybenull(i) then return i
  
                v.add("if (unlikely({i} == NULL)) \{")
                v.add_abort("Cast failed")
@@@ -437,7 -437,7 +437,7 @@@ class NaiveInterprete
        # Return `null` if one of the evaluation of the arguments return null.
        fun varargize(mpropdef: MMethodDef, map: nullable SignatureMap, recv: Instance, args: SequenceRead[AExpr]): nullable Array[Instance]
        do
 -              var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null)
 +              var msignature = mpropdef.msignature.as(not null)
                var res = new Array[Instance]
                res.add(recv)
  
        fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
        do
                if callsite == null then return null
 -              var initializers = callsite.mpropdef.initializers
 -              if not initializers.is_empty then
 -                      var recv = arguments.first
 -                      var i = 1
 -                      for p in initializers do
 -                              if p isa MMethod then
 -                                      var args = [recv]
 -                                      for x in p.intro.msignature.mparameters do
 -                                              args.add arguments[i]
 -                                              i += 1
 -                                      end
 -                                      self.send(p, args)
 -                              else if p isa MAttribute then
 -                                      assert recv isa MutableInstance
 -                                      write_attribute(p, recv, arguments[i])
 -                                      i += 1
 -                              else abort
 -                      end
 -                      assert i == arguments.length
 -
 -                      return send(callsite.mproperty, [recv])
 -              end
                return send(callsite.mproperty, arguments)
        end
  
@@@ -1475,7 -1497,12 +1475,12 @@@ redef class AAttrPropde
                        return evaluate_expr(v, recv, f)
                else if mpropdef == mwritepropdef then
                        assert args.length == 2
-                       v.write_attribute(attr, recv, args[1])
+                       var arg = args[1]
+                       if is_optional and arg.mtype isa MNullType then
+                               var f = v.new_frame(self, mpropdef, args)
+                               arg = evaluate_expr(v, recv, f)
+                       end
+                       v.write_attribute(attr, recv, arg)
                        return null
                else
                        abort
@@@ -1541,31 -1568,6 +1546,31 @@@ redef class AClassde
                                v.call(superpd, arguments)
                        end
                        return null
 +              else if mclassdef.auto_init == mpropdef then
 +                      var recv = arguments.first
 +                      var initializers = mpropdef.initializers
 +                      var no_init = false
 +                      if not initializers.is_empty then
 +                              var i = 1
 +                              for p in initializers do
 +                                      if p isa MMethod then
 +                                              var args = [recv]
 +                                              for x in p.intro.msignature.mparameters do
 +                                                      args.add arguments[i]
 +                                                      i += 1
 +                                              end
 +                                              v.send(p, args)
 +                                              if p.intro.is_calling_init then no_init = true
 +                                      else if p isa MAttribute then
 +                                              assert recv isa MutableInstance
 +                                              v.write_attribute(p, recv, arguments[i])
 +                                              i += 1
 +                                      else abort
 +                              end
 +                              assert i == arguments.length
 +                      end
 +                      if not no_init then v.send(mclass.the_root_init_mmethod.as(not null), [recv])
 +                      return null
                else
                        abort
                end
@@@ -1836,7 -1838,13 +1841,13 @@@ redef class AWithExp
                v.callsite(method_start, [expr])
                v.stmt(self.n_block)
                v.is_escape(self.break_mark) # Clear the break
+               # Execute the finally without an escape
+               var old_mark = v.escapemark
+               v.escapemark = null
                v.callsite(method_finish, [expr])
+               # Restore the escape unless another escape was provided
+               if v.escapemark == null then v.escapemark = old_mark
        end
  end
  
@@@ -1932,6 -1940,8 +1943,8 @@@ en
  redef class ACharExpr
        redef fun expr(v)
        do
+               if is_ascii then return v.byte_instance(self.value.as(not null).ascii)
+               if is_code_point then return v.int_instance(self.value.as(not null).code_point)
                return v.char_instance(self.value.as(not null))
        end
  end
@@@ -55,9 -55,10 +55,9 @@@ redef class ModelBuilde
                        toolcontext.run_phases_on_npropdef(res)
                        return res
                end
 -              if mpropdef isa MMethodDef and mpropdef.mproperty.is_root_init then
 -                      res = mclassdef2nclassdef.get_or_null(mpropdef.mclassdef)
 -                      if res != null then return res
 -              end
 +              # Fall back to the class node if any.
 +              res = mclassdef2nclassdef.get_or_null(mpropdef.mclassdef)
 +              if res != null then return res
                return null
        end
  
                        var mparameters = new Array[MParameter]
                        var msignature = new MSignature(mparameters, null)
                        mpropdef.msignature = msignature
                        mprop.is_init = true
                        self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
                        the_root_init_mmethod = mprop
 -                      return
                end
  
                # Is there already a constructor defined?
                        if mpropdef.mproperty.is_root_init then
                                assert defined_init == null
                                defined_init = mpropdef
 -                      else if mpropdef.mproperty.name == "init" then
 +                      else if mpropdef.mproperty.name == "autoinit" then
                                # An explicit old-style init named "init", so return
                                return
                        end
                end
  
 +              if mclassdef.auto_init != null then
 +                      return
 +              end
 +
                if not nclassdef isa AStdClassdef then return
  
                # Collect undefined attributes
                                        mreadpropdef.mproperty.is_autoinit = true
                                        continue
                                end
-                               if npropdef.has_value then continue
-                               var paramname = mreadpropdef.mproperty.name
-                               var ret_type = msignature.return_mtype
-                               if ret_type == null then return
-                               var mparameter = new MParameter(paramname, ret_type, false)
-                               mparameters.add(mparameter)
+                               if npropdef.has_value and not npropdef.is_optional then continue
                                var msetter = npropdef.mwritepropdef
                                if msetter == null then
                                        # No setter, it is a readonly attribute, so just add it
+                                       var paramname = mreadpropdef.mproperty.name
+                                       var ret_type = msignature.return_mtype
+                                       if ret_type == null then return
+                                       var mparameter = new MParameter(paramname, ret_type, false)
+                                       mparameters.add(mparameter)
                                        initializers.add(npropdef.mpropdef.mproperty)
                                        npropdef.mpropdef.mproperty.is_autoinit = true
                                else
                                        # Add the setter to the list
+                                       mparameters.add_all msetter.msignature.mparameters
                                        initializers.add(msetter.mproperty)
                                        msetter.mproperty.is_autoinit = true
                                end
                if the_root_init_mmethod == null then return
  
                # Look for most-specific new-stype init definitions
 -              var spropdefs = the_root_init_mmethod.lookup_super_definitions(mclassdef.mmodule, mclassdef.bound_mtype)
 -              if spropdefs.is_empty then
 -                      toolcontext.error(nclassdef.location, "Error: `{mclassdef}` does not specialize `{the_root_init_mmethod.intro_mclassdef}`. Possible duplication of the root class `Object`?")
 -                      return
 +              var spropdefs = new ArraySet[MMethodDef]
 +              for x in mclassdef.in_hierarchy.direct_greaters do
 +                      var y = x.mclass.intro.auto_init
 +                      if y == null then continue
 +                      if y.is_broken or y.msignature == null then return
 +                      spropdefs.add y
                end
  
                # Look at the autoinit class-annotation
                                        abort
                                end
                        end
 -              else
 +              else if spropdefs.not_empty then
 +                      # Search for inherited manual autoinit
 +                      var manual = null
 +                      for s in spropdefs do
 +                              if mpropdef2npropdef.has_key(s) then
 +                                      self.toolcontext.info("{mclassdef} inherits a manual autoinit {s}", 3)
 +                                      #mclassdef.autoinit = s
 +                                      #return
 +                                      manual = s
 +                              end
 +                      end
 +
                        # Search the longest-one and checks for conflict
                        var longest = spropdefs.first
                        if spropdefs.length > 1 then
                                # part 1. find the longest list
                                for spd in spropdefs do
                                        if spd.initializers.length > longest.initializers.length then longest = spd
 +                                      if spd != manual and manual != null then
 +                                              self.toolcontext.info("{mclassdef} conflict between manual autoinit {manual} and automatic autoinit {spd}.", 3)
 +                                      end
 +                              end
 +                              # conflict with manual autoinit?
 +                              if longest != manual and manual != null then
 +                                      self.error(nclassdef, "Error: conflict between manual autoinit {manual} and automatic autoinit {longest}.")
                                end
                                # part 2. compare
                                # Check for conflict in the order of initializers
                                mparameters.clear
                                initializers.clear
                        else
 -                              # Can we just inherit?
 -                              if spropdefs.length == 1 and mparameters.is_empty and defined_init == null then
 -                                      self.toolcontext.info("{mclassdef} inherits the basic constructor {longest}", 3)
 -                                      mclassdef.mclass.root_init = longest
 -                                      return
 -                              end
 -
                                # Combine the inherited list to what is collected
                                if longest.initializers.length > 0 then
 -                                      mparameters.prepend longest.new_msignature.mparameters
 +                                      mparameters.prepend longest.msignature.mparameters
                                        initializers.prepend longest.initializers
                                end
                        end
                end
  
 -              # If we already have a basic init definition, then setup its initializers
 -              if defined_init != null then
 -                      defined_init.initializers.add_all(initializers)
 +              # Create a specific new autoinit constructor
 +              do
 +                      var mprop = new MMethod(mclassdef, "autoinit", public_visibility)
 +                      mprop.is_init = true
 +                      var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
 +                      mpropdef.initializers.add_all(initializers)
                        var msignature = new MSignature(mparameters, null)
 -                      defined_init.new_msignature = msignature
 -                      self.toolcontext.info("{mclassdef} extends its basic constructor signature to {defined_init}{msignature}", 3)
 -                      mclassdef.mclass.root_init = defined_init
 -                      return
 +                      mpropdef.msignature = msignature
 +                      mclassdef.auto_init = mpropdef
 +                      self.toolcontext.info("{mclassdef} gets a free auto constructor `{mpropdef}{msignature}`. {spropdefs}", 3)
 +                      #mclassdef.mclass.root_init = mpropdef
 +                      mclassdef.mclass.the_root_init_mmethod = the_root_init_mmethod
                end
 -
 -              # Else create the local implicit basic init definition
 -              var mprop = the_root_init_mmethod
 -              var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
 -              mpropdef.has_supercall = true
 -              mpropdef.initializers.add_all(initializers)
 -              var msignature = new MSignature(mparameters, null)
 -              mpropdef.new_msignature = msignature
 -              mpropdef.msignature = new MSignature(new Array[MParameter], null) # always an empty real signature
 -              self.toolcontext.info("{mclassdef} gets a free constructor for attributes {mpropdef}{msignature}", 3)
 -              mclassdef.mclass.root_init = mpropdef
        end
  
        # Check the visibility of `mtype` as an element of the signature of `mpropdef`.
@@@ -497,15 -492,11 +499,15 @@@ en
  
  redef class MClass
        # The base init of the class.
 -      # Used to get the common new_msignature and initializers
        #
        # TODO: Where to put this information is not clear because unlike other
        # informations, the initialisers are stable in a same class.
        var root_init: nullable MMethodDef = null
 +
 +      # The base init of the class.
 +      #
 +      # TODO: merge with `root_init` and `ModelBuilder::the_root_init_mmethod` if possible
 +      var the_root_init_mmethod: nullable MMethod = null
  end
  
  redef class MClassDef
@@@ -598,7 -589,7 +600,7 @@@ redef class APropde
                        var mdoc = ndoc.to_mdoc
                        mpropdef.mdoc = mdoc
                        mdoc.original_mentity = mpropdef
-               else if mpropdef.is_intro and mpropdef.mproperty.visibility >= protected_visibility then
+               else if mpropdef.is_intro and mpropdef.mproperty.visibility >= protected_visibility and mpropdef.name != "new" then
                        modelbuilder.advice(self, "missing-doc", "Documentation warning: Undocumented property `{mpropdef.mproperty}`")
                end
  
@@@ -789,9 -780,6 +791,9 @@@ redef class AMethPropde
                        else if n_kwinit != null then
                                name = "init"
                                name_node = n_kwinit
 +                              if self.n_signature.n_params.not_empty or get_single_annotation("old_style_init", modelbuilder) != null then
 +                                      name = "autoinit"
 +                              end
                        else if n_kwnew != null then
                                name = "new"
                                name_node = n_kwnew
  
                var look_like_a_root_init = look_like_a_root_init(modelbuilder, mclassdef)
                var mprop: nullable MMethod = null
 -              if not is_init or n_kwredef != null then mprop = modelbuilder.try_get_mproperty_by_name(name_node, mclassdef, name).as(nullable MMethod)
 +              if not is_init or n_kwredef != null or look_like_a_root_init then mprop = modelbuilder.try_get_mproperty_by_name(name_node, mclassdef, name).as(nullable MMethod)
                if mprop == null and look_like_a_root_init then
                        mprop = modelbuilder.the_root_init_mmethod
                        var nb = n_block
                mclassdef.mprop2npropdef[mprop] = self
  
                var mpropdef = new MMethodDef(mclassdef, mprop, self.location)
 +              if mprop.name == "autoinit" and mclassdef.is_intro then
 +                      assert mclassdef.auto_init == null
 +                      mclassdef.auto_init = mpropdef
 +                      if mpropdef.is_intro then
 +                              mpropdef.initializers.add mprop
 +                              mpropdef.is_calling_init = true
 +                      end
 +              end
  
                set_doc(mpropdef, modelbuilder)
  
                        var root_init = mclassdef.mclass.root_init
                        if root_init != null then
                                # Inherit the initializers by refinement
 -                              mpropdef.new_msignature = root_init.new_msignature
                                assert mpropdef.initializers.is_empty
                                mpropdef.initializers.add_all root_init.initializers
                        end
@@@ -1175,6 -1156,9 +1177,9 @@@ redef class AAttrPropde
        # Is the node tagged lazy?
        var is_lazy = false
  
+       # Is the node tagged optional?
+       var is_optional = false
        # Has the node a default value?
        # Could be through `n_expr` or `n_block`
        var has_value = false
                        self.mlazypropdef = mlazypropdef
                end
  
+               var atoptional = self.get_single_annotation("optional", modelbuilder)
+               if atoptional != null then
+                       if not has_value then
+                               modelbuilder.error(atoptional, "Error: `optional` attributes need a default value.")
+                       end
+                       is_optional = true
+               end
                var atreadonly = self.get_single_annotation("readonly", modelbuilder)
                if atreadonly != null then
                        if not has_value then
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Float")
                                        if cla != null then mtype = cla.mclass_type
                                else if nexpr isa ACharExpr then
-                                       var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+                                       var cla: nullable MClass
+                                       if nexpr.is_ascii then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Byte")
+                                       else if nexpr.is_code_point then
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Int")
+                                       else
+                                               cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Char")
+                                       end
                                        if cla != null then mtype = cla.mclass_type
                                else if nexpr isa ABoolExpr then
                                        var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bool")
  
                var mwritepropdef = self.mwritepropdef
                if mwritepropdef != null then
+                       var mwritetype = mtype
+                       if is_optional then
+                               mwritetype = mwritetype.as_nullable
+                       end
                        var name: String
                        name = n_id2.text
-                       var mparameter = new MParameter(name, mtype, false)
+                       var mparameter = new MParameter(name, mwritetype, false)
                        var msignature = new MSignature([mparameter], null)
                        mwritepropdef.msignature = msignature
                end
@@@ -19,7 -19,7 +19,7 @@@ import nitni_bas
  
  redef class MMethod
        # Build a C function name for the FFI implementation (uses friendly naming).
-       # * On a specific static receiver mype `recv_mtype` 
+       # * On a specific static receiver type `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
@@@ -28,7 -28,7 +28,7 @@@
        do
                var cname
                if self.is_init then
 -                      if self.name == "init" or self.name == "new" then
 +                      if self.name == "init" or self.name == "new" or self.name == "autoinit" then
                                cname = "new_{recv_mtype.mangled_cname}"
                        else
                                cname = "new_{recv_mtype.mangled_cname}_{self.short_cname}"
  
                if suffix != null then cname = "{cname}{suffix}"
  
-               if length.long then cname = "{from_mmodule.name}___{cname}"
+               if length.long then cname = "{from_mmodule.c_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` 
+       # * On a specific static receiver type `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
@@@ -83,7 -83,7 +83,7 @@@
        end
  
        # Build a C function call for the FFI implementation (uses friendly naming).
-       # * On a specific static receiver mype `recv_mtype` 
+       # * On a specific static receiver type `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
diff --combined src/semantize/typing.nit
@@@ -152,7 -152,11 +152,11 @@@ private class TypeVisito
                        end
                        return null # forward error
                end
-               self.error(nexpr, "Error: expected an expression.")
+               var more_message = null
+               var p = nexpr.parent
+               if p != null then more_message = p.bad_expr_message(nexpr)
+               if more_message == null then more_message = "" else more_message = " " + more_message
+               self.error(nexpr, "Error: expected an expression{more_message}.")
                return null
        end
  
  
                var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
                if name == "new" and mproperty == null then
 -                      name = "init"
 +                      name = "autoinit"
                        mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
 +                      if mproperty == null then
 +                              name = "init"
 +                              mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
 +                      end
                end
  
                if mproperty == null then
                end
  
  
 -              var msignature = mpropdef.new_msignature or else mpropdef.msignature
 +              var msignature = mpropdef.msignature
                if msignature == null then return null # skip error
                msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature)
  
@@@ -806,6 -806,12 +810,12 @@@ en
  
  redef class ANode
        private fun accept_post_typing(v: TypeVisitor) do end
+       # An additional information message to explain the role of a child expression.
+       #
+       # The point of the method is to allow some kind of double dispatch so the parent
+       # choose how to describe its children.
+       private fun bad_expr_message(child: AExpr): nullable String do return null
  end
  
  redef class AAttrPropdef
@@@ -1449,9 -1455,15 +1459,15 @@@ redef class AFloatExp
  end
  
  redef class ACharExpr
-       redef fun accept_typing(v)
-       do
-               var mclass = v.get_mclass(self, "Char")
+       redef fun accept_typing(v) do
+               var mclass: nullable MClass = null
+               if is_ascii then
+                       mclass = v.get_mclass(self, "Byte")
+               else if is_code_point then
+                       mclass = v.get_mclass(self, "Int")
+               else
+                       mclass = v.get_mclass(self, "Char")
+               end
                if mclass == null then return # Forward error
                self.mtype = mclass.mclass_type
        end
@@@ -1585,7 -1597,7 +1601,7 @@@ redef class ARangeExp
                # get the constructor
                var callsite
                if self isa ACrangeExpr then
 -                      callsite = v.get_method(self, mtype, "init", false)
 +                      callsite = v.get_method(self, mtype, "autoinit", false)
                else if self isa AOrangeExpr then
                        callsite = v.get_method(self, mtype, "without_last", false)
                else
@@@ -1714,6 -1726,14 +1730,14 @@@ redef class ASendExp
        # The property invoked by the send.
        var callsite: nullable CallSite
  
+       redef fun bad_expr_message(child)
+       do
+               if child == self.n_expr then
+                       return "to be the receiver of `{self.property_name}`"
+               end
+               return null
+       end
        redef fun accept_typing(v)
        do
                var nrecv = self.n_expr
@@@ -1908,7 -1928,7 +1932,7 @@@ redef class ABraReassignExp
  end
  
  redef class AInitExpr
 -      redef fun property_name do return "init"
 +      redef fun property_name do if n_args.n_exprs.is_empty then return "init" else return "autoinit"
        redef fun property_node do return n_kwinit
        redef fun compute_raw_arguments do return n_args.to_a
  end
@@@ -2008,7 -2028,7 +2032,7 @@@ redef class ASuperExp
                        return
                end
  
 -              var msignature = superprop.new_msignature or else superprop.msignature.as(not null)
 +              var msignature = superprop.msignature.as(not null)
                msignature = v.resolve_for(msignature, recvtype, true).as(MSignature)
  
                var callsite = new CallSite(hot_location, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)