From: Jean Privat Date: Sat, 5 Mar 2016 23:14:34 +0000 (-0500) Subject: Merge: FFI: use more c_name and protect some macros for global compilation X-Git-Url: http://nitlanguage.org?hp=b3a9b5a30080d220d9edfb9b8c922882775135a1 Merge: FFI: use more c_name and protect some macros for global compilation Pull-Request: #1967 Reviewed-by: Jean Privat --- diff --git a/benchmarks/markdown/engines/nitmd/nitmd.nit b/benchmarks/markdown/engines/nitmd/nitmd.nit index 2db91b2..09c7d07 100644 --- a/benchmarks/markdown/engines/nitmd/nitmd.nit +++ b/benchmarks/markdown/engines/nitmd/nitmd.nit @@ -19,6 +19,7 @@ var n = args[1].to_i var str = file.to_path.read_all var parser = new MarkdownProcessor +parser.no_location = true for i in [1..n] do print parser.process(str) end diff --git a/lib/core/math.nit b/lib/core/math.nit index 36cf3fe..0f8325f 100644 --- a/lib/core/math.nit +++ b/lib/core/math.nit @@ -128,7 +128,7 @@ redef class Int # # assert 3.is_prime # assert not 1.is_prime - # assert not 12.is_prime + # assert not 15.is_prime fun is_prime: Bool do if self == 2 then @@ -136,7 +136,7 @@ redef class Int else if self <= 1 or self.is_even then return false end - for i in [3..self.sqrt[ do + for i in [3..self.sqrt] do if self % i == 0 then return false end return true diff --git a/lib/core/text/flat.nit b/lib/core/text/flat.nit index 47b8608..8081ecc 100644 --- a/lib/core/text/flat.nit +++ b/lib/core/text/flat.nit @@ -52,20 +52,25 @@ redef class FlatText fun char_to_byte_index(index: Int): Int do var dpos = index - _position var b = _bytepos + var its = _items - if dpos == 0 then return b if dpos == 1 then - b += _items.length_of_char_at(b) + if its[b] & 0x80u8 == 0x00u8 then + b += 1 + else + b += its.length_of_char_at(b) + end _bytepos = b _position = index return b end if dpos == -1 then - b = _items.find_beginning_of_char_at(b - 1) + b = its.find_beginning_of_char_at(b - 1) _bytepos = b _position = index return b end + if dpos == 0 then return b var ln = _length var pos = _position @@ -74,7 +79,6 @@ redef class FlatText var delta_end = (ln - 1) - index var delta_cache = (pos - index).abs var min = delta_begin - var its = _items if delta_cache < min then min = delta_cache if delta_end < min then min = delta_end @@ -292,7 +296,49 @@ redef class FlatText end redef fun [](index) do - assert index >= 0 and index < _length + var len = _length + + # Statistically: + # * ~70% want the next char + # * ~23% want the previous + # * ~7% want the same char + # + # So it makes sense to shortcut early. And early is here. + var dpos = index - _position + var b = _bytepos + if dpos == 1 and index < len - 1 then + var its = _items + var c = its[b] + if c & 0x80u8 == 0x00u8 then + # We want the next, and current is easy. + # So next is easy to find! + b += 1 + _position = index + _bytepos = b + # The rest will be done by `dpos==0` bellow. + dpos = 0 + end + else if dpos == -1 and index > 1 then + var its = _items + var c = its[b-1] + if c & 0x80u8 == 0x00u8 then + # We want the previous, and it is easy. + b -= 1 + dpos = 0 + _position = index + _bytepos = b + return c.ascii + end + end + if dpos == 0 then + # We know what we want (+0 or +1) just get it now! + var its = _items + var c = its[b] + if c & 0x80u8 == 0x00u8 then return c.ascii + return items.char_at(b) + end + + assert index >= 0 and index < len return fetch_char_at(index) end @@ -1250,6 +1296,10 @@ redef class NativeString # # Very unsafe, make sure to have room for this char prior to calling this function. private fun set_char_at(pos: Int, c: Char) do + if c.code_point < 128 then + self[pos] = c.code_point.to_b + return + end var ln = c.u8char_len native_set_char(pos, c, ln) end diff --git a/lib/markdown/markdown.nit b/lib/markdown/markdown.nit index 4c2428f..d63f3e4 100644 --- a/lib/markdown/markdown.nit +++ b/lib/markdown/markdown.nit @@ -133,6 +133,14 @@ class MarkdownProcessor # ~~~ var ext_mode = true + # Disable attaching MDLocation to Tokens + # + # Locations are useful for some tools but they may + # cause an important time and space overhead. + # + # Default = `false` + var no_location = false is writable + init do self.emitter = new MarkdownEmitter(self) # Process the mardown `input` string and return the processed output. @@ -397,11 +405,16 @@ class MarkdownProcessor c2 = ' ' end - var loc = new MDLocation( - current_loc.line_start, - current_loc.column_start + pos, - current_loc.line_start, - current_loc.column_start + pos) + var loc + if no_location then + loc = null + else + loc = new MDLocation( + current_loc.line_start, + current_loc.column_start + pos, + current_loc.line_start, + current_loc.column_start + pos) + end if c == '*' then if c1 == '*' then @@ -610,10 +623,12 @@ class MarkdownEmitter end # Append `c` to current buffer. - fun addc(c: Char) do add c.to_s + fun addc(c: Char) do + current_buffer.add c + end # Append a "\n" line break. - fun addn do add "\n" + fun addn do addc '\n' end # A Link Reference. @@ -1938,7 +1953,7 @@ end abstract class Token # Location of `self` in the original input. - var location: MDLocation + var location: nullable MDLocation # Position of `self` in input independant from lines. var pos: Int @@ -2330,18 +2345,11 @@ redef class Text if c == '\\' and pos + 1 < length then pos = escape(out, self[pos + 1], pos) else - var end_reached = false - for n in nend do - if c == n then - end_reached = true - break - end - end - if end_reached then break + for n in nend do if c == n then break label out.add c end pos += 1 - end + end label if pos == length then return -1 return pos end diff --git a/lib/markdown/test_markdown.nit b/lib/markdown/test_markdown.nit index 53c355f..8a2c7a0 100644 --- a/lib/markdown/test_markdown.nit +++ b/lib/markdown/test_markdown.nit @@ -2830,7 +2830,7 @@ class TestTokenProcessor redef fun token_at(input, pos) do var token = super if token isa TokenNone then return token - var res = "{token.class_name} at {token.location}" + var res = "{token.class_name} at {token.location or else "?"}" var exp = test_stack.shift print "" print "EXP {exp}" diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 347aa11..1fad40d 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -2046,6 +2046,8 @@ redef class MMethodDef 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 @@ -3094,7 +3096,18 @@ redef class AAttrPropdef 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 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 diff --git a/src/frontend/check_annotation.nit b/src/frontend/check_annotation.nit index d640ac2..5adcabd 100644 --- a/src/frontend/check_annotation.nit +++ b/src/frontend/check_annotation.nit @@ -84,6 +84,7 @@ lazy noinit readonly writable +optional autoinit noautoinit lateinit diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index bbe07d1..23d3ba1 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -1497,7 +1497,12 @@ redef class AAttrPropdef 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 diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index 03d9951..6588268 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -203,19 +203,21 @@ redef class ModelBuilder 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 @@ -1154,6 +1156,9 @@ redef class AAttrPropdef # 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 @@ -1250,6 +1255,14 @@ redef class AAttrPropdef 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 @@ -1421,9 +1434,13 @@ redef class AAttrPropdef 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 diff --git a/src/semantize/typing.nit b/src/semantize/typing.nit index aeb3b7e..ddc87e2 100644 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@ -152,7 +152,11 @@ private class TypeVisitor 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 @@ -802,6 +806,12 @@ end 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 @@ -1710,6 +1720,14 @@ redef class ASendExpr # 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 diff --git a/tests/base_attr_optional.nit b/tests/base_attr_optional.nit new file mode 100644 index 0000000..4417afe --- /dev/null +++ b/tests/base_attr_optional.nit @@ -0,0 +1,43 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import kernel + +class A + var i: Int = 99 is optional + + var o: Object = 999 is optional +end + +var a = new A +a.i.output +a.o.output + +a.i = 1 +a.o = 10 +a.i.output +a.o.output + +a.i = null +a.o = null +a.i.output +a.o.output + +a = new A(2) +a.i.output +a.o.output + +a = new A(3, true) +a.i.output +a.o.output diff --git a/tests/error_arg.nit b/tests/error_arg.nit new file mode 100644 index 0000000..c550d9f --- /dev/null +++ b/tests/error_arg.nit @@ -0,0 +1,39 @@ +# 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 core::kernel + +redef class Int + fun a: Int do return 10*self+self.abs +end + +fun foo(a: Int): Int do + a.output + return a +end +fun bar(a: Int) do a.output + +foo 1.a +foo(1.a) +foo (1).a +foo(1).a +foo((1).a) + +'\n'.output + +bar 1.a +bar(1.a) +#alt1#bar (1).a +#alt1#bar(1).a +bar((1).a) diff --git a/tests/sav/base_attr_optional.res b/tests/sav/base_attr_optional.res new file mode 100644 index 0000000..c879e94 --- /dev/null +++ b/tests/sav/base_attr_optional.res @@ -0,0 +1,10 @@ +99 +999 +1 +10 +99 +999 +2 +999 +3 +true diff --git a/tests/sav/base_meth_call_alt1.res b/tests/sav/base_meth_call_alt1.res index 5b14b4e..b2c999e 100644 --- a/tests/sav/base_meth_call_alt1.res +++ b/tests/sav/base_meth_call_alt1.res @@ -1 +1 @@ -alt/base_meth_call_alt1.nit:36,1--6: Error: expected an expression. +alt/base_meth_call_alt1.nit:36,1--6: Error: expected an expression to be the receiver of `output`. diff --git a/tests/sav/error_arg.res b/tests/sav/error_arg.res new file mode 100644 index 0000000..1aa7d08 --- /dev/null +++ b/tests/sav/error_arg.res @@ -0,0 +1,9 @@ +11 +11 +1 +1 +11 + +11 +11 +11 diff --git a/tests/sav/error_arg_alt1.res b/tests/sav/error_arg_alt1.res new file mode 100644 index 0000000..efe82e4 --- /dev/null +++ b/tests/sav/error_arg_alt1.res @@ -0,0 +1,2 @@ +alt/error_arg_alt1.nit:37,1--7: Error: expected an expression to be the receiver of `a`. +alt/error_arg_alt1.nit:38,1--6: Error: expected an expression to be the receiver of `a`. diff --git a/tests/sav/nitcg/test_text_stat.res b/tests/sav/nitcg/test_text_stat.res index 8fd2394..e28137f 100644 --- a/tests/sav/nitcg/test_text_stat.res +++ b/tests/sav/nitcg/test_text_stat.res @@ -9,37 +9,37 @@ Allocations, by type: -RopeBuffer = 0 Calls to length, by type: - FlatString = 23 (cache misses 5, 21.73%) + FlatString = 18 (cache misses 5, 27.77%) Indexed accesses, by type: - FlatString = 13 + FlatString = 8 Calls to bytelen for each type: FlatString = 61 Calls to position for each type: - FlatString = 27 + FlatString = 17 Calls to bytepos for each type: - FlatString = 14 -Calls to first_byte on FlatString 216 + FlatString = 9 +Calls to first_byte on FlatString 191 Calls to last_byte on FlatString 19 FlatStrings allocated with length 78 (86.813%) Length of travel for index distribution: -* null = 16 => occurences 80.0%, cumulative 80.0% -* 1 = 14 => occurences 35.0%, cumulative 75.0% +* null = 11 => occurences 73.333%, cumulative 73.333% +* 1 = 8 => occurences 27.586%, cumulative 65.517% Byte length of the FlatStrings created: * null = 6 => occurences 4.444%, cumulative 4.444% -* 1 = 21 => occurences 14.094%, cumulative 18.121% -* 2 = 33 => occurences 20.245%, cumulative 36.81% +* 1 = 24 => occurences 16.107%, cumulative 20.134% +* 2 = 30 => occurences 18.405%, cumulative 36.81% * 3 = 29 => occurences 16.292%, cumulative 50.0% -* 4 = 9 => occurences 4.663%, cumulative 50.777% -* 5 = 20 => occurences 9.615%, cumulative 56.731% -* 6 = 21 => occurences 9.417%, cumulative 62.332% +* 4 = 5 => occurences 2.591%, cumulative 48.705% +* 5 = 20 => occurences 9.615%, cumulative 54.808% +* 6 = 25 => occurences 11.211%, cumulative 62.332% * 9 = 1 => occurences 0.42%, cumulative 58.824% * 10 = 9 => occurences 3.557%, cumulative 58.893% * 11 = 2 => occurences 0.746%, cumulative 56.343% * 12 = 1 => occurences 0.355%, cumulative 53.901% * 13 = 1 => occurences 0.339%, cumulative 51.864% * 14 = 1 => occurences 0.325%, cumulative 50.0% -* 15 = 5 => occurences 1.558%, cumulative 49.533% -* 16 = 7 => occurences 2.083%, cumulative 49.405% +* 15 = 7 => occurences 2.181%, cumulative 50.156% +* 16 = 5 => occurences 1.488%, cumulative 49.405% * 17 = 1 => occurences 0.285%, cumulative 47.578% * 25 = 2 => occurences 0.549%, cumulative 46.429% * 26 = 1 => occurences 0.265%, cumulative 44.974% @@ -53,5 +53,5 @@ Byte length of the FlatStrings created: * 40 = 1 => occurences 0.207%, cumulative 37.19% * 43 = 1 => occurences 0.201%, cumulative 36.419% * 46 = 1 => occurences 0.196%, cumulative 35.686% -* 48 = 1 => occurences 0.191%, cumulative 34.99% -* 51 = 21 => occurences 3.918%, cumulative 38.06% +* 51 = 20 => occurences 3.824%, cumulative 38.623% +* 55 = 1 => occurences 0.186%, cumulative 37.732% diff --git a/tests/sav/test_text_stat.res b/tests/sav/test_text_stat.res index e320033..702e2b2 100644 --- a/tests/sav/test_text_stat.res +++ b/tests/sav/test_text_stat.res @@ -9,48 +9,49 @@ Allocations, by type: -RopeBuffer = 0 Calls to length, by type: - FlatString = 23 (cache misses 5, 21.73%) + FlatString = 18 (cache misses 5, 27.77%) Indexed accesses, by type: - FlatString = 13 + FlatString = 8 Calls to bytelen for each type: FlatString = 61 Calls to position for each type: - FlatString = 27 + FlatString = 17 Calls to bytepos for each type: - FlatString = 14 -Calls to first_byte on FlatString 216 + FlatString = 9 +Calls to first_byte on FlatString 191 Calls to last_byte on FlatString 19 FlatStrings allocated with length 78 (86.813%) Length of travel for index distribution: -* 0 = 16 => occurences 80.0%, cumulative 80.0% -* 1 = 14 => occurences 35.0%, cumulative 75.0% +* 0 = 11 => occurences 73.333%, cumulative 73.333% +* 1 = 8 => occurences 27.586%, cumulative 65.517% Byte length of the FlatStrings created: * 0 = 6 => occurences 4.478%, cumulative 4.478% -* 1 = 21 => occurences 14.189%, cumulative 18.243% -* 2 = 33 => occurences 20.37%, cumulative 37.037% +* 1 = 24 => occurences 16.216%, cumulative 20.27% +* 2 = 30 => occurences 18.519%, cumulative 37.037% * 3 = 29 => occurences 16.384%, cumulative 50.282% -* 4 = 7 => occurences 3.646%, cumulative 50.0% -* 5 = 20 => occurences 9.662%, cumulative 56.039% -* 6 = 21 => occurences 9.459%, cumulative 61.712% -* 9 = 1 => occurences 0.422%, cumulative 58.228% -* 10 = 9 => occurences 3.571%, cumulative 58.333% -* 11 = 2 => occurences 0.749%, cumulative 55.805% -* 12 = 1 => occurences 0.356%, cumulative 53.381% -* 13 = 1 => occurences 0.34%, cumulative 51.361% -* 14 = 1 => occurences 0.326%, cumulative 49.511% -* 15 = 5 => occurences 1.563%, cumulative 49.063% -* 16 = 7 => occurences 2.09%, cumulative 48.955% -* 17 = 1 => occurences 0.286%, cumulative 47.143% -* 25 = 2 => occurences 0.551%, cumulative 46.006% -* 26 = 1 => occurences 0.265%, cumulative 44.562% -* 31 = 2 => occurences 0.513%, cumulative 43.59% -* 32 = 1 => occurences 0.248%, cumulative 42.327% -* 33 = 1 => occurences 0.24%, cumulative 41.247% -* 34 = 2 => occurences 0.465%, cumulative 40.465% -* 35 = 1 => occurences 0.225%, cumulative 39.414% -* 37 = 1 => occurences 0.219%, cumulative 38.512% -* 39 = 1 => occurences 0.213%, cumulative 37.66% -* 40 = 1 => occurences 0.207%, cumulative 36.853% -* 43 = 1 => occurences 0.202%, cumulative 36.089% -* 46 = 1 => occurences 0.196%, cumulative 35.363% -* 48 = 3 => occurences 0.575%, cumulative 35.057% +* 4 = 3 => occurences 1.563%, cumulative 47.917% +* 5 = 20 => occurences 9.662%, cumulative 54.106% +* 6 = 26 => occurences 11.712%, cumulative 62.162% +* 9 = 1 => occurences 0.422%, cumulative 58.65% +* 10 = 9 => occurences 3.571%, cumulative 58.73% +* 11 = 2 => occurences 0.749%, cumulative 56.18% +* 12 = 1 => occurences 0.356%, cumulative 53.737% +* 13 = 1 => occurences 0.34%, cumulative 51.701% +* 14 = 1 => occurences 0.326%, cumulative 49.837% +* 15 = 7 => occurences 2.188%, cumulative 50.0% +* 16 = 5 => occurences 1.493%, cumulative 49.254% +* 17 = 1 => occurences 0.286%, cumulative 47.429% +* 25 = 2 => occurences 0.551%, cumulative 46.281% +* 26 = 1 => occurences 0.265%, cumulative 44.828% +* 31 = 2 => occurences 0.513%, cumulative 43.846% +* 32 = 1 => occurences 0.248%, cumulative 42.574% +* 33 = 1 => occurences 0.24%, cumulative 41.487% +* 34 = 2 => occurences 0.465%, cumulative 40.698% +* 35 = 1 => occurences 0.225%, cumulative 39.64% +* 37 = 1 => occurences 0.219%, cumulative 38.731% +* 39 = 1 => occurences 0.213%, cumulative 37.872% +* 40 = 1 => occurences 0.207%, cumulative 37.06% +* 43 = 1 => occurences 0.202%, cumulative 36.29% +* 46 = 1 => occurences 0.196%, cumulative 35.56% +* 51 = 14 => occurences 2.682%, cumulative 37.356% +* 52 = 5 => occurences 0.931%, cumulative 37.244%