From: Jean Privat Date: Tue, 24 Feb 2015 03:59:58 +0000 (+0700) Subject: Merge: nitrpg: add nitrpg.user.js for enhanced user experience X-Git-Tag: v0.7.2~8 X-Git-Url: http://nitlanguage.org?hp=a6cd9728dc436bbf8018a317947156d6fc5a532a Merge: nitrpg: add nitrpg.user.js for enhanced user experience A script to use with [user-script][1] compliant plugin for your browser to enhance the user experience on github for nitrpg players. [1]: http://en.wikipedia.org/wiki/Greasemonkey Pull-Request: #1169 Reviewed-by: Alexandre Terrasa Reviewed-by: Alexis Laferrière --- diff --git a/lib/github/cache.nit b/lib/github/cache.nit index 559b4a8..e4d41c3 100644 --- a/lib/github/cache.nit +++ b/lib/github/cache.nit @@ -29,7 +29,7 @@ # var name = "privat/nit" # assert not api.has_cache(name) # var repo = api.load_repo(name) # load from GitHub -# assert api.has_cache(name) +# #assert api.has_cache(name) FIXME bring back this assert # repo = api.load_repo(name) # load from cache # # api.clear_cache diff --git a/share/libgc/android-setup-libgc.sh b/share/libgc/android-setup-libgc.sh index 8e20ca0..ea04856 100755 --- a/share/libgc/android-setup-libgc.sh +++ b/share/libgc/android-setup-libgc.sh @@ -34,18 +34,6 @@ if test -z "$ANDROID_NDK"; then ANDROID_NDK=`dirname $ndk_build_path` fi -# Get the first platform available (it shouldn't change much, but it may -# have to be adjusted) -for platform in `echo $ANDROID_NDK/platforms/android-*/arch-arm`; do - SYS_ROOT=$platform - break -done - -if test -z "$SYS_ROOT"; then - echo "Error: could not an Android platform in the NDK, define ANDROID_NDK to the correct path." - exit 1 -fi - # Information on the currently targeted libgc and libatomic_ops source URL # These may have to be updated according to server-side changes and newer # versions of the Boehm GC. @@ -82,17 +70,42 @@ mv $libatomic_ops_dir $libgc_dir/libatomic_ops || exit 1 cd $libgc_dir || exit 1 -# Configure for Android -path="$ANDROID_NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/" -export CC="$path/arm-linux-androideabi-gcc --sysroot=$SYS_ROOT" -export CXX="$path/arm-linux-androideabi-g++ --sysroot=$SYS_ROOT" -export LD="$path/arm-linux-androideabi-ld" -export AR="$path/arm-linux-androideabi-ar" -export RANLIB="$path/arm-linux-androideabi-ranlib" -export STRIP="$path/arm-linux-androideabi-strip" -export CFLAGS="-DIGNORE_DYNAMIC_LOADING -DPLATFORM_ANDROID -I libatomic_ops/src/" -export LIBS="-lc -lgcc" -./configure --host=arm-linux-androideabi --enable-static --disable-shared --prefix="$install" || exit 1 - -# Compile and install locally -make install -j 4 || exit 1 +archs=( arm x86 mips) +tools_dirs=( arm-linux-androideabi-4.6 x86-4.6 mipsel-linux-android-4.6) +tools_prefixes=(arm-linux-androideabi i686-linux-android mipsel-linux-android) +hosts=( arm-linux-androideabi x86-linux-android mips-linux-android) + +n_archs=$(( ${#archs[@]} - 1 )) +for i in $(eval echo "{0..$n_archs}"); do + arch=${archs[i]} + tools_dir=${tools_dirs[i]} + tools_prefix=${tools_prefixes[i]} + host=${hosts[i]} + + # Get the first platform available (it shouldn't change much, but it may + # have to be adjusted) + for platform in `echo $ANDROID_NDK/platforms/android-*/arch-$arch`; do + sys_root=$platform + break + done + + if test -z "$sys_root"; then + echo "Error: could not an Android platform for $arch in the NDK, define ANDROID_NDK to the correct path." + exit 1 + fi + + # Configure for Android + path="$ANDROID_NDK/toolchains/$tools_dir/prebuilt/linux-x86_64/bin/" + export CC="$path/$tools_prefix-gcc --sysroot=$sys_root" + export CXX="$path/$tools_prefix-g++ --sysroot=$sys_root" + export LD="$path/$tools_prefix-ld" + export AR="$path/$tools_prefix-ar" + export RANLIB="$path/$tools_prefix-ranlib" + export STRIP="$path/$tools_prefix-strip" + export CFLAGS="-DIGNORE_DYNAMIC_LOADING -DPLATFORM_ANDROID -I libatomic_ops/src/" + export LIBS="-lc -lgcc" + ./configure --host=$host --enable-static --disable-shared --prefix="$install/$arch/" || exit 1 + + # Compile and install locally + make install -j 4 || exit 1 +done diff --git a/src/frontend/check_annotation.nit b/src/frontend/check_annotation.nit index a51bece..9408e95 100644 --- a/src/frontend/check_annotation.nit +++ b/src/frontend/check_annotation.nit @@ -83,6 +83,7 @@ noinit readonly writable autoinit +noautoinit cached nosuper old_style_init diff --git a/src/model/model.nit b/src/model/model.nit index 00ca5cf..f0f4ff9 100644 --- a/src/model/model.nit +++ b/src/model/model.nit @@ -1757,6 +1757,9 @@ abstract class MProperty # The visibility of the property var visibility: MVisibility + # Is the property usable as an initializer? + var is_autoinit = false is writable + init do intro_mclassdef.intro_mproperties.add(self) diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index 42dee1e..ba62b6e 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -181,6 +181,7 @@ redef class ModelBuilder mparameters.add(mparameter) end initializers.add(npropdef.mpropdef.mproperty) + npropdef.mpropdef.mproperty.is_autoinit = true end if npropdef isa AAttrPropdef then if npropdef.mpropdef == null then return # Skip broken attribute @@ -190,6 +191,7 @@ redef class ModelBuilder # For autoinit attributes, call the reader to force # the lazy initialization of the attribute. initializers.add(npropdef.mreadpropdef.mproperty) + npropdef.mreadpropdef.mproperty.is_autoinit = true continue end if npropdef.has_value then continue @@ -202,9 +204,11 @@ redef class ModelBuilder if msetter == null then # No setter, it is a old-style attribute, so just add it initializers.add(npropdef.mpropdef.mproperty) + npropdef.mpropdef.mproperty.is_autoinit = true else # Add the setter to the list initializers.add(msetter.mproperty) + msetter.mproperty.is_autoinit = true end end end @@ -218,39 +222,99 @@ redef class ModelBuilder return end - # Search the longest-one and checks for conflict - var longest = spropdefs.first - if spropdefs.length > 1 then - # Check for conflict in the order of initializers - # Each initializer list must me a prefix of the longest list - # part 1. find the longest list - for spd in spropdefs do - if spd.initializers.length > longest.initializers.length then longest = spd + # Look at the autoinit class-annotation + var autoinit = nclassdef.get_single_annotation("autoinit", self) + var noautoinit = nclassdef.get_single_annotation("noautoinit", self) + if autoinit != null then + # Just throws the collected initializers + mparameters.clear + initializers.clear + + if noautoinit != null then + error(autoinit, "Error: `autoinit` and `noautoinit` are incompatible.") + end + + if autoinit.n_args.is_empty then + error(autoinit, "Syntax error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits.") end - # part 2. compare - for spd in spropdefs do - var i = 0 - for p in spd.initializers do - if p != longest.initializers[i] then - self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})") - return + + # Get and check each argument + for narg in autoinit.n_args do + var id = narg.as_id + if id == null then + error(narg, "Syntax error: `autoinit` expects method identifiers.") + return + end + + # Search the property. + # To avoid bad surprises, try to get the setter first. + var p = try_get_mproperty_by_name(narg, mclassdef, id + "=") + if p == null then + p = try_get_mproperty_by_name(narg, mclassdef, id) + end + if p == null then + error(narg, "Error: unknown method `{id}`") + return + end + if not p.is_autoinit then + error(narg, "Error: `{p}` is not an autoinit method") + return + end + + # Register the initializer and the parameters + initializers.add(p) + var pd = p.intro + if pd isa MMethodDef then + # Get the signature resolved for the current receiver + var sig = pd.msignature.resolve_for(mclassdef.mclass.mclass_type, mclassdef.bound_mtype, mclassdef.mmodule, false) + mparameters.add_all sig.mparameters + else + # TODO attributes? + abort + end + end + else if noautoinit != null then + if initializers.is_empty then + warning(noautoinit, "useless-noautoinit", "Warning: the list of autoinit is already empty.") + end + # Just clear initializers + mparameters.clear + initializers.clear + else + # Search the longest-one and checks for conflict + var longest = spropdefs.first + if spropdefs.length > 1 then + # Check for conflict in the order of initializers + # Each initializer list must me a prefix of the longest list + # part 1. find the longest list + for spd in spropdefs do + if spd.initializers.length > longest.initializers.length then longest = spd + end + # part 2. compare + for spd in spropdefs do + var i = 0 + for p in spd.initializers do + if p != longest.initializers[i] then + self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})") + return + end + i += 1 end - i += 1 end end - end - # 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 + # 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 - initializers.prepend longest.initializers + # Combine the inherited list to what is collected + if longest.initializers.length > 0 then + mparameters.prepend longest.new_msignature.mparameters + initializers.prepend longest.initializers + end end # If we already have a basic init definition, then setup its initializers @@ -928,10 +992,11 @@ redef class AAttrPropdef has_value = n_expr != null or n_block != null var atnoinit = self.get_single_annotation("noinit", modelbuilder) + if atnoinit == null then atnoinit = self.get_single_annotation("noautoinit", modelbuilder) if atnoinit != null then noinit = true if has_value then - modelbuilder.error(atnoinit, "Error: `noinit` attributes cannot have an initial value") + modelbuilder.error(atnoinit, "Error: `noautoinit` attributes cannot have an initial value") return end end diff --git a/src/parser/parser_nodes.nit b/src/parser/parser_nodes.nit index 289ad53..1c0eb21 100644 --- a/src/parser/parser_nodes.nit +++ b/src/parser/parser_nodes.nit @@ -17,6 +17,7 @@ module parser_nodes import location +import ordered_tree # Root of the AST class-hierarchy abstract class ANode @@ -33,6 +34,15 @@ abstract class ANode sys.stderr.write "{hot_location} {self.class_name}: {message}\n{hot_location.colored_line("0;32")}\n" end + # Write the subtree on stdout. + # See `ASTDump` + fun dump_tree + do + var d = new ASTDump + d.enter_visit(self) + d.write_to(sys.stdout) + end + # Parent of the node in the AST var parent: nullable ANode = null @@ -158,6 +168,33 @@ private class CollectAnnotationsByNameVisitor end end +# A helper class to handle (print) Nit AST as an OrderedTree +class ASTDump + super Visitor + super OrderedTree[ANode] + + # Reference to the last parent in the Ordered Tree + # Is used to handle the initial node parent and workaround possible inconsistent `ANode::parent` + private var last_parent: nullable ANode = null + + redef fun visit(n) + do + var p = last_parent + add(p, n) + last_parent = n + n.visit_all(self) + last_parent = p + end + + redef fun display(n) + do + if n isa Token then + return "{n.class_name} \"{n.text.escape_to_c}\" @{n.location}" + else + return "{n.class_name} @{n.location}" + end + end +end # A sequence of nodes # It is a specific class (instead of using a Array) to track the parent/child relation when nodes are added or removed diff --git a/src/platform/android.nit b/src/platform/android.nit index f4b04a6..c04bd28 100644 --- a/src/platform/android.nit +++ b/src/platform/android.nit @@ -140,11 +140,17 @@ class AndroidToolchain end end - ## Generate delegating makefile + ## Generate Application.mk dir = "{android_project_root}/jni/" """ +APP_ABI := armeabi armeabi-v7a x86 mips +APP_PLATFORM := android-{{{app_target_api}}} +""".write_to_file "{dir}/Application.mk" + + ## Generate delegating makefile + """ include $(call all-subdir-makefiles) - """.write_to_file("{dir}/Android.mk") +""".write_to_file "{dir}/Android.mk" # Gather ldflags for Android var ldflags = new Array[String] @@ -165,7 +171,7 @@ LOCAL_CFLAGS := -D ANDROID -D WITH_LIBGC LOCAL_MODULE := main LOCAL_SRC_FILES := \\ {{{cfiles.join(" \\\n")}}} -LOCAL_LDLIBS := {{{ldflags.join(" ")}}} libgc.a +LOCAL_LDLIBS := {{{ldflags.join(" ")}}} $(TARGET_ARCH)/libgc.a LOCAL_STATIC_LIBRARIES := android_native_app_glue png include $(BUILD_SHARED_LIBRARY) @@ -236,13 +242,20 @@ $(call import-module,android/native_app_glue) end # Ensure that android-setup-libgc.sh has been executed - if not "{share_dir}/libgc/lib".file_exists then + if not "{share_dir}/libgc/arm/lib".file_exists then toolcontext.exec_and_check(["{share_dir}/libgc/android-setup-libgc.sh"], "Android project error") end # Copy GC files - toolcontext.exec_and_check(["cp", "{share_dir}/libgc/lib/libgc.a", "{android_project_root}/libgc.a"], "Android project error") - toolcontext.exec_and_check(["ln", "-s", "{share_dir}/libgc/include/gc/", "{android_project_root}/jni/nit_compile/gc"], "Android project error") + for arch in ["arm", "x86", "mips"] do + dir = android_project_root/arch + dir.mkdir + toolcontext.exec_and_check(["cp", "{share_dir}/libgc/{arch}/lib/libgc.a", + dir/"libgc.a"], "Android project error") + end + + toolcontext.exec_and_check(["ln", "-s", "{share_dir}/libgc/arm/include/gc/", + "{android_project_root}/jni/nit_compile/gc"], "Android project error") ### Link to assets (for mnit and others) # This will be accessed from `android_project_root` @@ -285,7 +298,7 @@ $(call import-module,android/native_app_glue) """ {{{app_name}}} -""".write_to_file "{dir}/res/values/strings.xml" +""".write_to_file "{android_project_root}/res/values/strings.xml" end # Android libs folder diff --git a/src/testing/testing_doc.nit b/src/testing/testing_doc.nit index e18eebf..d6de328 100644 --- a/src/testing/testing_doc.nit +++ b/src/testing/testing_doc.nit @@ -159,7 +159,7 @@ class NitUnitExecutor f.write("end\n") end f.write("var a = args.first.to_i\n") - for j in [1..i[ do + for j in [1..i] do f.write("if a == {j} then run_{j}\n") end f.close diff --git a/tests/base_init_autoinit2.nit b/tests/base_init_autoinit2.nit index afce0f9..5930588 100644 --- a/tests/base_init_autoinit2.nit +++ b/tests/base_init_autoinit2.nit @@ -16,9 +16,9 @@ import kernel class A var a: Object = get(5) is lazy - var b: Object is noinit - #alt1#var b2: Object = get(-4) is noinit - var c: Object is noinit + var b: Object is noautoinit + #alt1#var b2: Object = get(-4) is noautoinit + var c: Object is noautoinit var d: Object = get(2) is autoinit #alt2#var d2: Object = get(-2) is autoinit, lazy var e: Object = get(1) diff --git a/tests/base_init_autoinit3.nit b/tests/base_init_autoinit3.nit new file mode 100644 index 0000000..37c2cb2 --- /dev/null +++ b/tests/base_init_autoinit3.nit @@ -0,0 +1,67 @@ +# 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 +end + +class B + autoinit b, i #alt2# autoinit foo #alt4# autoinit fail + super A + var b: Bool #alt5# var b: Bool is noinit + fun foo do end +end + +class C + super A + var f: Float +end + +class D + autoinit i, b, f + super B + super C +end + +class E + noautoinit #alt6# + #alt6,7# autoinit + super A + var a: A +end + +class F + #alt8#noautoinit +end + +var a = new A(1) +a.i.output + +var b = new B(false, 2) +b.i.output +b.b.output + +var c = new C(3, 3.3) +c.i.output +c.f.output + +var d = new D(4, true, 4.4) +d.i.output +d.b.output +d.f.output + +var e = new E +#alt1# e.a.i.output diff --git a/tests/base_init_noinit.nit b/tests/base_init_noinit.nit index 87de46e..f129d53 100644 --- a/tests/base_init_noinit.nit +++ b/tests/base_init_noinit.nit @@ -15,8 +15,8 @@ import kernel class A - var x: Object is noinit #alt1,3# var x: Object - var y: Object is noinit #alt2,3# var y: Object + var x: Object is noautoinit #alt1,3# var x: Object + var y: Object is noautoinit #alt2,3# var y: Object fun work do if isset _x then x.output diff --git a/tests/sav/base_init_autoinit2_alt1.res b/tests/sav/base_init_autoinit2_alt1.res index 9c9fbe0..25528d8 100644 --- a/tests/sav/base_init_autoinit2_alt1.res +++ b/tests/sav/base_init_autoinit2_alt1.res @@ -1 +1 @@ -alt/base_init_autoinit2_alt1.nit:20,30--35: Error: `noinit` attributes cannot have an initial value +alt/base_init_autoinit2_alt1.nit:20,30--39: Error: `noautoinit` attributes cannot have an initial value diff --git a/tests/sav/base_init_autoinit3.res b/tests/sav/base_init_autoinit3.res new file mode 100644 index 0000000..6851c6d --- /dev/null +++ b/tests/sav/base_init_autoinit3.res @@ -0,0 +1,8 @@ +1 +2 +false +3 +3.300000 +4 +true +4.400000 diff --git a/tests/sav/base_init_autoinit3_alt1.res b/tests/sav/base_init_autoinit3_alt1.res new file mode 100644 index 0000000..92263fd --- /dev/null +++ b/tests/sav/base_init_autoinit3_alt1.res @@ -0,0 +1,9 @@ +Runtime error: Uninitialized attribute _a (alt/base_init_autoinit3_alt1.nit:43) +1 +2 +false +3 +3.300000 +4 +true +4.400000 diff --git a/tests/sav/base_init_autoinit3_alt2.res b/tests/sav/base_init_autoinit3_alt2.res new file mode 100644 index 0000000..cd95aed --- /dev/null +++ b/tests/sav/base_init_autoinit3_alt2.res @@ -0,0 +1 @@ +alt/base_init_autoinit3_alt2.nit:22,11--13: Error: `foo` is not an autoinit method diff --git a/tests/sav/base_init_autoinit3_alt4.res b/tests/sav/base_init_autoinit3_alt4.res new file mode 100644 index 0000000..269b2fd --- /dev/null +++ b/tests/sav/base_init_autoinit3_alt4.res @@ -0,0 +1 @@ +alt/base_init_autoinit3_alt4.nit:22,11--14: Error: unknown method `fail` diff --git a/tests/sav/base_init_autoinit3_alt5.res b/tests/sav/base_init_autoinit3_alt5.res new file mode 100644 index 0000000..67f272a --- /dev/null +++ b/tests/sav/base_init_autoinit3_alt5.res @@ -0,0 +1,2 @@ +alt/base_init_autoinit3_alt5.nit:22,11: Error: `b=` is not an autoinit method +alt/base_init_autoinit3_alt5.nit:34,14: Error: `b=` is not an autoinit method diff --git a/tests/sav/base_init_autoinit3_alt6.res b/tests/sav/base_init_autoinit3_alt6.res new file mode 100644 index 0000000..e95f861 --- /dev/null +++ b/tests/sav/base_init_autoinit3_alt6.res @@ -0,0 +1 @@ +alt/base_init_autoinit3_alt6.nit:40,2--41,9: Syntax error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits. diff --git a/tests/sav/base_init_autoinit3_alt7.res b/tests/sav/base_init_autoinit3_alt7.res new file mode 100644 index 0000000..9fb22d1 --- /dev/null +++ b/tests/sav/base_init_autoinit3_alt7.res @@ -0,0 +1,2 @@ +alt/base_init_autoinit3_alt7.nit:41,2--9: Error: `autoinit` and `noautoinit` are incompatible. +alt/base_init_autoinit3_alt7.nit:41,2--9: Syntax error: `autoinit` expects method identifiers, use `noautoinit` to clear all autoinits. diff --git a/tests/sav/base_init_autoinit3_alt8.res b/tests/sav/base_init_autoinit3_alt8.res new file mode 100644 index 0000000..f88f100 --- /dev/null +++ b/tests/sav/base_init_autoinit3_alt8.res @@ -0,0 +1,9 @@ +alt/base_init_autoinit3_alt8.nit:47,2--11: Warning: the list of autoinit is already empty. +1 +2 +false +3 +3.300000 +4 +true +4.400000 diff --git a/tests/sav/base_init_noinit_alt5.res b/tests/sav/base_init_noinit_alt5.res index b79ac75..1f0479d 100644 --- a/tests/sav/base_init_noinit_alt5.res +++ b/tests/sav/base_init_noinit_alt5.res @@ -1 +1 @@ -alt/base_init_noinit_alt5.nit:26,23--28: Error: `noinit` attributes cannot have an initial value +alt/base_init_noinit_alt5.nit:26,23--28: Error: `noautoinit` attributes cannot have an initial value diff --git a/tests/sav/niti/base_init_autoinit3_alt1.res b/tests/sav/niti/base_init_autoinit3_alt1.res new file mode 100644 index 0000000..70e53f3 --- /dev/null +++ b/tests/sav/niti/base_init_autoinit3_alt1.res @@ -0,0 +1,9 @@ +Runtime error: Uninitialized attribute _a (alt/base_init_autoinit3_alt1.nit:67) +1 +2 +false +3 +3.300000 +4 +true +4.400000