From: Jean Privat Date: Sat, 23 Apr 2016 01:48:13 +0000 (-0400) Subject: Merge remote-tracking branch 'origin/master' into init_auto X-Git-Url: http://nitlanguage.org?hp=-c Merge remote-tracking branch 'origin/master' into init_auto --- a7613d08d2fddf71ce954e7cb441ba6274d5f43f diff --combined src/compiler/abstract_compiler.nit index d2f0b11,31dfcc4..7d2f983 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@@ -651,6 -651,8 +651,8 @@@ abstract class AbstractCompile self.header.add_decl("#include ") self.header.add_decl("#include ") self.header.add_decl("#include ") + # longjmp ! + self.header.add_decl("#include \n") self.header.add_decl("#include \n") self.header.add_decl("#include \n") self.header.add_decl("#include \n") @@@ -679,6 -681,7 +681,7 @@@ compile_header_structs compile_nitni_structs + compile_catch_stack var gccd_disable = modelbuilder.toolcontext.opt_no_gcc_directive.value if gccd_disable.has("noreturn") or gccd_disable.has("all") then @@@ -707,6 -710,17 +710,17 @@@ self.header.add_decl("extern val *glob_sys;") end + # Stack stocking environment for longjumps + protected fun compile_catch_stack do + self.header.add_decl """ + struct catch_stack_t { + int cursor; + jmp_buf envs[100]; + }; + extern struct catch_stack_t catchStack; + """ + end + # Declaration of structures for live Nit types protected fun compile_header_structs is abstract @@@ -790,6 -804,7 +804,7 @@@ extern void nitni_global_ref_decr( stru v.add_decl("int glob_argc;") v.add_decl("char **glob_argv;") v.add_decl("val *glob_sys;") + v.add_decl("struct catch_stack_t catchStack;") if self.modelbuilder.toolcontext.opt_typing_test_metrics.value then for tag in count_type_test_tags do @@@ -878,6 -893,7 +893,7 @@@ v.add("signal(SIGPIPE, SIG_IGN);") v.add("glob_argc = argc; glob_argv = argv;") + v.add("catchStack.cursor = -1;") v.add("initialize_gc_option();") v.add "initialize_nitni_global_refs();" @@@ -1164,6 -1180,29 +1180,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 @@@ -1186,7 -1225,7 +1202,7 @@@ # 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) @@@ -1588,6 -1627,18 +1604,18 @@@ return res end + # Generates a NativeString instance fully escaped in C-style \xHH fashion + fun native_string_instance(ns: NativeString, len: Int): RuntimeVariable do + var mtype = mmodule.native_string_type + var nat = new_var(mtype) + var byte_esc = new Buffer.with_cap(len * 4) + for i in [0 .. len[ do + byte_esc.append("\\x{ns[i].to_s.substring_from(2)}") + end + self.add("{nat} = \"{byte_esc}\";") + return nat + end + # Generate a string value fun string_instance(string: String): RuntimeVariable do @@@ -1696,6 -1747,9 +1724,9 @@@ # used by aborts, asserts, casts, etc. fun add_abort(message: String) do + self.add("if(catchStack.cursor >= 0)\{") + self.add("longjmp(catchStack.envs[catchStack.cursor], 1);") + self.add("\}") self.add("PRINT_ERROR(\"Runtime error: %s\", \"{message.escape_to_c}\");") add_raw_abort end @@@ -3174,32 -3228,6 +3205,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 @@@ -3362,8 -3390,19 +3393,19 @@@ en redef class ADoExpr redef fun stmt(v) do - v.stmt(self.n_block) - v.add_escape_label(break_mark) + if self.n_catch != null then + v.add("catchStack.cursor += 1;") + v.add("if(!setjmp(catchStack.envs[catchStack.cursor]))\{") + v.stmt(self.n_block) + v.add("catchStack.cursor -= 1;") + v.add("\}else \{") + v.add("catchStack.cursor -= 1;") + v.stmt(self.n_catch) + v.add("\}") + else + v.stmt(self.n_block) + end + v.add_escape_label(break_mark) end end @@@ -3589,14 -3628,75 +3631,75 @@@ redef class AArrayExp end end + redef class AugmentedStringFormExpr + # Factorize the making of a `Regex` object from a literal prefixed string + protected fun make_re(v: AbstractCompilerVisitor, rs: RuntimeVariable): nullable RuntimeVariable do + var re = to_re + assert re != null + var res = v.compile_callsite(re, [rs]) + if res == null then + print "Cannot call property `to_re` on {self}" + abort + end + for i in suffix.chars do + if i == 'i' then + var ign = ignore_case + assert ign != null + v.compile_callsite(ign, [res, v.bool_instance(true)]) + continue + end + if i == 'm' then + var nl = newline + assert nl != null + v.compile_callsite(nl, [res, v.bool_instance(true)]) + continue + end + if i == 'b' then + var ext = extended + assert ext != null + v.compile_callsite(ext, [res, v.bool_instance(false)]) + continue + end + # Should not happen, this needs to be updated + # along with the addition of new suffixes + abort + end + return res + end + end + redef class AStringFormExpr - redef fun expr(v) do return v.string_instance(self.value.as(not null)) + redef fun expr(v) do return v.string_instance(value) + end + + redef class AStringExpr + redef fun expr(v) do + var s = v.string_instance(value) + if is_string then return s + if is_bytestring then + var ns = v.native_string_instance(bytes.items, bytes.length) + var ln = v.int_instance(bytes.length) + var cs = to_bytes_with_copy + assert cs != null + var res = v.compile_callsite(cs, [ns, ln]) + assert res != null + s = res + else if is_re then + var res = make_re(v, s) + assert res != null + s = res + else + print "Unimplemented prefix or suffix for {self}" + abort + end + return s + end end redef class ASuperstringExpr redef fun expr(v) do - var type_string = mtype.as(not null) + var type_string = v.mmodule.string_type # Collect elements of the superstring var array = new Array[AExpr] @@@ -3650,10 -3750,14 +3753,14 @@@ # Fast join the native string to get the result var res = v.send(v.get_property("native_to_s", a.mtype), [a]) + assert res != null + + if is_re then res = make_re(v, res) # We finish to work with the native array, # so store it so that it can be reused v.add("{varonce} = {a};") + return res end end diff --combined src/interpreter/naive_interpreter.nit index cbc328a,0028df4..7389e2e --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@@ -113,17 -113,20 +113,20 @@@ class NaiveInterprete return self.modelbuilder.force_get_primitive_method(current_node, name, recv.mclass, self.mainmodule) end - # Is a return executed? - # Set this mark to skip the evaluation until the end of the specified method frame - var returnmark: nullable FRAME = null - - # Is a break or a continue executed? + # Is a return, a break or a continue executed? # Set this mark to skip the evaluation until a labeled statement catch it with `is_escape` var escapemark: nullable EscapeMark = null + # Is an abort being executed ? + # Set this mark to return to the last `catch` bloc or effectively aborting if there isn't any + var catch_mark = new EscapeMark + + # The count of `catch` blocs that have been encountered and can catch an abort + var catch_count = 0 + # Is a return or a break or a continue executed? # Use this function to know if you must skip the evaluation of statements - fun is_escaping: Bool do return returnmark != null or escapemark != null + fun is_escaping: Bool do return escapemark != null # The value associated with the current return/break/continue, if any. # Set the value when you set a escapemark. @@@ -328,6 -331,16 +331,16 @@@ return instance end + # Return a new native string initialized with `txt` + fun native_string_instance_from_ns(txt: NativeString, len: Int): Instance + do + var instance = native_string_instance_len(len) + var val = instance.val + txt.copy_to(val, len, 0, 0) + + return instance + end + # Return a new native string initialized of `length` fun native_string_instance_len(length: Int): PrimitiveInstance[NativeString] do @@@ -437,7 -450,7 +450,7 @@@ # 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) @@@ -569,6 -582,28 +582,6 @@@ 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 @@@ -816,10 -851,8 +829,8 @@@ redef class AMethPropde var f = v.new_frame(self, mpropdef, args) var res = call_commons(v, mpropdef, args, f) v.frames.shift - if v.returnmark == f then - v.returnmark = null + if v.is_escape(self.return_mark) then res = v.escapevalue - v.escapevalue = null return res end return res @@@ -980,9 -1013,6 +991,6 @@@ return v.int32_instance(recvval.to_i32) else if pname == "to_u32" then return v.uint32_instance(recvval.to_u32) - else if pname == "rand" then - var res = recvval.rand - return v.int_instance(res) end else if cname == "Byte" then var recvval = args[0].to_b @@@ -1108,8 -1138,6 +1116,6 @@@ return v.float_instance(args[0].to_f.log) else if pname == "pow" then return v.float_instance(args[0].to_f.pow(args[1].to_f)) - else if pname == "rand" then - return v.float_instance(args[0].to_f.rand) else if pname == "abs" then return v.float_instance(args[0].to_f.abs) else if pname == "hypot_with" then @@@ -1518,10 -1546,9 +1524,9 @@@ redef class AAttrPropde val = v.expr(nexpr) else if nblock != null then v.stmt(nblock) - assert v.returnmark == f + assert v.escapemark == return_mark val = v.escapevalue - v.returnmark = null - v.escapevalue = null + v.escapemark = null else abort end @@@ -1546,31 -1573,6 +1551,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 @@@ -1691,24 -1693,17 +1696,17 @@@ redef class AEscapeExp end end redef class AAbortExpr redef fun stmt(v) do - fatal(v, "Aborted") - exit(1) + # Abort as asked if there is no `catch` bloc + if v.catch_count <= 0 then + fatal(v, "Aborted") + exit(1) + else + # Abort mode, skipping everything until a `catch` bloc is reached + v.escapemark = v.catch_mark + end end end @@@ -1752,8 -1747,15 +1750,15 @@@ en redef class ADoExpr redef fun stmt(v) do + # If this bloc has a catch, register it in the counter + if self.n_catch != null then v.catch_count += 1 v.stmt(self.n_block) v.is_escape(self.break_mark) # Clear the break (if any) + if self.n_catch != null then + v.catch_count -= 1 + # Are we in abort mode? then this catch is executing + if v.is_escape(v.catch_mark) then v.stmt(self.n_catch) + end end end @@@ -1971,11 -1973,71 +1976,71 @@@ redef class AArrayExp end end + redef class AugmentedStringFormExpr + # Factorize the making of a `Regex` object from a literal prefixed string + fun make_re(v: NaiveInterpreter, rs: Instance): nullable Instance do + var tore = to_re + assert tore != null + var res = v.callsite(tore, [rs]) + if res == null then + print "Cannot call property `to_re` on {self}" + abort + end + for j in suffix.chars do + if j == 'i' then + var prop = ignore_case + assert prop != null + v.callsite(prop, [res, v.bool_instance(true)]) + continue + end + if j == 'm' then + var prop = newline + assert prop != null + v.callsite(prop, [res, v.bool_instance(true)]) + continue + end + if j == 'b' then + var prop = extended + assert prop != null + v.callsite(prop, [res, v.bool_instance(false)]) + continue + end + # Should not happen, this needs to be updated + # along with the addition of new suffixes + abort + end + return res + end + end + redef class AStringFormExpr - redef fun expr(v) - do - var txt = self.value.as(not null) - return v.string_instance(txt) + redef fun expr(v) do return v.string_instance(value) + end + + redef class AStringExpr + redef fun expr(v) do + var s = v.string_instance(value) + if is_string then return s + if is_bytestring then + var ns = v.native_string_instance_from_ns(bytes.items, bytes.length) + var ln = v.int_instance(bytes.length) + var prop = to_bytes_with_copy + assert prop != null + var res = v.callsite(prop, [ns, ln]) + if res == null then + print "Cannot call property `to_bytes` on {self}" + abort + end + s = res + else if is_re then + var res = make_re(v, s) + assert res != null + s = res + else + print "Unimplemented prefix or suffix for {self}" + abort + end + return s end end @@@ -1991,6 -2053,7 +2056,7 @@@ redef class ASuperstringExp var i = v.array_instance(array, v.mainmodule.object_type) var res = v.send(v.force_get_primitive_method("plain_to_s", i.mtype), [i]) assert res != null + if is_re then res = make_re(v, res) return res end end diff --combined src/modelize/modelize_property.nit index 59d725b,df8f8bd..8c167c6 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@@ -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 @@@ -150,9 -151,11 +150,9 @@@ 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? @@@ -163,16 -166,12 +163,16 @@@ 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 @@@ -229,12 -228,10 +229,12 @@@ 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 @@@ -288,31 -285,13 +288,31 @@@ 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 @@@ -345,27 -324,41 +345,27 @@@ 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`. @@@ -499,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 @@@ -791,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 @@@ -826,7 -812,7 +826,7 @@@ 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 @@@ -873,14 -859,6 +873,14 @@@ 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) @@@ -905,6 -883,7 +905,6 @@@ 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 @@@ -1427,7 -1406,16 +1427,16 @@@ redef class AAttrPropde var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String") if cla != null then mtype = cla.mclass_type else if nexpr isa AStringFormExpr then - var cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String") + var cla: nullable MClass + if nexpr.is_bytestring then + cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Bytes") + else if nexpr.is_re then + cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "Regex") + else if nexpr.is_string then + cla = modelbuilder.try_get_mclass_by_name(nexpr, mmodule, "String") + else + abort + end if cla != null then mtype = cla.mclass_type else modelbuilder.error(self, "Error: untyped attribute `{mreadpropdef}`. Implicit typing allowed only for literals and new.") diff --combined src/rapid_type_analysis.nit index 9624932,42a757b..5da1494 --- a/src/rapid_type_analysis.nit +++ b/src/rapid_type_analysis.nit @@@ -245,6 -245,7 +245,6 @@@ class RapidTypeAnalysi v.add_monomorphic_send(vararg, self.modelbuilder.force_get_primitive_method(node, "with_native", vararg.mclass, self.mainmodule)) end - # TODO? new_msignature var sig = msignature var osig = mmeth.intro.msignature.as(not null) for i in [0..sig.arity[ do @@@ -258,15 -259,9 +258,15 @@@ if npropdef isa AClassdef then if mmethoddef.mproperty.is_root_init then + # Final init call if not mmethoddef.is_intro then self.add_super_send(v.receiver, mmethoddef) end + else if mmethoddef.mclassdef.auto_init == mmethoddef then + # autoinit call + for i in mmethoddef.initializers do + if i isa MMethod then self.add_send(v.receiver, i) + end else npropdef.debug "cannot RTA {mmethoddef}" abort @@@ -590,6 -585,11 +590,11 @@@ redef class AStringFormExp v.add_type(native) var prop = v.get_method(native, "to_s_full") v.add_monomorphic_send(native, prop) + v.add_callsite(to_re) + v.add_callsite(ignore_case) + v.add_callsite(newline) + v.add_callsite(extended) + v.add_callsite(to_bytes_with_copy) end end diff --combined src/semantize/typing.nit index d0325cc,69329f9..5f4c2dc --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@@ -318,12 -318,8 +318,12 @@@ private class TypeVisito 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 @@@ -382,7 -378,7 +382,7 @@@ 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) @@@ -1135,6 -1131,7 +1135,7 @@@ redef class ADoExp redef fun accept_typing(v) do v.visit_stmt(n_block) + v.visit_stmt(n_catch) self.is_typed = true end end @@@ -1473,21 -1470,59 +1474,59 @@@ redef class ACharExp end end - redef class AStringFormExpr - redef fun accept_typing(v) - do + redef class AugmentedStringFormExpr + super AExpr + + # Text::to_re, used for prefix `re` + var to_re: nullable CallSite = null + # Regex::ignore_case, used for suffix `i` on `re` + var ignore_case: nullable CallSite = null + # Regex::newline, used for suffix `m` on `re` + var newline: nullable CallSite = null + # Regex::extended, used for suffix `b` on `re` + var extended: nullable CallSite = null + # NativeString::to_bytes_with_copy, used for prefix `b` + var to_bytes_with_copy: nullable CallSite = null + + redef fun accept_typing(v) do var mclass = v.get_mclass(self, "String") if mclass == null then return # Forward error - self.mtype = mclass.mclass_type + if is_bytestring then + to_bytes_with_copy = v.get_method(self, v.mmodule.native_string_type, "to_bytes_with_copy", false) + mclass = v.get_mclass(self, "Bytes") + else if is_re then + to_re = v.get_method(self, mclass.mclass_type, "to_re", false) + for i in suffix.chars do + mclass = v.get_mclass(self, "Regex") + if mclass == null then + v.error(self, "Error: `Regex` class unknown") + return + end + var service = "" + if i == 'i' then + service = "ignore_case=" + ignore_case = v.get_method(self, mclass.mclass_type, service, false) + else if i == 'm' then + service = "newline=" + newline = v.get_method(self, mclass.mclass_type, service, false) + else if i == 'b' then + service = "extended=" + extended = v.get_method(self, mclass.mclass_type, service, false) + else + v.error(self, "Type Error: Unrecognized suffix {i} in prefixed Regex") + abort + end + end + end + if mclass == null then return # Forward error + mtype = mclass.mclass_type end end redef class ASuperstringExpr redef fun accept_typing(v) do - var mclass = v.get_mclass(self, "String") - if mclass == null then return # Forward error - self.mtype = mclass.mclass_type + super var objclass = v.get_mclass(self, "Object") if objclass == null then return # Forward error var objtype = objclass.mclass_type @@@ -1601,7 -1636,7 +1640,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 @@@ -1932,7 -1967,7 +1971,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 @@@ -2032,7 -2067,7 +2071,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)