Compare commits

..

90 Commits

Author SHA1 Message Date
Arfon Smith
9aa24a216a Merge pull request #2612 from github/cut-release-v4.5.15
Cut release v4.5.15
2015-09-01 21:04:40 +01:00
Arfon Smith
13702451ab Bumping to v4.5.15 2015-09-01 19:13:02 +01:00
Arfon Smith
f0242f6f97 Updating grammars 2015-09-01 19:12:27 +01:00
Arfon Smith
9775820398 Merge pull request #2591 from jtbandes/master
Vendored definitions for Xcode-related files
2015-09-01 18:53:08 +01:00
Arfon Smith
7daf26bcd0 Merge pull request #2604 from larsbrinkhoff/alphabetise-heuristics
Alphabetise heuristics.
2015-09-01 15:25:49 +01:00
Arfon Smith
231f705098 Merge pull request #2606 from thejameskyle/jsproj
Add .jsproj extension
2015-09-01 15:23:53 +01:00
Arfon Smith
893ab8fd8d Merge pull request #2610 from ismail-arilik/patch-1
Add color for the PL/SQL language.
2015-09-01 15:20:49 +01:00
ismail-arilik
5afdd2c533 Add color for the PL/SQL language.
I have added color to the PL/SQL language: #dad8d8. I take this color from a window background which evokes the interface of the language.
2015-09-01 14:23:59 +03:00
Lars Brinkhoff
e4f5c0066a Add checks to keep heuristics alphabetised. 2015-09-01 08:21:34 +02:00
James Kyle
9b8bf9068f Move jsproj example to xml directory 2015-08-31 11:35:01 -07:00
James Kyle
6e05edc350 Add .jsproj extension 2015-08-31 10:26:29 -07:00
Lars Brinkhoff
dd8eaf2893 Alphabetise heuristics. 2015-08-31 08:53:51 +02:00
Ben Balter
e24efad5ff Merge pull request #2594 from github/license-help
Add some additional help text to license test
2015-08-26 14:55:37 -04:00
Arfon Smith
58a34cdb7d Merge pull request #2589 from mandel/master
Add the X10 language.
2015-08-26 19:36:54 +01:00
Louis Mandel
b1c6b330e9 Switch to Apache License. 2015-08-26 14:26:30 -04:00
Ben Balter
7c3e265033 also add help for unapproved licenses 2015-08-26 12:31:29 -04:00
Louis Mandel
13695a716c Update X10 grammar license. 2015-08-26 09:46:02 -04:00
Ben Balter
c9e43804d6 add some help text to license test 2015-08-26 09:26:04 -04:00
Arfon Smith
1535e3553e Merge pull request #2580 from LeonaMorro/master
add *.lslp as an additional extension for LSL (LindenScriptingLanguage)
2015-08-26 14:09:48 +01:00
Arfon Smith
0ac05bbbeb Merge pull request #2582 from pchaigno/vendor-libraries
Vendored JS files
2015-08-26 14:02:57 +01:00
Arfon Smith
d3f979d640 Merge pull request #2592 from jtbandes/typo
Fix typo in Obj-C heuristic keyword
2015-08-26 12:52:05 +01:00
Jacob Bandes-Storch
0e9ded45dc Fix typo in Obj-C heuristic keyword
`synchronised` → `synchronized`
2015-08-26 00:34:00 -07:00
Jacob Bandes-Storch
a2ca886510 Vendored definitions for Xcode-related files 2015-08-25 23:42:20 -07:00
Louis Mandel
25a1af3775 Add the X10 language (http://x10-lang.org/). 2015-08-24 13:26:43 -04:00
Paul Chaignon
0d8e0a2970 Sublime Text workspace files as vendored 2015-08-24 12:32:26 +02:00
Paul Chaignon
c0fff6c8a8 Make Slick regexp more general 2015-08-21 12:30:01 +02:00
Paul Chaignon
e6b4428614 Tests for new vendored files 2015-08-21 12:24:04 +02:00
Paul Chaignon
4e6e69833d Test for new CodeMirror regexp 2015-08-21 12:15:17 +02:00
Paul Chaignon
1d9faff4c6 New JS vendored files 2015-08-21 12:13:42 +02:00
Paul Chaignon
7025cbe760 Fix CodeMirror regex for vendored files 2015-08-21 12:12:52 +02:00
LeonaMorro
e922b7c2ca added *.lslp to samples/LSL folder 2015-08-21 11:44:23 +02:00
LeonaMorro
96518d2d0f added *.lslp as LSL(Linden Scripting Language) 2015-08-21 11:17:12 +02:00
Arfon Smith
1241b20ba1 Merge pull request #2578 from blakeembrey/correct-raml-type
Make RAML a markup language
2015-08-20 20:56:21 +01:00
Ben Balter
f03f5c1628 Merge pull request #2568 from github/licensee
Use Licensee to classify submodule licenses
2015-08-20 15:42:50 -04:00
Ben Balter
cb550a3662 remove some random submodules 2015-08-20 15:30:51 -04:00
Ben Balter
d1f90d61c5 Merge branch 'master' into licensee 2015-08-20 15:25:15 -04:00
Blake Embrey
16e65fe189 Make RAML a markup language
RAML was originally merged as a data language, but this seems like an incorrect definition. I changed it to be markup instead, which will also result in RAML appearing in repo statistics.
2015-08-20 10:07:44 -07:00
Ben Balter
62a0faa729 let us 2015-08-20 12:23:52 -04:00
Ben Balter
fbb3ab2292 batch license test output 2015-08-20 11:38:31 -04:00
Arfon Smith
b3b75e5ef8 Merge pull request #2574 from github/perl-t
Adding Perl/Perl6 heuristic for '.t'
2015-08-20 10:29:52 +01:00
Arfon Smith
8b36210db5 Merge pull request #2573 from a0viedo/patch-1
relativize link in readme
2015-08-20 10:25:02 +01:00
Arfon Smith
a74f3b3e46 Adding Perl/Perl6 heuristic for '.t' 2015-08-20 10:16:52 +01:00
Alejandro Oviedo
e214a52de5 relativize link in readme
...so it could link properly in other branches and forks.
2015-08-19 19:15:05 -03:00
Arfon Smith
0624a9395c Merge pull request #2571 from pchaigno/prolog-grammar
New grammars for Prolog and ECLiPSe
2015-08-19 21:44:13 +01:00
Arfon Smith
b2e7f7ffa6 Merge pull request #2570 from pchaigno/typescript-grammar
New grammar for Typescript
2015-08-19 21:41:15 +01:00
Arfon Smith
b312b39a10 Merge pull request #2572 from pchaigno/rmarkdown-tmscope
TextMate scope for RMarkdown
2015-08-19 21:38:42 +01:00
Paul Chaignon
80e2d112b2 tm_scope for RMarkdown 2015-08-19 22:07:23 +02:00
Paul Chaignon
519b169df0 New grammar for Typescript from Sublime Text package 2015-08-19 21:30:24 +02:00
Paul Chaignon
5c2cfbc334 Remove Typescript grammar 2015-08-19 21:27:40 +02:00
Paul Chaignon
7d91e4959a Dissociate ECLiPSe from Prolog
ECLiPSe syntax is slightly different from Prolog syntax
ECLiPSe is in the Prolog group so it will only be highlighted differently
2015-08-19 20:56:14 +02:00
Paul Chaignon
0c5aa2a7eb Merge branch 'master' into prolog-grammar 2015-08-19 20:46:15 +02:00
Paul Chaignon
0d7a264981 Update submodule for Prolog grammar 2015-08-19 20:43:16 +02:00
Arfon Smith
52ff2d2e74 Merge pull request #2557 from pchaigno/mozilla-public-license
Recognize the Mozilla Public License for grammars
2015-08-19 19:21:33 +01:00
Ben Balter
8a7ceaa845 bump licensee to support ruby 1.9.3 2015-08-19 13:22:31 -04:00
Ben Balter
fd9ce2d1cf use licensee to classify submodule licenses 2015-08-19 12:54:21 -04:00
Arfon Smith
c7bab11ebe Merge pull request #2566 from github/cut-release-v4.5.14
v4.5.14 version bump
2015-08-19 10:36:52 +01:00
Arfon Smith
6995fc28b6 v4.5.14 version bump 2015-08-19 07:01:07 +01:00
Arfon Smith
102f14d0e9 Grammars update 2015-08-19 06:59:39 +01:00
Arfon Smith
aac168402b Merge pull request #2565 from pchaigno/aspectj-grammar
Grammar for AspectJ
2015-08-19 06:49:16 +01:00
Paul Chaignon
152d49513f Grammar for AspectJ from Sublime Text package 2015-08-19 00:11:34 +02:00
Arfon Smith
d5564c808d Merge pull request #2560 from larsbrinkhoff/sexp
Add .sexp to Common Lisp.
2015-08-18 21:15:46 +01:00
Lars Brinkhoff
82410e07b2 Add .sexp to Common Lisp.
config.sexp by Jeremie Dimino; Apache License 2.0.
rss.sexp by Dan Lentz; LGPL 2.1.
2015-08-18 12:45:47 +02:00
Arfon Smith
94d90b30b5 Merge pull request #2561 from pchaigno/labview-xml
Highlight LabVIEW files as XML
2015-08-18 12:25:38 +02:00
Paul Chaignon
06997f0da2 Fix scope of grammar for LabVIEW 2015-08-14 14:17:32 +02:00
Paul Chaignon
55aafa416d Highlight LabVIEW files as XML 2015-08-14 13:56:28 +02:00
Paul Chaignon
6226a46988 Recognize the Mozilla Public License for grammars 2015-08-13 17:35:01 +02:00
Paul Chaignon
8d216f0c43 Grammar for Prolog from Sublime Text package
MPLv2 License is currently unrecognized
2015-08-13 17:15:04 +02:00
Paul Chaignon
7f5bb25542 Remove grammar for Prolog from TextMate bundle 2015-08-13 16:56:21 +02:00
Arfon Smith
5fcdf6adc2 Merge pull request #2555 from larsbrinkhoff/zone
Add .arpa to DNS Zone.
2015-08-13 10:18:51 +01:00
Lars Brinkhoff
6a565a849b Add .arpa to DNS Zone.
sample.arpa by Freeswitch project; Mozilla Public License 1.1.
2015-08-13 07:38:17 +02:00
Arfon Smith
66fc67e34c Merge pull request #2554 from github/mcandre-master
DNS Zone files
2015-08-12 18:54:04 +01:00
Arfon Smith
7cf140940e Fixing up the build 2015-08-12 17:20:29 +01:00
Arfon Smith
60e90bab23 Removing un-used Bind bundle 2015-08-12 17:06:39 +01:00
Arfon Smith
4f58258186 Removing erroneous submodule 2015-08-12 17:05:57 +01:00
Arfon Smith
03e2904ebf Merge branch 'master' of https://github.com/mcandre/linguist into mcandre-master 2015-08-12 15:15:28 +01:00
Andrew Pennebaker
bea90b256e use st2-zonefile (MIT licensed) instead of Bind.tmbundle (unlicensed) 2015-08-11 14:01:45 -05:00
Arfon Smith
8eb37ba956 Merge pull request #2541 from github/reworking-documentation-paths
Reworking documentation paths
2015-08-11 09:44:19 +01:00
Arfon Smith
8d20c1fb59 More inclusive documentation matches for License and Readme files 2015-08-11 09:39:41 +01:00
Arfon Smith
9a1abf0c49 Merge branch 'master' into reworking-documentation-paths 2015-08-11 09:10:08 +01:00
Arfon Smith
5d5550c48b Moving vendored definitions to documentation 2015-08-07 10:42:31 +01:00
Arfon Smith
fd570d906a Adding examples path to documentation.yml 2015-08-07 10:35:18 +01:00
Andrew Pennebaker
03369b8a6c use https url for travis support 2015-05-03 12:51:52 -05:00
Andrew Pennebaker
3b2ddb1a18 classify DNS zone as a data format 2015-05-01 11:25:16 -05:00
Andrew Pennebaker
1e20b12241 zone: add ace_mode 2015-04-30 15:40:44 -05:00
Andrew Pennebaker
81c41df15c zone: add tm_scope 2015-04-30 15:39:32 -05:00
Andrew Pennebaker
8b736189e0 better name for DNS zone 2015-04-30 15:34:43 -05:00
Andrew Pennebaker
188d2367df add sample zone file 2015-04-30 15:25:52 -05:00
Andrew Pennebaker
5aeac500da list zone in grammars.yml 2015-04-30 15:24:46 -05:00
Andrew Pennebaker
5730ab28ab list zone in languages.yml 2015-04-30 15:23:31 -05:00
Andrew Pennebaker
1c56b03a28 highlight DNS zone (BIND) files 2015-04-30 15:14:26 -05:00
68 changed files with 2532 additions and 395 deletions

21
.gitmodules vendored
View File

@@ -169,9 +169,6 @@
[submodule "vendor/grammars/sublime-idris"]
path = vendor/grammars/sublime-idris
url = https://github.com/laughedelic/sublime-idris
[submodule "vendor/grammars/sublime-better-typescript"]
path = vendor/grammars/sublime-better-typescript
url = https://github.com/lavrton/sublime-better-typescript
[submodule "vendor/grammars/moonscript-tmbundle"]
path = vendor/grammars/moonscript-tmbundle
url = https://github.com/leafo/moonscript-tmbundle
@@ -397,9 +394,6 @@
[submodule "vendor/grammars/processing.tmbundle"]
path = vendor/grammars/processing.tmbundle
url = https://github.com/textmate/processing.tmbundle
[submodule "vendor/grammars/prolog.tmbundle"]
path = vendor/grammars/prolog.tmbundle
url = https://github.com/textmate/prolog.tmbundle
[submodule "vendor/grammars/python-django.tmbundle"]
path = vendor/grammars/python-django.tmbundle
url = https://github.com/textmate/python-django.tmbundle
@@ -668,3 +662,18 @@
[submodule "vendor/grammars/vue-syntax-highlight"]
path = vendor/grammars/vue-syntax-highlight
url = https://github.com/vuejs/vue-syntax-highlight
[submodule "vendor/grammars/st2-zonefile"]
path = vendor/grammars/st2-zonefile
url = https://github.com/sixty4k/st2-zonefile
[submodule "vendor/grammars/sublimeprolog"]
path = vendor/grammars/sublimeprolog
url = https://github.com/alnkpa/sublimeprolog
[submodule "vendor/grammars/sublime-aspectj"]
path = vendor/grammars/sublime-aspectj
url = https://github.com/pchaigno/sublime-aspectj
[submodule "vendor/grammars/sublime-typescript"]
path = vendor/grammars/sublime-typescript
url = https://github.com/Microsoft/TypeScript-Sublime-Plugin
[submodule "vendor/grammars/X10"]
path = vendor/grammars/X10
url = git@github.com:x10-lang/x10-highlighting.git

View File

@@ -16,7 +16,7 @@ See [Troubleshooting](#troubleshooting) and [`CONTRIBUTING.md`](/CONTRIBUTING.md
The Language stats bar is built by aggregating the languages of each file in that repository. If it is reporting a language that you don't expect:
0. Click on the name of the language in the stats bar to see a list of the files that are identified as that language.
0. If you see files that you didn't write, consider moving the files into one of the [paths for vendored code](https://github.com/github/linguist/blob/master/lib/linguist/vendor.yml), or use the [manual overrides](#overrides) feature to ignore them.
0. If you see files that you didn't write, consider moving the files into one of the [paths for vendored code](/lib/linguist/vendor.yml), or use the [manual overrides](#overrides) feature to ignore them.
0. If the files are being misclassified, search for [open issues][issues] to see if anyone else has already reported the issue. Any information you an add, especially links to public repositories, is helpful.
0. If there are no reported issues of this misclassification, [open an issue][new-issue] and include a link to the repository or a sample of the code that is being misclassified.

View File

@@ -24,4 +24,6 @@ Gem::Specification.new do |s|
s.add_development_dependency 'rake'
s.add_development_dependency 'yajl-ruby'
s.add_development_dependency 'color-proximity', '~> 0.2.1'
s.add_development_dependency 'licensee', '~> 4.7.4'
end

View File

@@ -144,6 +144,8 @@ vendor/grammars/VBDotNetSyntax:
- source.vbnet
vendor/grammars/Vala-TMBundle:
- source.vala
vendor/grammars/X10:
- source.x10
vendor/grammars/abap.tmbundle:
- source.abap
vendor/grammars/actionscript3-tmbundle:
@@ -331,6 +333,7 @@ vendor/grammars/language-hy:
vendor/grammars/language-javascript:
- source.js
- source.js.regexp
- source.js.regexp.replacement
vendor/grammars/language-jsoniq/:
- source.jq
- source.xq
@@ -431,8 +434,6 @@ vendor/grammars/powershell:
- source.powershell
vendor/grammars/processing.tmbundle:
- source.processing
vendor/grammars/prolog.tmbundle:
- source.prolog
vendor/grammars/protobuf-tmbundle:
- source.protobuf
vendor/grammars/puppet-textmate-bundle:
@@ -470,6 +471,8 @@ vendor/grammars/smalltalk-tmbundle:
- source.smalltalk
vendor/grammars/sql.tmbundle:
- source.sql
vendor/grammars/st2-zonefile:
- text.zone_file
vendor/grammars/standard-ml.tmbundle:
- source.cm
- source.ml
@@ -477,10 +480,10 @@ vendor/grammars/sublime-MuPAD:
- source.mupad
vendor/grammars/sublime-apl/:
- source.apl
vendor/grammars/sublime-aspectj/:
- source.aspectj
vendor/grammars/sublime-befunge:
- source.befunge
vendor/grammars/sublime-better-typescript:
- source.ts
vendor/grammars/sublime-bsv:
- source.bsv
vendor/grammars/sublime-cirru:
@@ -519,6 +522,9 @@ vendor/grammars/sublime-text-ox/:
- source.ox
vendor/grammars/sublime-text-pig-latin/:
- source.pig_latin
vendor/grammars/sublime-typescript/:
- source.ts
- source.tsx
vendor/grammars/sublime-varnish:
- source.varnish.vcl
vendor/grammars/sublime_cobol:
@@ -529,6 +535,9 @@ vendor/grammars/sublime_cobol:
vendor/grammars/sublime_man_page_support:
- source.man
- text.groff
vendor/grammars/sublimeprolog/:
- source.prolog
- source.prolog.eclipse
vendor/grammars/sublimetext-cuda-cpp:
- source.cuda-c++
vendor/grammars/swift.tmbundle:

View File

@@ -13,6 +13,7 @@
- (^|/)[Dd]ocumentation/
- (^|/)javadoc/
- ^man/
- ^[Ee]xamples/
## Documentation files ##
@@ -21,4 +22,9 @@
- (^|/)COPYING(\.|$)
- (^|/)INSTALL(\.|$)
- (^|/)LICEN[CS]E(\.|$)
- (^|/)[Ll]icen[cs]e(\.|$)
- (^|/)README(\.|$)
- (^|/)[Rr]eadme(\.|$)
# Samples folders
- ^[Ss]amples/

View File

@@ -33,7 +33,7 @@ module Linguist
#
# Examples
#
# disambiguate "Perl", "Prolog" do |data|
# disambiguate ".pm" do |data|
# if data.include?("use strict")
# Language["Perl"]
# elsif /^[^#]+:-/.match(data)
@@ -65,7 +65,17 @@ module Linguist
end
# Common heuristics
ObjectiveCRegex = /^[ \t]*@(interface|class|protocol|property|end|synchronised|selector|implementation)\b/
ObjectiveCRegex = /^[ \t]*@(interface|class|protocol|property|end|synchronized|selector|implementation)\b/
disambiguate ".asc" do |data|
if /^(----[- ]BEGIN|ssh-(rsa|dss)) /.match(data)
Language["Public Key"]
elsif /^[=-]+(\s|\n)|{{[A-Za-z]/.match(data)
Language["AsciiDoc"]
elsif /^(\/\/.+|((import|export)\s+)?(function|int|float|char)\s+((room|repeatedly|on|game)_)?([A-Za-z]+[A-Za-z_0-9]+)\s*[;\(])/.match(data)
Language["AGS Script"]
end
end
disambiguate ".bb" do |data|
if /^\s*; /.match(data) || data.include?("End Function")
@@ -75,67 +85,9 @@ module Linguist
end
end
disambiguate ".cs" do |data|
if /![\w\s]+methodsFor: /.match(data)
Language["Smalltalk"]
elsif /^\s*namespace\s*[\w\.]+\s*{/.match(data) || /^\s*\/\//.match(data)
Language["C#"]
end
end
disambiguate ".h" do |data|
if ObjectiveCRegex.match(data)
Language["Objective-C"]
elsif (/^\s*#\s*include <(cstdint|string|vector|map|list|array|bitset|queue|stack|forward_list|unordered_map|unordered_set|(i|o|io)stream)>/.match(data) ||
/^\s*template\s*</.match(data) || /^[ \t]*try/.match(data) || /^[ \t]*catch\s*\(/.match(data) || /^[ \t]*(class|(using[ \t]+)?namespace)\s+\w+/.match(data) || /^[ \t]*(private|public|protected):$/.match(data) || /std::\w+/.match(data))
Language["C++"]
end
end
disambiguate ".pl" do |data|
if /^(use v6|(my )?class|module)/.match(data)
Language["Perl6"]
elsif /use strict|use\s+v?5\./.match(data)
Language["Perl"]
elsif /^[^#]+:-/.match(data)
Language["Prolog"]
end
end
disambiguate ".pm" do |data|
if /^(use v6|(my )?class|module)/.match(data)
Language["Perl6"]
elsif /use strict|use\s+v?5\./.match(data)
Language["Perl"]
end
end
disambiguate ".ecl" do |data|
if /^[^#]+:-/.match(data)
Language["Prolog"]
elsif data.include?(":=")
Language["ECL"]
end
end
disambiguate ".pro" do |data|
if /^[^#]+:-/.match(data)
Language["Prolog"]
elsif data.include?("last_client=")
Language["INI"]
elsif data.include?("HEADERS") && data.include?("SOURCES")
Language["QMake"]
elsif /^\s*function[ \w,]+$/.match(data)
Language["IDL"]
end
end
disambiguate ".tst" do |data|
if (data.include?("gap> "))
Language["GAP"]
# Heads up - we don't usually write heuristics like this (with no regex match)
else
Language["Scilab"]
disambiguate ".ch" do |data|
if /^\s*#\s*(if|ifdef|ifndef|define|command|xcommand|translate|xtranslate|include|pragma|undef)\b/i.match(data)
Language["xBase"]
end
end
@@ -149,29 +101,29 @@ module Linguist
end
end
disambiguate ".php" do |data|
if data.include?("<?hh")
Language["Hack"]
elsif /<?[^h]/.match(data)
Language["PHP"]
disambiguate ".cs" do |data|
if /![\w\s]+methodsFor: /.match(data)
Language["Smalltalk"]
elsif /^\s*namespace\s*[\w\.]+\s*{/.match(data) || /^\s*\/\//.match(data)
Language["C#"]
end
end
disambiguate ".sc" do |data|
if /\^(this|super)\./.match(data) || /^\s*(\+|\*)\s*\w+\s*{/.match(data) || /^\s*~\w+\s*=\./.match(data)
Language["SuperCollider"]
elsif /^\s*import (scala|java)\./.match(data) || /^\s*val\s+\w+\s*=/.match(data) || /^\s*class\b/.match(data)
Language["Scala"]
disambiguate ".d" do |data|
if /^module /.match(data)
Language["D"]
elsif /^((dtrace:::)?BEGIN|provider |#pragma (D (option|attributes)|ident)\s)/.match(data)
Language["DTrace"]
elsif /(\/.*:( .* \\)$| : \\$|^ : |: \\$)/.match(data)
Language["Makefile"]
end
end
disambiguate ".asc" do |data|
if /^(----[- ]BEGIN|ssh-(rsa|dss)) /.match(data)
Language["Public Key"]
elsif /^[=-]+(\s|\n)|{{[A-Za-z]/.match(data)
Language["AsciiDoc"]
elsif /^(\/\/.+|((import|export)\s+)?(function|int|float|char)\s+((room|repeatedly|on|game)_)?([A-Za-z]+[A-Za-z_0-9]+)\s*[;\(])/.match(data)
Language["AGS Script"]
disambiguate ".ecl" do |data|
if /^[^#]+:-/.match(data)
Language["ECLiPSe"]
elsif data.include?(":=")
Language["ECL"]
end
end
@@ -183,6 +135,16 @@ module Linguist
end
end
disambiguate ".fr" do |data|
if /^(: |also |new-device|previous )/.match(data)
Language["Forth"]
elsif /^\s*(import|module|package|data|type) /.match(data)
Language["Frege"]
else
Language["Text"]
end
end
disambiguate ".fs" do |data|
if /^(: |new-device)/.match(data)
Language["Forth"]
@@ -195,6 +157,47 @@ module Linguist
end
end
disambiguate ".gs" do |data|
Language["Gosu"] if /^uses java\./.match(data)
end
disambiguate ".h" do |data|
if ObjectiveCRegex.match(data)
Language["Objective-C"]
elsif (/^\s*#\s*include <(cstdint|string|vector|map|list|array|bitset|queue|stack|forward_list|unordered_map|unordered_set|(i|o|io)stream)>/.match(data) ||
/^\s*template\s*</.match(data) || /^[ \t]*try/.match(data) || /^[ \t]*catch\s*\(/.match(data) || /^[ \t]*(class|(using[ \t]+)?namespace)\s+\w+/.match(data) || /^[ \t]*(private|public|protected):$/.match(data) || /std::\w+/.match(data))
Language["C++"]
end
end
disambiguate ".l" do |data|
if /\(def(un|macro)\s/.match(data)
Language["Common Lisp"]
elsif /^(%[%{}]xs|<.*>)/.match(data)
Language["Lex"]
elsif /^\.[a-z][a-z](\s|$)/i.match(data)
Language["Groff"]
elsif /^\((de|class|rel|code|data|must)\s/.match(data)
Language["PicoLisp"]
end
end
disambiguate ".ls" do |data|
if /^\s*package\s*[\w\.\/\*\s]*\s*{/.match(data)
Language["LoomScript"]
else
Language["LiveScript"]
end
end
disambiguate ".lsp", ".lisp" do |data|
if /^\s*\((defun|in-package|defpackage) /i.match(data)
Language["Common Lisp"]
elsif /^\s*\(define /.match(data)
Language["NewLisp"]
end
end
disambiguate ".m" do |data|
if ObjectiveCRegex.match(data)
Language["Objective-C"]
@@ -213,41 +216,113 @@ module Linguist
end
end
disambiguate ".gs" do |data|
Language["Gosu"] if /^uses java\./.match(data)
end
disambiguate ".ls" do |data|
if /^\s*package\s*[\w\.\/\*\s]*\s*{/.match(data)
Language["LoomScript"]
else
Language["LiveScript"]
disambiguate ".ml" do |data|
if /(^\s*module)|let rec |match\s+(\S+\s)+with/.match(data)
Language["OCaml"]
elsif /=> |case\s+(\S+\s)+of/.match(data)
Language["Standard ML"]
end
end
disambiguate ".lsp", ".lisp" do |data|
if /^\s*\((defun|in-package|defpackage) /i.match(data)
Language["Common Lisp"]
elsif /^\s*\(define /.match(data)
disambiguate ".mod" do |data|
if data.include?('<!ENTITY ')
Language["XML"]
elsif /MODULE\s\w+\s*;/i.match(data) || /^\s*END \w+;$/i.match(data)
Language["Modula-2"]
else
[Language["Linux Kernel Module"], Language["AMPL"]]
end
end
disambiguate ".ms" do |data|
if /^[.'][a-z][a-z](\s|$)/i.match(data)
Language["Groff"]
elsif /((^|\s)move?[. ])|\.(include|globa?l)\s/.match(data)
Language["GAS"]
end
end
disambiguate ".n" do |data|
if /^[.']/.match(data)
Language["Groff"]
elsif /^(module|namespace|using)\s/.match(data)
Language["Nemerle"]
end
end
disambiguate ".ncl" do |data|
if data.include?("THE_TITLE")
Language["Text"]
end
end
disambiguate ".nl" do |data|
if /^(b|g)[0-9]+ /.match(data)
Language["NL"]
else
Language["NewLisp"]
end
end
disambiguate ".ts" do |data|
if data.include?("<TS ")
Language["XML"]
else
Language["TypeScript"]
disambiguate ".php" do |data|
if data.include?("<?hh")
Language["Hack"]
elsif /<?[^h]/.match(data)
Language["PHP"]
end
end
disambiguate ".fr" do |data|
if /^(: |also |new-device|previous )/.match(data)
Language["Forth"]
elsif /^\s*(import|module|package|data|type) /.match(data)
Language["Frege"]
else
Language["Text"]
disambiguate ".pl" do |data|
if /^(use v6|(my )?class|module)/.match(data)
Language["Perl6"]
elsif /use strict|use\s+v?5\./.match(data)
Language["Perl"]
elsif /^[^#]+:-/.match(data)
Language["Prolog"]
end
end
disambiguate ".pm", ".t" do |data|
if /^(use v6|(my )?class|module)/.match(data)
Language["Perl6"]
elsif /use strict|use\s+v?5\./.match(data)
Language["Perl"]
end
end
disambiguate ".pro" do |data|
if /^[^#]+:-/.match(data)
Language["Prolog"]
elsif data.include?("last_client=")
Language["INI"]
elsif data.include?("HEADERS") && data.include?("SOURCES")
Language["QMake"]
elsif /^\s*function[ \w,]+$/.match(data)
Language["IDL"]
end
end
disambiguate ".r" do |data|
if /\bRebol\b/i.match(data)
Language["Rebol"]
elsif data.include?("<-")
Language["R"]
end
end
disambiguate ".rs" do |data|
if /^(use |fn |mod |pub |macro_rules|impl|#!?\[)/.match(data)
Language["Rust"]
elsif /#include|#pragma\s+(rs|version)|__attribute__/.match(data)
Language["RenderScript"]
end
end
disambiguate ".sc" do |data|
if /\^(this|super)\./.match(data) || /^\s*(\+|\*)\s*\w+\s*{/.match(data) || /^\s*~\w+\s*=\./.match(data)
Language["SuperCollider"]
elsif /^\s*import (scala|java)\./.match(data) || /^\s*val\s+\w+\s*=/.match(data) || /^\s*class\b/.match(data)
Language["Scala"]
end
end
@@ -267,95 +342,20 @@ module Linguist
end
end
disambiguate ".d" do |data|
if /^module /.match(data)
Language["D"]
elsif /^((dtrace:::)?BEGIN|provider |#pragma (D (option|attributes)|ident)\s)/.match(data)
Language["DTrace"]
elsif /(\/.*:( .* \\)$| : \\$|^ : |: \\$)/.match(data)
Language["Makefile"]
end
end
disambiguate ".ml" do |data|
if /(^\s*module)|let rec |match\s+(\S+\s)+with/.match(data)
Language["OCaml"]
elsif /=> |case\s+(\S+\s)+of/.match(data)
Language["Standard ML"]
end
end
disambiguate ".mod" do |data|
if data.include?('<!ENTITY ')
disambiguate ".ts" do |data|
if data.include?("<TS ")
Language["XML"]
elsif /MODULE\s\w+\s*;/i.match(data) || /^\s*END \w+;$/i.match(data)
Language["Modula-2"]
else
[Language["Linux Kernel Module"], Language["AMPL"]]
Language["TypeScript"]
end
end
disambiguate ".ncl" do |data|
if data.include?("THE_TITLE")
Language["Text"]
end
end
disambiguate ".nl" do |data|
if /^(b|g)[0-9]+ /.match(data)
Language["NL"]
disambiguate ".tst" do |data|
if (data.include?("gap> "))
Language["GAP"]
# Heads up - we don't usually write heuristics like this (with no regex match)
else
Language["NewLisp"]
end
end
disambiguate ".rs" do |data|
if /^(use |fn |mod |pub |macro_rules|impl|#!?\[)/.match(data)
Language["Rust"]
elsif /#include|#pragma\s+(rs|version)|__attribute__/.match(data)
Language["RenderScript"]
end
end
disambiguate ".l" do |data|
if /\(def(un|macro)\s/.match(data)
Language["Common Lisp"]
elsif /^(%[%{}]xs|<.*>)/.match(data)
Language["Lex"]
elsif /^\.[a-z][a-z](\s|$)/i.match(data)
Language["Groff"]
elsif /^\((de|class|rel|code|data|must)\s/.match(data)
Language["PicoLisp"]
end
end
disambiguate ".n" do |data|
if /^[.']/.match(data)
Language["Groff"]
elsif /^(module|namespace|using)\s/.match(data)
Language["Nemerle"]
end
end
disambiguate ".ms" do |data|
if /^[.'][a-z][a-z](\s|$)/i.match(data)
Language["Groff"]
elsif /((^|\s)move?[. ])|\.(include|globa?l)\s/.match(data)
Language["GAS"]
end
end
disambiguate ".ch" do |data|
if /^\s*#\s*(if|ifdef|ifndef|define|command|xcommand|translate|xtranslate|include|pragma|undef)\b/i.match(data)
Language["xBase"]
end
end
disambiguate ".r" do |data|
if /\bRebol\b/i.match(data)
Language["Rebol"]
elsif data.include?("<-")
Language["R"]
Language["Scilab"]
end
end
end

View File

@@ -214,7 +214,7 @@ AspectJ:
color: "#a957b0"
extensions:
- .aj
tm_scope: none
tm_scope: source.aspectj
ace_mode: text
Assembly:
@@ -616,6 +616,7 @@ Common Lisp:
- .lsp
- .ny
- .podsl
- .sexp
interpreters:
- lisp
- sbcl
@@ -750,6 +751,14 @@ DM:
tm_scope: source.c++
ace_mode: c_cpp
DNS Zone:
type: data
extensions:
- .zone
- .arpa
tm_scope: text.zone_file
ace_mode: text
DTrace:
type: programming
aliases:
@@ -834,6 +843,14 @@ ECL:
tm_scope: none
ace_mode: text
ECLiPSe:
type: programming
group: prolog
extensions:
- .ecl
tm_scope: source.prolog.eclipse
ace_mode: prolog
Eagle:
type: markup
color: "#814C05"
@@ -1702,6 +1719,7 @@ LSL:
ace_mode: lsl
extensions:
- .lsl
- .lslp
interpreters:
- lsl
color: '#3d9970'
@@ -1710,8 +1728,8 @@ LabVIEW:
type: programming
extensions:
- .lvproj
tm_scope: none
ace_mode: text
tm_scope: text.xml
ace_mode: xml
Lasso:
type: programming
@@ -2425,6 +2443,7 @@ PLSQL:
type: programming
ace_mode: sql
tm_scope: source.plsql.oracle
color: "#dad8d8"
extensions:
- .pls
- .pkb
@@ -2619,11 +2638,11 @@ Prolog:
color: "#74283c"
extensions:
- .pl
- .ecl
- .pro
- .prolog
interpreters:
- swipl
tm_scope: source.prolog
ace_mode: prolog
Propeller Spin:
@@ -2761,7 +2780,7 @@ R:
ace_mode: r
RAML:
type: data
type: markup
ace_mode: yaml
tm_scope: source.yaml
color: "#77d9fb"
@@ -2804,7 +2823,7 @@ RMarkdown:
ace_mode: markdown
extensions:
- .rmd
tm_scope: none
tm_scope: source.gfm
Racket:
type: programming
@@ -3550,6 +3569,16 @@ WebIDL:
tm_scope: source.webidl
ace_mode: text
X10:
type: programming
aliases:
- xten
ace_mode: text
extensions:
- .x10
color: "#4B6BEF"
tm_scope: source.x10
XC:
type: programming
color: "#99DA07"
@@ -3587,6 +3616,7 @@ XML:
- .iml
- .ivy
- .jelly
- .jsproj
- .kml
- .launch
- .mdpolicy

View File

@@ -78,6 +78,9 @@
# Haxelib projects often contain a neko bytecode file named run.n
- run.n$
# Bootstrap Datepicker
- bootstrap-datepicker/
## Commonly Bundled JavaScript frameworks ##
# jQuery
@@ -88,6 +91,34 @@
- (^|/)jquery\-ui(\-\d\.\d+(\.\d+)?)?(\.\w+)?\.(js|css)$
- (^|/)jquery\.(ui|effects)\.([^.]*)\.(js|css)$
# jQuery Gantt
- jquery.fn.gantt.js
# jQuery fancyBox
- jquery.fancybox.js
# Fuel UX
- fuelux.js
# jQuery File Upload
- (^|/)jquery\.fileupload(-\w+)?\.js$
# Slick
- (^|/)slick\.\w+.js$
# Leaflet plugins
- (^|/)Leaflet\.Coordinates-\d+\.\d+\.\d+\.src\.js$
- leaflet.draw-src.js
- leaflet.draw.css
- Control.FullScreen.css
- Control.FullScreen.js
- leaflet.spin.js
- wicket-leaflet.js
# Sublime Text workspace files
- .sublime-project
- .sublime-workspace
# Prototype
- (^|/)prototype(.*)\.js$
- (^|/)effects\.js$
@@ -122,7 +153,7 @@
- (^|/)Chart\.js$
# Codemirror
- (^|/)[Cc]ode[Mm]irror/(lib|mode|theme|addon|keymap|demo)
- (^|/)[Cc]ode[Mm]irror/(\d+\.\d+/)?(lib|mode|theme|addon|keymap|demo)
# SyntaxHighlighter - http://alexgorbatchev.com/
- (^|/)shBrush([^.]*)\.js$
@@ -164,6 +195,11 @@
## Obj-C ##
# Xcode
- \.xctemplate/
- \.imageset/
# Carthage
- ^Carthage/
@@ -179,6 +215,10 @@
# Fabric
- Fabric.framework/
# git config files
- gitattributes$
- gitignore$
- gitmodules$
## Groovy ##
@@ -224,19 +264,6 @@
# Html5shiv
- (^|/)html5shiv\.js$
# Samples folders
- ^[Ss]amples/
# LICENSE, README, git config files
- ^COPYING$
- LICENSE$
- License$
- gitattributes$
- gitignore$
- gitmodules$
- ^README$
- ^readme$
# Test fixtures
- ^[Tt]ests?/fixtures/

View File

@@ -1,3 +1,3 @@
module Linguist
VERSION = "4.5.13"
VERSION = "4.5.15"
end

View File

@@ -0,0 +1,2 @@
((exe_name hello)
(link_order (world hello)))

View File

@@ -0,0 +1,103 @@
(:TURTLE
(:@PREFIX "rdf:" "<http://www.w3.org/1999/02/22-rdf-syntax-ns#>")
(:@PREFIX "owl:" "<http://www.w3.org/2002/07/owl#>")
(:@PREFIX "dc:" "<http://purl.org/dc/elements/1.1/>")
(:@PREFIX "xsd:" "<http://www.w3.org/2001/XMLSchema#>")
(:@PREFIX "rdfs:" "<http://www.w3.org/2000/01/rdf-schema#>")
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/channel>")
(:PREDICATE-OBJECT-LIST
(:URIREF #1="<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>")
(:OBJECTS
(:QNAME "rdfs:Class")))
(:PREDICATE-OBJECT-LIST
(:QNAME "rdfs:comment")
(:OBJECTS
(:STRING "An RSS information channel.")))
(:PREDICATE-OBJECT-LIST
(:QNAME "rdfs:isDefinedBy")
(:OBJECTS
(:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST
(:QNAME "rdfs:label")
(:OBJECTS
(:STRING "Channel"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/description>")
(:PREDICATE-OBJECT-LIST
(:URIREF #1#)
(:OBJECTS
(:QNAME "rdf:Property")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment")
(:OBJECTS (:STRING "A short text description of the subject.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Description")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:subPropertyOf") (:OBJECTS (:QNAME "dc:description"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/image>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdfs:Class")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment") (:OBJECTS (:STRING "An RSS image.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Image"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/item>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdfs:Class")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment") (:OBJECTS (:STRING "An RSS item.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Item"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/items>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdf:Property")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment")
(:OBJECTS
(:STRING "Points to a list of rss:item elements that are members of the subject channel.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Items"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/link>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdf:Property")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment")
(:OBJECTS (:STRING "The URL to which an HTML rendering of the subject will link.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Link")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:subPropertyOf") (:OBJECTS (:QNAME "dc:identifier"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/name>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdf:Property")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment")
(:OBJECTS (:STRING "The text input field's (variable) name.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Name"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/textinput>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdfs:Class")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment") (:OBJECTS (:STRING "An RSS text input.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Text Input"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/title>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdf:Property")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment")
(:OBJECTS (:STRING "A descriptive title for the channel.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "Title")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:subPropertyOf") (:OBJECTS (:QNAME "dc:title"))))
(:TRIPLES (:URIREF "<http://purl.org/rss/1.0/url>")
(:PREDICATE-OBJECT-LIST (:URIREF #1#) (:OBJECTS (:QNAME "rdf:Property")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:comment")
(:OBJECTS
(:STRING
"The URL of the image to used in the 'src' attribute of the channel's image tag when rendered as HTML.")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:isDefinedBy")
(:OBJECTS (:URIREF "<http://purl.org/rss/1.0/>")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:label") (:OBJECTS (:STRING "URL")))
(:PREDICATE-OBJECT-LIST (:QNAME "rdfs:subPropertyOf") (:OBJECTS (:QNAME "dc:identifier")))))

View File

@@ -0,0 +1,13 @@
$ORIGIN 0.0.0.c.2.1.0.3.0.0.2.1.e.f.f.3.ip6.arpa.
$TTL 60
@ IN SOA ns root (
2002042901 ; SERIAL
7200 ; REFRESH
600 ; RETRY
36000000 ; EXPIRE
120 ; MINIMUM
)
NS ns.example.com.
c.a.7.e.d.7.e.f.f.f.0.2.8.0.a.0 PTR sip01.example.com.

View File

@@ -0,0 +1,12 @@
$TTL 3d
@ IN SOA root.localhost. root.sneaky.net. (
2015042907 ; serial
3d ; refresh
1h ; retry
12d ; expire
2h ; negative response TTL
)
IN NS root.localhost.
IN NS localhost. ; secondary name server is preferably externally maintained
www IN A 3.141.59.26

74
samples/LSL/LSL.lslp Normal file
View File

@@ -0,0 +1,74 @@
/*
Testing syntax highlighting
for the Linden Scripting Language
*/
integer someIntNormal = 3672;
integer someIntHex = 0x00000000;
integer someIntMath = PI_BY_TWO;
integer event = 5673;// 'event' is invalid.illegal
key someKeyTexture = TEXTURE_DEFAULT;
string someStringSpecial = EOF;
some_user_defined_function_without_return_type(string inputAsString)
{
llSay(PUBLIC_CHANNEL, inputAsString);
}
string user_defined_function_returning_a_string(key inputAsKey)
{
return (string)inputAsKey;
}
default
{
state_entry()
{
key someKey = NULL_KEY;
someKey = llGetOwner();
string someString = user_defined_function_returning_a_string(someKey);
some_user_defined_function_without_return_type(someString);
}
touch_start(integer num_detected)
{
list agentsInRegion = llGetAgentList(AGENT_LIST_REGION, []);
integer numOfAgents = llGetListLength(agentsInRegion);
integer index; // defaults to 0
for (; index <= numOfAgents - 1; index++) // for each agent in region
{
llRegionSayTo(llList2Key(agentsInRegion, index), PUBLIC_CHANNEL, "Hello, Avatar!");
}
}
touch_end(integer num_detected)
{
someIntNormal = 3672;
someIntHex = 0x00000000;
someIntMath = PI_BY_TWO;
event = 5673;// 'event' is invalid.illegal
someKeyTexture = TEXTURE_DEFAULT;
someStringSpecial = EOF;
llSetInventoryPermMask("some item", MASK_NEXT, PERM_ALL);// 'llSetInventoryPermMask' is reserved.godmode
llWhisper(PUBLIC_CHANNEL, "Leaving \"default\" now...");
state other;
}
}
state other
{
state_entry()
{
llWhisper(PUBLIC_CHANNEL, "Entered \"state other\", returning to \"default\" again...");
state default;
}
}

72
samples/X10/ArraySum.x10 Normal file
View File

@@ -0,0 +1,72 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.io.Console;
/**
* A simple illustration of loop parallelization within a single place.
*/
public class ArraySum {
var sum:Long;
val data:Rail[Long];
public def this(n:Long) {
// Create a Rail with n elements (0..(n-1)), all initialized to 1.
data = new Rail[Long](n, 1);
sum = 0;
}
def sum(a:Rail[Long], start:Long, last:Long) {
var mySum: Long = 0;
for (i in start..(last-1)) {
mySum += a(i);
}
return mySum;
}
def sum(numThreads:Long) {
val mySize = data.size/numThreads;
finish for (p in 0..(numThreads-1)) async {
val mySum = sum(data, p*mySize, (p+1)*mySize);
// Multiple activities will simultaneously update
// this location -- so use an atomic operation.
atomic sum += mySum;
}
}
public static def main(args:Rail[String]) {
var size:Long = 5*1000*1000;
if (args.size >=1)
size = Long.parse(args(0));
Console.OUT.println("Initializing.");
val a = new ArraySum(size);
val P = [1,2,4];
//warmup loop
Console.OUT.println("Warming up.");
for (numThreads in P)
a.sum(numThreads);
for (numThreads in P) {
Console.OUT.println("Starting with " + numThreads + " threads.");
a.sum=0;
var time: long = - System.nanoTime();
a.sum(numThreads);
time += System.nanoTime();
Console.OUT.println("For p=" + numThreads
+ " result: " + a.sum
+ ((size==a.sum)? " ok" : " bad")
+ " (time=" + (time/(1000*1000)) + " ms)");
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.xrx.Runtime;
/**
* Demonstrate how to instantiate the X10 runtime as an executor service
* submit jobs to the runtime, wait jobs to complete and cancel all jobs
*
* Compile with: x10c -O -EXECUTOR_MODE=true Cancellation.x10
* Run with: X10_CANCELLABLE=true X10_NPLACES=4 x10 -DX10RT_IMPL=JavaSockets Cancellation
*/
class Cancellation {
static def job(id:Long, iterations:Long) = ()=>{
at (Place.places().next(here)) async {
for (i in 1..iterations) {
finish for (p in Place.places()) {
at (p) async Console.OUT.println(here+" says hello (job " + id + ", iteration " + i + ")");
}
Console.ERR.println();
System.sleep(200);
}
}
};
public static def main(args:Rail[String]):void {
val w1 = Runtime.submit(job(1, 5));
w1.await(); Console.ERR.println("Job 1 completed\n");
val w2 = Runtime.submit(job(2, 1000));
System.threadSleep(1000);
val c1 = Runtime.cancelAll();
try { w2.await(); } catch (e:Exception) { Console.ERR.println("Job 2 aborted with exception " + e +"\n"); }
c1.await(); // waiting for cancellation to be processed
System.threadSleep(1000);
Runtime.submit(job(3, 1000));
Runtime.submit(job(4, 1000));
System.threadSleep(1000);
val c2 = Runtime.cancelAll();
c2.await();
Console.ERR.println("Goodbye\n");
}
}

52
samples/X10/Fibonacci.x10 Normal file
View File

@@ -0,0 +1,52 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.io.Console;
/**
* This is a small program to illustrate the use of
* <code>async</code> and <code>finish</code> in a
* prototypical recursive divide-and-conquer algorithm.
* It is obviously not intended to show a efficient way to
* compute Fibonacci numbers in X10.<p>
*
* The heart of the example is the <code>run</code> method,
* which directly embodies the recursive definition of
* <pre>
* fib(n) = fib(n-1)+fib(n-2);
* </pre>
* by using an <code>async</code> to compute <code>fib(n-1)</code> while
* the current activity computes <code>fib(n-2)</code>. A <code>finish</code>
* is used to ensure that both computations are complete before
* their results are added together to compute <code>fib(n)</code>
*/
public class Fibonacci {
public static def fib(n:long) {
if (n<=2) return 1;
val f1:long;
val f2:long;
finish {
async { f1 = fib(n-1); }
f2 = fib(n-2);
}
return f1 + f2;
}
public static def main(args:Rail[String]) {
val n = (args.size > 0) ? Long.parse(args(0)) : 10;
Console.OUT.println("Computing fib("+n+")");
val f = fib(n);
Console.OUT.println("fib("+n+") = "+f);
}
}

View File

@@ -0,0 +1,86 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.array.*;
import x10.compiler.Foreach;
import x10.compiler.Inline;
/**
* This is a sample program illustrating how to use
* X10's array classes. It also illustrates the use
* of foreach to acheive intra-place parallelism.
*
* The program solves a set of 2D partial differential
* equations by iteratively applying a 5-point stencil
* operation until convergence is reached.
*/
public class HeatTransfer_v0 {
static val EPSILON = 1.0e-5;
val N:Long;
val A:Array_2[Double]{self!=null};
val Tmp:Array_2[Double]{self!=null};
public def this(size:Long) {
N = size;
A = new Array_2[Double](N+2, N+2); // zero-initialized N+2 * N+2 array of doubles
for (j in 1..N) A(0, j) = 1; // set one border row to 1
Tmp = new Array_2[Double](A);
}
final @Inline def stencil(x:Long, y:Long):Double {
return (A(x-1,y) + A(x+1,y) + A(x,y-1) + A(x,y+1)) / 4;
}
def run() {
val is = new DenseIterationSpace_2(1,1,N,N);
var delta:Double;
do {
// Compute new values, storing in tmp
delta = Foreach.blockReduce(is,
(i:Long, j:Long)=>{
Tmp(i,j) = stencil(i,j);
// Reduce max element-wise delta (A now holds previous values)
return Math.abs(Tmp(i,j) - A(i,j));
},
(a:Double, b:Double)=>Math.max(a,b), 0.0
);
// swap backing data of A and Tmp
Array.swap(A, Tmp);
} while (delta > EPSILON);
}
def prettyPrintResult() {
for (i in 1..N) {
for (j in 1..N) {
Console.OUT.printf("%1.4f ",A(i,j));
}
Console.OUT.println();
}
}
public static def main(args:Rail[String]) {
val n = args.size > 0 ? Long.parse(args(0)) : 8;
Console.OUT.println("HeatTransfer example with N="+n+" and epsilon="+EPSILON);
Console.OUT.println("Initializing data structures");
val ht = new HeatTransfer_v0(n);
Console.OUT.println("Beginning computation...");
val start = System.nanoTime();
ht.run();
val stop = System.nanoTime();
Console.OUT.printf("...completed in %1.3f seconds.\n", ((stop-start) as double)/1e9);
if (n <= 10) {
ht.prettyPrintResult();
}
}
}

View File

@@ -0,0 +1,114 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.array.*;
import x10.compiler.Foreach;
import x10.util.Team;
/**
* This is a sample program illustrating how to use
* X10's distributed array classes. It also illustrates the use
* of foreach to achieve intra-place parallelism and the mixture
* of APGAS finish/async/at with Team collective operations.
*
* This version of the program uses a vanilla DistArray without
* ghost regions. As a result, the stencil function does
* inefficient fine-grained neighbor communication to get individual values.
* Compare this to HeatTransfer_v2 which utilizes ghost regions and
* bulk ghost-region exchange functions.
*
* The program solves a set of 2D partial differential
* equations by iteratively applying a 5-point stencil
* operation until convergence is reached.
*/
public class HeatTransfer_v1 {
static val EPSILON = 1.0e-5;
val N:Long;
val A:DistArray_BlockBlock_2[Double]{self!=null};
val Tmp:DistArray_BlockBlock_2[Double]{self!=null};
public def this(size:Long) {
N = size;
val init = (i:Long, j:Long)=>i==0 ? 1.0 : 0.0;
A = new DistArray_BlockBlock_2[Double](N+2, N+2, init);
Tmp = new DistArray_BlockBlock_2[Double](N+2, N+2, init);
}
final def stencil(x:Long, y:Long):Double {
val cls = (dx:Long, dy:Long)=>{
val p = A.place(x+dx, y+dy);
p == here ? A(x+dx,y+dy) : at (p) A(x+dx,y+dy)
};
val tmp = cls(-1,0) + cls(1,0) + cls(0,-1) + cls(0,1);
return tmp / 4;
}
def run() {
val myTeam = new Team(A.placeGroup());
finish for (p in A.placeGroup()) at (p) async {
// Compute the subset of the local indices on which
// we want to apply the stencil (the interior points of the N+2 x N+2 grid)
val li = A.localIndices();
val interior = new DenseIterationSpace_2(li.min(0) == 0 ? 1 : li.min(0),
li.min(1) == 0 ? 1 : li.min(1),
li.max(0) == N+1 ? N : li.max(0),
li.max(1) == N+1 ? N : li.max(1));
var delta:Double;
do {
// Compute new values, storing in tmp
val myDelta = Foreach.blockReduce(interior,
(i:Long, j:Long)=>{
Tmp(i,j) = stencil(i,j);
// Reduce max element-wise delta (A now holds previous values)
return Math.abs(Tmp(i,j) - A(i,j));
},
(a:Double, b:Double)=>Math.max(a,b), 0.0
);
myTeam.barrier();
// Unlike Array, DistArray doesn't provide an optimized swap.
// So, until it does, we have to copy the data elements.
Foreach.block(interior, (i:Long, j:Long)=>{
A(i,j) = Tmp(i,j);
});
delta = myTeam.allreduce(myDelta, Team.MAX);
} while (delta > EPSILON);
}
}
def prettyPrintResult() {
for (i in 1..N) {
for (j in 1..N) {
val x = at (A.place(i,j)) A(i,j);
Console.OUT.printf("%1.4f ", x);
}
Console.OUT.println();
}
}
public static def main(args:Rail[String]) {
val n = args.size > 0 ? Long.parse(args(0)) : 8;
Console.OUT.println("HeatTransfer example with N="+n+" and epsilon="+EPSILON);
Console.OUT.println("Initializing data structures");
val ht = new HeatTransfer_v1(n);
Console.OUT.println("Beginning computation...");
val start = System.nanoTime();
ht.run();
val stop = System.nanoTime();
Console.OUT.printf("...completed in %1.3f seconds.\n", ((stop-start) as double)/1e9);
if (n <= 10) {
ht.prettyPrintResult();
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.io.Console;
/**
* The classic hello world program, with a twist - prints a message
* from the command line at every Place.
* The messages from each Place may appear in any order, but the
* finish ensures that the last message printed will be "Goodbye"
* <pre>
* Typical output:
* [dgrove@linchen samples]$ ./HelloWholeWorld 'best wishes'
* Place(1) says hello and best wishes
* Place(2) says hello and best wishes
* Place(3) says hello and best wishes
* Place(0) says hello and best wishes
* Goodbye
* [dgrove@linchen samples]$
* </pre>
*/
class HelloWholeWorld {
public static def main(args:Rail[String]):void {
if (args.size < 1) {
Console.OUT.println("Usage: HelloWholeWorld message");
return;
}
finish for (p in Place.places()) {
at (p) async Console.OUT.println(here+" says hello and "+args(0));
}
Console.OUT.println("Goodbye");
}
}

View File

@@ -0,0 +1,23 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.io.Console;
/**
* The classic hello world program, shows how to output to the console.
*/
class HelloWorld {
public static def main(Rail[String]) {
Console.OUT.println("Hello World!" );
}
}

45
samples/X10/Histogram.x10 Normal file
View File

@@ -0,0 +1,45 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
public class Histogram {
public static def compute(data:Rail[Int], numBins:Int) {
val bins = new Rail[Int](numBins);
finish for (i in data.range) async {
val b = data(i) % numBins;
atomic bins(b)++;
}
return bins;
}
public static def run(N:Int, S:Int):Boolean {
val a = new Rail[Int](N, (i:long)=> i as int);
val b = compute(a, S);
val v = b(0);
var ok:Boolean = true;
for (x in b.range) ok &= (b(x)==v);
return ok;
}
public static def main(args:Rail[String]) {
if (args.size != 2L) {
Console.OUT.println("Usage: Histogram SizeOfArray NumberOfBins");
return;
}
val N = Int.parse(args(0));
val S = Int.parse(args(1));
val ok = run(N,S);
if (ok) {
Console.OUT.println("Test ok.");
} else {
Console.OUT.println("Test failed.");
}
}
}

55
samples/X10/Integrate.x10 Normal file
View File

@@ -0,0 +1,55 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
/**
* This is a slightly more realistic example of the
* basic computational pattern of using async/finish
* to express recursive divide-and-conquer algorithms.
* The program does integration via Guassian Quadrature.
* <p>
* It also can serve as an example of using a closure.
*/
public class Integrate {
static val epsilon = 1.0e-9;
val fun:(double)=>double;
public def this(f:(double)=>double) { fun = f; }
public def computeArea(left:double, right:double) {
return recEval(left, fun(left), right, fun(right), 0);
}
private def recEval(l:double, fl:double, r:double, fr:double, a:double) {
val h = (r - l) / 2;
val hh = h / 2;
val c = l + h;
val fc = fun(c);
val al = (fl + fc) * hh;
val ar = (fr + fc) * hh;
val alr = al + ar;
if (Math.abs(alr - a) < epsilon) return alr;
val expr1:double;
val expr2:double;
finish {
async { expr1 = recEval(c, fc, r, fr, ar); };
expr2 = recEval(l, fl, c, fc, al);
}
return expr1 + expr2;
}
public static def main(args:Rail[String]) {
val obj = new Integrate((x:double)=>(x*x + 1.0) * x);
val xMax = args.size > 0 ? Long.parse(args(0)) : 10;
val area = obj.computeArea(0, xMax);
Console.OUT.println("The area of (x*x +1) * x from 0 to "+xMax+" is "+area);
}
}

151
samples/X10/KMeans.x10 Normal file
View File

@@ -0,0 +1,151 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.io.Console;
import x10.util.Random;
/**
* A KMeans object o can compute K means of a given set of
* points of dimension o.myDim.
* <p>
* This class implements a sequential program, that is readily parallelizable.
*
* For a scalable, high-performance version of this benchmark see
* KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org)
*/
public class KMeans(myDim:Long) {
static val DIM=2;
static val K=4;
static val POINTS=2000;
static val ITERATIONS=50;
static val EPS=0.01F;
static type ValVector(k:Long) = Rail[Float]{self.size==k};
static type ValVector = ValVector(DIM);
static type Vector(k:Long) = Rail[Float]{self.size==k};
static type Vector = Vector(DIM);
static type SumVector(d:Long) = V{self.dim==d};
static type SumVector = SumVector(DIM);
/**
* V represents the sum of 'count' number of vectors of dimension 'dim'.
*/
static class V(dim:Long) implements (Long)=>Float {
var vec: Vector(dim);
var count:Int;
def this(dim:Long, init:(Long)=>Float): SumVector(dim) {
property(dim);
vec = new Rail[Float](this.dim, init);
count = 0n;
}
public operator this(i:Long) = vec(i);
def makeZero() {
for (i in 0..(dim-1))
vec(i) =0.0F;
count=0n;
}
def addIn(a:ValVector(dim)) {
for (i in 0..(dim-1))
vec(i) += a(i);
count++;
}
def div(f:Int) {
for (i in 0..(dim-1))
vec(i) /= f;
}
def dist(a:ValVector(dim)):Float {
var dist:Float=0.0F;
for (i in 0..(dim-1)) {
val tmp = vec(i)-a(i);
dist += tmp*tmp;
}
return dist;
}
def dist(a:SumVector(dim)):Float {
var dist:Float=0.0F;
for (i in 0..(dim-1)) {
val tmp = vec(i)-a(i);
dist += tmp*tmp;
}
return dist;
}
def print() {
Console.OUT.println();
for (i in 0..(dim-1)) {
Console.OUT.print((i>0? " " : "") + vec(i));
}
}
def normalize() { div(count);}
def count() = count;
}
def this(myDim:Long):KMeans{self.myDim==myDim} {
property(myDim);
}
static type KMeansData(myK:Long, myDim:Long)= Rail[SumVector(myDim)]{self.size==myK};
/**
* Compute myK means for the given set of points of dimension myDim.
*/
def computeMeans(myK:Long, points:Rail[ValVector(myDim)]):KMeansData(myK, myDim) {
var redCluster : KMeansData(myK, myDim) =
new Rail[SumVector(myDim)](myK, (i:long)=> new V(myDim, (j:long)=>points(i)(j)));
var blackCluster: KMeansData(myK, myDim) =
new Rail[SumVector(myDim)](myK, (i:long)=> new V(myDim, (j:long)=>0.0F));
for (i in 1..ITERATIONS) {
val tmp = redCluster;
redCluster = blackCluster;
blackCluster=tmp;
for (p in 0..(POINTS-1)) {
var closest:Long = -1;
var closestDist:Float = Float.MAX_VALUE;
val point = points(p);
for (k in 0..(myK-1)) { // compute closest mean in cluster.
val dist = blackCluster(k).dist(point);
if (dist < closestDist) {
closestDist = dist;
closest = k;
}
}
redCluster(closest).addIn(point);
}
for (k in 0..(myK-1))
redCluster(k).normalize();
var b:Boolean = true;
for (k in 0..(myK-1)) {
if (redCluster(k).dist(blackCluster(k)) > EPS) {
b=false;
break;
}
}
if (b)
break;
for (k in 0..(myK-1))
blackCluster(k).makeZero();
}
return redCluster;
}
public static def main (Rail[String]) {
val rnd = new Random(0);
val points = new Rail[ValVector](POINTS,
(long)=>new Rail[Float](DIM, (long)=>rnd.nextFloat()));
val result = new KMeans(DIM).computeMeans(K, points);
for (k in 0..(K-1)) result(k).print();
}
}
// vim: shiftwidth=4:tabstop=4:expandtab

147
samples/X10/KMeansDist.x10 Normal file
View File

@@ -0,0 +1,147 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.array.*;
import x10.io.Console;
import x10.util.Random;
/**
* A low performance formulation of distributed KMeans using fine-grained asyncs.
*
* For a highly optimized and scalable, version of this benchmark see
* KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org)
*/
public class KMeansDist {
static val DIM=2;
static val CLUSTERS=4;
static val POINTS=2000;
static val ITERATIONS=50;
public static def main (Rail[String]) {
val world = Place.places();
val local_curr_clusters =
PlaceLocalHandle.make[Array_2[Float]](world, () => new Array_2[Float](CLUSTERS, DIM));
val local_new_clusters =
PlaceLocalHandle.make[Array_2[Float]](world, () => new Array_2[Float](CLUSTERS, DIM));
val local_cluster_counts =
PlaceLocalHandle.make[Rail[Int]](world, ()=> new Rail[Int](CLUSTERS));
val rnd = PlaceLocalHandle.make[Random](world, () => new Random(0));
val points = new DistArray_Block_2[Float](POINTS, DIM, world, (Long,Long)=>rnd().nextFloat());
val central_clusters = new Array_2[Float](CLUSTERS, DIM, (i:Long, j:Long) => {
at (points.place(i,j)) points(i,j)
});
val old_central_clusters = new Array_2[Float](CLUSTERS, DIM);
val central_cluster_counts = new Rail[Int](CLUSTERS);
for (iter in 1..ITERATIONS) {
Console.OUT.println("Iteration: "+iter);
finish {
// reset state
for (d in world) at (d) async {
for ([i,j] in central_clusters.indices()) {
local_curr_clusters()(i, j) = central_clusters(i, j);
local_new_clusters()(i, j) = 0f;
}
local_cluster_counts().clear();
}
}
finish {
// compute new clusters and counters
for (p in 0..(POINTS-1)) {
at (points.place(p,0)) async {
var closest:Long = -1;
var closest_dist:Float = Float.MAX_VALUE;
for (k in 0..(CLUSTERS-1)) {
var dist : Float = 0;
for (d in 0..(DIM-1)) {
val tmp = points(p,d) - local_curr_clusters()(k, d);
dist += tmp * tmp;
}
if (dist < closest_dist) {
closest_dist = dist;
closest = k;
}
}
atomic {
for (d in 0..(DIM-1)) {
local_new_clusters()(closest,d) += points(p,d);
}
local_cluster_counts()(closest)++;
}
}
}
}
for ([i,j] in old_central_clusters.indices()) {
old_central_clusters(i, j) = central_clusters(i, j);
central_clusters(i, j) = 0f;
}
central_cluster_counts.clear();
finish {
val central_clusters_gr = GlobalRef(central_clusters);
val central_cluster_counts_gr = GlobalRef(central_cluster_counts);
val there = here;
for (d in world) at (d) async {
// access PlaceLocalHandles 'here' and then data will be captured by at and transfered to 'there' for accumulation
val tmp_new_clusters = local_new_clusters();
val tmp_cluster_counts = local_cluster_counts();
at (there) atomic {
for ([i,j] in tmp_new_clusters.indices()) {
central_clusters_gr()(i,j) += tmp_new_clusters(i,j);
}
for (j in 0..(CLUSTERS-1)) {
central_cluster_counts_gr()(j) += tmp_cluster_counts(j);
}
}
}
}
for (k in 0..(CLUSTERS-1)) {
for (d in 0..(DIM-1)) {
central_clusters(k, d) /= central_cluster_counts(k);
}
}
// TEST FOR CONVERGENCE
var b:Boolean = true;
for ([i,j] in old_central_clusters.indices()) {
if (Math.abs(old_central_clusters(i, j)-central_clusters(i, j))>0.0001) {
b = false;
break;
}
}
if (b) break;
}
for (d in 0..(DIM-1)) {
for (k in 0..(CLUSTERS-1)) {
if (k>0)
Console.OUT.print(" ");
Console.OUT.print(central_clusters(k,d));
}
Console.OUT.println();
}
}
}
// vim: shiftwidth=4:tabstop=4:expandtab

View File

@@ -0,0 +1,144 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2015.
*/
import x10.array.Array;
import x10.array.Array_2;
import x10.compiler.Foreach;
import x10.util.Random;
/**
* A better formulation of distributed KMeans using coarse-grained asyncs to
* implement an allreduce pattern for cluster centers and counts.
*
* For a highly optimized and scalable, version of this benchmark see
* KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org)
*/
public class KMeansDistPlh {
static val DIM=2;
static val CLUSTERS=4;
static class ClusterState {
val clusters = new Array_2[Float](CLUSTERS, DIM);
val clusterCounts = new Rail[Int](CLUSTERS);
}
public static def main(args:Rail[String]) {
val numPoints = args.size > 0 ? Long.parse(args(0)) : 2000;
val iterations = args.size > 1 ? Long.parse(args(1)) : 50;
val world = Place.places();
val clusterStatePlh = PlaceLocalHandle.make[ClusterState](world, () => new ClusterState());
val currentClustersPlh = PlaceLocalHandle.make[Array_2[Float]](world, () => new Array_2[Float](CLUSTERS, DIM));
val pointsPlh = PlaceLocalHandle.make[Array_2[Float]](world, () => {
val rand = new Random(here.id);
return new Array_2[Float](numPoints/world.size(), DIM, (Long,Long)=>rand.nextFloat());
});
val centralCurrentClusters = new Array_2[Float](CLUSTERS, DIM);
val centralNewClusters = new Array_2[Float](CLUSTERS, DIM);
val centralClusterCounts = new Rail[Int](CLUSTERS);
// arbitrarily initialize central clusters to first few points
for ([i,j] in centralCurrentClusters.indices()) {
centralCurrentClusters(i,j) = pointsPlh()(i,j);
}
for (iter in 1..iterations) {
Console.OUT.println("Iteration: "+iter);
finish {
for (place in world) async {
val placeClusters = at(place) {
val currentClusters = currentClustersPlh();
Array.copy(centralCurrentClusters, currentClusters);
val clusterState = clusterStatePlh();
val newClusters = clusterState.clusters;
newClusters.clear();
val clusterCounts = clusterState.clusterCounts;
clusterCounts.clear();
// compute new clusters and counters
val points = pointsPlh();
for (p in 0..(points.numElems_1-1)) {
var closest:Long = -1;
var closestDist:Float = Float.MAX_VALUE;
for (k in 0..(CLUSTERS-1)) {
var dist : Float = 0;
for (d in 0..(DIM-1)) {
val tmp = points(p,d) - currentClusters(k, d);
dist += tmp * tmp;
}
if (dist < closestDist) {
closestDist = dist;
closest = k;
}
}
atomic {
for (d in 0..(DIM-1)) {
newClusters(closest,d) += points(p,d);
}
clusterCounts(closest)++;
}
}
clusterState
};
// combine place clusters to central
atomic {
for ([i,j] in centralNewClusters.indices()) {
centralNewClusters(i,j) += placeClusters.clusters(i,j);
}
for (j in 0..(CLUSTERS-1)) {
centralClusterCounts(j) += placeClusters.clusterCounts(j);
}
}
}
}
for (k in 0..(CLUSTERS-1)) {
for (d in 0..(DIM-1)) {
centralNewClusters(k, d) /= centralClusterCounts(k);
}
}
// TEST FOR CONVERGENCE
var b:Boolean = true;
for ([i,j] in centralCurrentClusters.indices()) {
if (Math.abs(centralCurrentClusters(i, j)-centralNewClusters(i, j)) > 0.0001) {
b = false;
break;
}
}
Array.copy(centralNewClusters, centralCurrentClusters);
if (b) break;
centralNewClusters.clear();
centralClusterCounts.clear();
}
for (d in 0..(DIM-1)) {
for (k in 0..(CLUSTERS-1)) {
if (k > 0)
Console.OUT.print(" ");
Console.OUT.print(centralCurrentClusters(k,d));
}
Console.OUT.println();
}
}
}
// vim: shiftwidth=4:tabstop=4:expandtab

192
samples/X10/KMeansSPMD.x10 Normal file
View File

@@ -0,0 +1,192 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.io.Console;
import x10.io.File;
import x10.io.Marshal;
import x10.io.IOException;
import x10.util.OptionsParser;
import x10.util.Option;
import x10.util.Team;
/**
* An SPMD formulation of KMeans.
*
* For a highly optimized and scalable version of this benchmark see
* KMeans.x10 in the X10 Benchmarks (separate download from x10-lang.org)
*/
public class KMeansSPMD {
public static def printClusters (clusters:Rail[Float], dims:long) {
for (d in 0..(dims-1)) {
for (k in 0..(clusters.size/dims-1)) {
if (k>0)
Console.OUT.print(" ");
Console.OUT.print(clusters(k*dims+d).toString());
}
Console.OUT.println();
}
}
public static def main (args:Rail[String]) {here == Place.FIRST_PLACE } {
val opts = new OptionsParser(args, [
Option("q","quiet","just print time taken"),
Option("v","verbose","print out each iteration"),
Option("h","help","this information")
], [
Option("p","points","location of data file"),
Option("i","iterations","quit after this many iterations"),
Option("c","clusters","number of clusters to find"),
Option("d","dim","number of dimensions"),
Option("s","slices","factor by which to oversubscribe computational resources"),
Option("n","num","quantity of points")
]);
if (opts.filteredArgs().size!=0L) {
Console.ERR.println("Unexpected arguments: "+opts.filteredArgs());
Console.ERR.println("Use -h or --help.");
System.setExitCode(1n);
return;
}
if (opts("-h")) {
Console.OUT.println(opts.usage(""));
return;
}
val fname = opts("-p", "points.dat");
val num_clusters=opts("-c",4);
val num_slices=opts("-s",1);
val num_global_points=opts("-n", 2000);
val iterations=opts("-i",50);
val dim=opts("-d", 4);
val verbose = opts("-v");
val quiet = opts("-q");
if (!quiet)
Console.OUT.println("points: "+num_global_points+" clusters: "+num_clusters+" dim: "+dim);
// file is dimension-major
val file = new File(fname);
val fr = file.openRead();
val init_points = (long) => Float.fromIntBits(Marshal.INT.read(fr).reverseBytes());
val num_file_points = (file.size() / dim / 4) as Int;
val file_points = new Rail[Float](num_file_points*dim, init_points);
val team = Team.WORLD;
val num_slice_points = num_global_points / num_slices / Place.numPlaces();
finish {
for (h in Place.places()) at(h) async {
var compute_time:Long = 0;
var comm_time:Long = 0;
var barrier_time:Long = 0;
val host_clusters = new Rail[Float](num_clusters*dim, (i:long)=>file_points(i));
val host_cluster_counts = new Rail[Int](num_clusters);
for (slice in 0..(num_slices-1)) {
// carve out local portion of points (point-major)
val offset = (slice*Place.numPlaces() + here.id) * num_slice_points;
if (verbose)
Console.OUT.println(h.toString()+" gets "+offset+" len "+num_slice_points);
val init = (i:long) => {
val p=i%num_slice_points;
val d=i/num_slice_points;
return file_points(offset+p+d*num_file_points);
};
// these are pretty big so allocate up front
val host_points = new Rail[Float](num_slice_points*dim, init);
val host_nearest = new Rail[Float](num_slice_points);
val start_time = System.currentTimeMillis();
barrier_time -= System.nanoTime();
team.barrier();
barrier_time += System.nanoTime();
main_loop: for (iter in 0..(iterations-1)) {
//if (offset==0) Console.OUT.println("Iteration: "+iter);
val old_clusters = new Rail[Float](host_clusters.size);
Rail.copy(host_clusters, 0L, old_clusters, 0L, host_clusters.size);
host_clusters.clear();
host_cluster_counts.clear();
compute_time -= System.nanoTime();
for (p in 0..(num_slice_points-1)) {
var closest:Long = -1;
var closest_dist:Float = Float.MAX_VALUE;
for (k in 0..(num_clusters-1)) {
var dist : Float = 0;
for (d in 0..(dim-1)) {
val tmp = host_points(p+d*num_slice_points) - old_clusters(k*dim+d);
dist += tmp * tmp;
}
if (dist < closest_dist) {
closest_dist = dist;
closest = k;
}
}
for (d in 0..(dim-1)) {
host_clusters(closest*dim+d) += host_points(p+d*num_slice_points);
}
host_cluster_counts(closest)++;
}
compute_time += System.nanoTime();
comm_time -= System.nanoTime();
team.allreduce(host_clusters, 0L, host_clusters, 0L, host_clusters.size, Team.ADD);
team.allreduce(host_cluster_counts, 0L, host_cluster_counts, 0L, host_cluster_counts.size, Team.ADD);
comm_time += System.nanoTime();
for (k in 0..(num_clusters-1)) {
for (d in 0..(dim-1)) host_clusters(k*dim+d) /= host_cluster_counts(k);
}
if (offset==0 && verbose) {
Console.OUT.println("Iteration: "+iter);
printClusters(host_clusters,dim);
}
// TEST FOR CONVERGENCE
for (j in 0..(num_clusters*dim-1)) {
if (true/*||Math.abs(clusters_old(j)-host_clusters(j))>0.0001*/) continue main_loop;
}
break;
} // main_loop
} // slice
Console.OUT.printf("%d: computation %.3f s communication %.3f s (barrier %.3f s)\n",
here.id, compute_time/1E9, comm_time/1E9, barrier_time/1E9);
team.barrier();
if (here.id == 0) {
Console.OUT.println("\nFinal results:");
printClusters(host_clusters,dim);
}
} // async
} // finish
}
}
// vim: shiftwidth=4:tabstop=4:expandtab

42
samples/X10/MontyPi.x10 Normal file
View File

@@ -0,0 +1,42 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.array.DistArray_Unique;
import x10.io.Console;
import x10.util.Random;
/**
* Calculation of an approximation to pi by using a Monte Carlo simulation
* (throwing darts into the unit square and determining the fraction that land
* in the unit circle).
*/
public class MontyPi {
public static def main(args:Rail[String]) {
if (args.size != 1L) {
Console.OUT.println("Usage: MontyPi <number of points>");
return;
}
val N = Long.parse(args(0));
val initializer = () => {
val r = new Random();
var result:Long = 0;
for(c in 1..N) {
val x = r.nextDouble();
val y = r.nextDouble();
if (x*x +y*y <= 1.0) result++;
}
result
};
val result = new DistArray_Unique[Long](Place.places(), initializer);
val pi = (4.0*result.reduce((x:Long,y:Long) => x+y, 0) as Double)/(N*Place.numPlaces());
Console.OUT.println("The value of pi is " + pi);
}
}

123
samples/X10/NQueensDist.x10 Normal file
View File

@@ -0,0 +1,123 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
* (C) Copyright Australian National University 2011.
*/
import x10.array.DistArray_Unique;
/**
* A distributed version of NQueens. Runs over NUM_PLACES.
* Identical to NQueensPar, except that work is distributed
* over multiple places rather than shared between threads.
*/
public class NQueensDist {
public static val EXPECTED_SOLUTIONS =
[0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184, 14772512];
val N:Long;
val P:Long;
val results:DistArray_Unique[Long];
val R:LongRange;
def this(N:Long, P:Long) {
this.N=N;
this.P=P;
this.results = new DistArray_Unique[Long]();
this.R = 0..(N-1);
}
def start() {
new Board().distSearch();
}
def run():Long {
finish start();
val result = results.reduce(((x:Long,y:Long) => x+y),0);
return result;
}
class Board {
val q: Rail[Long];
/** The number of low-rank positions that are fixed in this board for the purposes of search. */
var fixed:Long;
def this() {
q = new Rail[Long](N);
fixed = 0;
}
/**
* @return true if it is safe to put a queen in file <code>j</code>
* on the next rank after the last fixed position.
*/
def safe(j:Long) {
for (k in 0..(fixed-1)) {
if (j == q(k) || Math.abs(fixed-k) == Math.abs(j-q(k)))
return false;
}
return true;
}
/** Search all positions for the current board. */
def search() {
for (k in R) searchOne(k);
}
/**
* Modify the current board by adding a new queen
* in file <code>k</code> on rank <code>fixed</code>,
* and search for all safe positions with this prefix.
*/
def searchOne(k:Long) {
if (safe(k)) {
if (fixed==(N-1)) {
// all ranks safely filled
atomic NQueensDist.this.results(here.id)++;
} else {
q(fixed++) = k;
search();
fixed--;
}
}
}
/**
* Search this board, dividing the work between all places
* using a block distribution of the current free rank.
*/
def distSearch() {
val work = R.split(Place.numPlaces());
finish for (p in Place.places()) {
val myPiece = work(p.id);
at (p) async {
// implicit copy of 'this' made across the at divide
for (k in myPiece) {
searchOne(k);
}
}
}
}
}
public static def main(args:Rail[String]) {
val n = args.size > 0 ? Long.parse(args(0)) : 8;
Console.OUT.println("N=" + n);
//warmup
//finish new NQueensPar(12, 1).start();
val P = Place.numPlaces();
val nq = new NQueensDist(n,P);
var start:Long = -System.nanoTime();
val answer = nq.run();
val result = answer==EXPECTED_SOLUTIONS(n);
start += System.nanoTime();
start /= 1000000;
Console.OUT.println("NQueensDist " + nq.N + "(P=" + P +
") has " + answer + " solutions" +
(result? " (ok)." : " (wrong).") +
"time=" + start + "ms");
}
}

117
samples/X10/NQueensPar.x10 Normal file
View File

@@ -0,0 +1,117 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
* (C) Copyright Australian National University 2011.
*/
/**
* Compute the number of solutions to the N queens problem.
*/
public class NQueensPar {
public static val EXPECTED_SOLUTIONS =
[0, 1, 0, 0, 2, 10, 4, 40, 92, 352, 724, 2680, 14200, 73712, 365596, 2279184, 14772512];
val N:Int;
val P:Int;
var nSolutions:Int = 0n;
val R:IntRange;
def this(N:Int, P:Int) {
this.N=N;
this.P=P;
this.R = 0n..(N-1n);
}
def start() {
new Board().parSearch();
}
class Board {
val q: Rail[Int];
/** The number of low-rank positions that are fixed in this board for the purposes of search. */
var fixed:Int;
def this() {
q = new Rail[Int](N);
fixed = 0n;
}
def this(b:Board) {
this.q = new Rail[Int](b.q);
this.fixed = b.fixed;
}
/**
* @return true if it is safe to put a queen in file <code>j</code>
* on the next rank after the last fixed position.
*/
def safe(j:Int) {
for (k in 0n..(fixed-1n)) {
if (j == q(k) || Math.abs(fixed-k) == Math.abs(j-q(k)))
return false;
}
return true;
}
/** Search all positions for the current board. */
def search() {
for (k in R) searchOne(k);
}
/**
* Modify the current board by adding a new queen
* in file <code>k</code> on rank <code>fixed</code>,
* and search for all safe positions with this prefix.
*/
def searchOne(k:Int) {
if (safe(k)) {
if (fixed==(N-1n)) {
// all ranks safely filled
atomic NQueensPar.this.nSolutions++;
} else {
q(fixed++) = k;
search();
fixed--;
}
}
}
/**
* Search this board, dividing the work between threads
* using a block distribution of the current free rank.
*/
def parSearch() {
for (work in R.split(P)) async {
val board = new Board(this);
for (w in work) {
board.searchOne(w);
}
}
}
}
public static def main(args:Rail[String]) {
val n = args.size > 0 ? Int.parse(args(0)) : 8n;
Console.OUT.println("N=" + n);
//warmup
//finish new NQueensPar(12, 1).start();
val ps = [1n,2n,4n];
for (numTasks in ps) {
Console.OUT.println("starting " + numTasks + " tasks");
val nq = new NQueensPar(n,numTasks);
var start:Long = -System.nanoTime();
finish nq.start();
val result = (nq.nSolutions as Long)==EXPECTED_SOLUTIONS(nq.N);
start += System.nanoTime();
start /= 1000000;
Console.OUT.println("NQueensPar " + nq.N + "(P=" + numTasks +
") has " + nq.nSolutions + " solutions" +
(result? " (ok)." : " (wrong).") + "time=" + start + "ms");
}
}
}

73
samples/X10/QSort.x10 Normal file
View File

@@ -0,0 +1,73 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
/**
* Straightforward quicksort implementation using
* naive partition-in-the-middle and not bothering with
* well-known optimizations such as using insertion sort
* once the partitions get small. This is only intended
* as a simple example of an array-based program that
* combines a recirsive divide and conquer algorithm
* with async and finish, not as a highly efficient
* sorting procedure..
*/
public class QSort {
private static def partition(data:Rail[int], left:long, right:long) {
var i:long = left;
var j:long = right;
var tmp:int;
var pivot:long = data((left + right) / 2);
while (i <= j) {
while (data(i) < pivot) i++;
while (data(j) > pivot) j--;
if (i <= j) {
tmp = data(i);
data(i) = data(j);
data(j) = tmp;
i++;
j--;
}
}
return i;
}
public static def qsort(data:Rail[int], left:long, right:long) {
index:long = partition(data, left, right);
finish {
if (left < index - 1)
async qsort(data, left, index - 1);
if (index < right)
qsort(data, index, right);
}
}
public static def main(args:Rail[String]) {
val N = args.size>0 ? Long.parse(args(0)) : 100;
val r = new x10.util.Random();
val data = new Rail[int](N, (long)=>r.nextInt(9999n));
qsort(data, 0, N-1);
for (i in 0..(N-1)) {
Console.OUT.print(data(i));
if (i%10 == 9) {
Console.OUT.println();
} else {
Console.OUT.print(", ");
}
}
Console.OUT.println();
}
}

View File

@@ -0,0 +1,123 @@
/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2014.
*/
import x10.io.Console;
import x10.util.Random;
/**
* This class represents a real-world problem in graphics engines --
* determining which objects in a large sprawling world are close enough to the
* camera to be considered for rendering.
*
* It illustrates the usage of X10 structs to define new primitive types.
* In Native X10, structs are allocated within their containing object/stack frame
* and thus using structs instead of classes for Vector3 and WorldObject greatly
* improves the memory efficiency of the computation.
*
* @Author Dave Cunningham
* @Author Vijay Saraswat
*/
class StructSpheres {
static type Real = Float;
static struct Vector3(x:Real, y:Real, z:Real) {
public def getX () = x;
public def getY () = y;
public def getZ () = z;
public def add (other:Vector3)
= Vector3(this.x+other.x, this.y+other.y, this.z+other.z);
public def neg () = Vector3(-this.x, -this.y, -this.z);
public def sub (other:Vector3) = add(other.neg());
public def length () = Math.sqrtf(length2());
public def length2 () = x*x + y*y + z*z;
}
static struct WorldObject {
def this (x:Real, y:Real, z:Real, r:Real) {
pos = Vector3(x,y,z);
renderingDistance = r;
}
public def intersects (home:Vector3)
= home.sub(pos).length2() < renderingDistance*renderingDistance;
protected val pos:Vector3;
protected val renderingDistance:Real;
}
public static def compute():boolean {
val reps = 7500;
// The following correspond to a modern out-door computer game:
val num_objects = 50000;
val world_size = 6000;
val obj_max_size = 400;
val ran = new Random(0);
// the array can go on the heap
// but the elements ought to be /*inlined*/ in the array
val spheres =
new Rail[WorldObject](num_objects, (i:long) => {
val x = (ran.nextDouble()*world_size) as Real;
val y = (ran.nextDouble()*world_size) as Real;
val z = (ran.nextDouble()*world_size) as Real;
val r = (ran.nextDouble()*obj_max_size) as Real;
return WorldObject(x,y,z,r);
});
val time_start = System.nanoTime();
var counter : Long = 0;
// HOT LOOP BEGINS
for (c in 1..reps) {
val x = (ran.nextDouble()*world_size) as Real;
val y = (ran.nextDouble()*world_size) as Real;
val z = (ran.nextDouble()*world_size) as Real;
val pos = Vector3(x,y,z);
for (i in spheres.range()) {
if (spheres(i).intersects(pos)) {
counter++;
}
}
}
// HOT LOOP ENDS
val time_taken = System.nanoTime() - time_start;
Console.OUT.println("Total time: "+time_taken/1E9);
val expected = 109702;
val ok = counter == expected;
if (!ok) {
Console.ERR.println("number of intersections: "+counter
+" (expected "+expected+")");
}
return ok;
}
public static def main (Rail[String]) {
compute();
}
}

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|AnyCPU">
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x86">
<Configuration>Debug</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|AnyCPU">
<Configuration>Release</Configuration>
<Platform>AnyCPU</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x86">
<Configuration>Release</Configuration>
<Platform>x86</Platform>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>42fc11d8-64c6-4967-a15a-dfd787f68766</ProjectGuid>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup Condition="'$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0'">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).props" />
<PropertyGroup>
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>$(VersionNumberMajor).$(VersionNumberMinor)</MinimumVisualStudioVersion>
<DefaultLanguage>en-US</DefaultLanguage>
</PropertyGroup>
<ItemGroup>
<AppxManifest Include="package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<Content Include="css\browser.css" />
<Content Include="default.html" />
<Content Include="images\icons.png" />
<Content Include="images\logo_150x150.png" />
<Content Include="images\logo_310x150.png" />
<Content Include="images\logo_310x310.png" />
<Content Include="images\logo_44x44.png" />
<Content Include="images\logo_71x71.png" />
<Content Include="images\logo_badge.png" />
<Content Include="images\logo_bg.png" />
<Content Include="images\logo_splash.png" />
<Content Include="images\logo_store.png" />
<Content Include="js\components\address-bar.js" />
<Content Include="js\browser.js" />
<Content Include="js\components\favorites.js" />
<Content Include="js\components\navigation.js" />
<Content Include="js\components\settings.js" />
<Content Include="js\components\title-bar.js" />
<Content Include="js\components\webview.js" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NativeListener\NativeListener.vcxproj" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\$(WMSJSProjectDirectory)\Microsoft.VisualStudio.$(WMSJSProject).targets" />
<!-- To modify your build process, add your task inside one of the targets below then uncomment
that target and the DisableFastUpToDateCheck PropertyGroup.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
<PropertyGroup>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup>
-->
</Project>

View File

@@ -3,6 +3,7 @@ require "minitest/autorun"
require "mocha/setup"
require "linguist"
require 'color-proximity'
require 'licensee'
def fixtures_path
File.expand_path("../fixtures", __FILE__)

View File

@@ -301,6 +301,7 @@ class TestBlob < Minitest::Test
# Codemirror deps
assert sample_blob("codemirror/mode/blah.js").vendored?
assert sample_blob("codemirror/5.0/mode/blah.js").vendored?
# Debian packaging
assert sample_blob("debian/cron.d").vendored?
@@ -308,6 +309,12 @@ class TestBlob < Minitest::Test
# Erlang
assert sample_blob("rebar").vendored?
# git config files
assert_predicate fixture_blob("some/path/.gitattributes"), :vendored?
assert_predicate fixture_blob(".gitignore"), :vendored?
assert_predicate fixture_blob("special/path/.gitmodules"), :vendored?
# Minified JavaScript and CSS
assert sample_blob("foo.min.js").vendored?
assert sample_blob("foo.min.css").vendored?
@@ -326,9 +333,6 @@ class TestBlob < Minitest::Test
assert sample_blob("public/javascripts/controls.js").vendored?
assert sample_blob("public/javascripts/dragdrop.js").vendored?
# Samples
assert sample_blob("Samples/Ruby/foo.rb").vendored?
# jQuery
assert sample_blob("jquery.js").vendored?
assert sample_blob("public/javascripts/jquery.js").vendored?
@@ -358,6 +362,26 @@ class TestBlob < Minitest::Test
assert sample_blob("ui/minified/jquery.effects.blind.min.js").vendored?
assert sample_blob("ui/minified/jquery.ui.accordion.min.js").vendored?
# jQuery Gantt
assert sample_blob("web-app/jquery-gantt/js/jquery.fn.gantt.js").vendored?
# jQuery fancyBox
assert sample_blob("web-app/fancybox/jquery.fancybox.js").vendored?
# Fuel UX
assert sample_blob("web-app/fuelux/js/fuelux.js").vendored?
# jQuery File Upload
assert sample_blob("fileupload-9.0.0/jquery.fileupload-process.js").vendored?
# Slick
assert sample_blob("web-app/slickgrid/controls/slick.columnpicker.js").vendored?
# Leaflet plugins
assert sample_blob("leaflet-plugins/Leaflet.Coordinates-0.5.0.src.js").vendored?
assert sample_blob("leaflet-plugins/leaflet.draw-src.js").vendored?
assert sample_blob("leaflet-plugins/leaflet.spin.js").vendored?
# MooTools
assert sample_blob("public/javascripts/mootools-core-1.3.2-full-compat.js").vendored?
assert sample_blob("public/javascripts/mootools-core-1.3.2-full-compat-yc.js").vendored?
@@ -489,6 +513,11 @@ class TestBlob < Minitest::Test
# Crashlytics
assert sample_blob("Crashlytics.framework/Crashlytics.h").vendored?
# Xcode
assert sample_blob("myapp/My Template.xctemplate/___FILEBASENAME___.h").vendored?
assert sample_blob("myapp/My Images.xcassets/some/stuff.imageset/Contents.json").vendored?
assert !sample_blob("myapp/MyData.json").vendored?
end
def test_documentation
@@ -511,13 +540,15 @@ class TestBlob < Minitest::Test
assert_predicate fixture_blob("README"), :documentation?
assert_predicate fixture_blob("README.md"), :documentation?
assert_predicate fixture_blob("README.txt"), :documentation?
assert_predicate fixture_blob("Readme"), :documentation?
assert_predicate fixture_blob("readme"), :documentation?
assert_predicate fixture_blob("foo/README"), :documentation?
assert_predicate fixture_blob("CHANGE"), :documentation?
assert_predicate fixture_blob("CHANGE.md"), :documentation?
assert_predicate fixture_blob("CHANGE.txt"), :documentation?
assert_predicate fixture_blob("foo/CHANGE"), :documentation?
assert_predicate fixture_blob("CHANGELOG"), :documentation?
assert_predicate fixture_blob("CHANGELOG.md"), :documentation?
assert_predicate fixture_blob("CHANGELOG.txt"), :documentation?
@@ -526,15 +557,19 @@ class TestBlob < Minitest::Test
assert_predicate fixture_blob("CHANGES"), :documentation?
assert_predicate fixture_blob("CHANGES.md"), :documentation?
assert_predicate fixture_blob("CHANGES.txt"), :documentation?
assert_predicate fixture_blob("foo/CHANGES"), :documentation?
assert_predicate fixture_blob("foo/CHANGES"), :documentation?
assert_predicate fixture_blob("CONTRIBUTING"), :documentation?
assert_predicate fixture_blob("CONTRIBUTING.md"), :documentation?
assert_predicate fixture_blob("CONTRIBUTING.txt"), :documentation?
assert_predicate fixture_blob("foo/CONTRIBUTING"), :documentation?
assert_predicate fixture_blob("examples/some-file.pl"), :documentation?
assert_predicate fixture_blob("Examples/some-example-file.rb"), :documentation?
assert_predicate fixture_blob("LICENSE"), :documentation?
assert_predicate fixture_blob("LICENCE.md"), :documentation?
assert_predicate fixture_blob("License.txt"), :documentation?
assert_predicate fixture_blob("LICENSE.txt"), :documentation?
assert_predicate fixture_blob("foo/LICENSE"), :documentation?
@@ -549,6 +584,11 @@ class TestBlob < Minitest::Test
assert_predicate fixture_blob("foo/INSTALL"), :documentation?
refute_predicate fixture_blob("foo.md"), :documentation?
# Samples
assert sample_blob("Samples/Ruby/foo.rb").documentation?
assert_predicate fixture_blob("INSTALL.txt"), :documentation?
end
def test_language

View File

@@ -3,12 +3,13 @@ require_relative "./helper"
class TestGrammars < Minitest::Test
ROOT = File.expand_path("../..", __FILE__)
LICENSE_WHITELIST = [
PROJECT_WHITELIST = [
# This grammar's MIT license is inside a subdirectory.
"vendor/grammars/SublimePapyrus",
# This grammar has a nonstandard but acceptable license.
"vendor/grammars/gap-tmbundle",
"vendor/grammars/factor",
# These grammars have no license but have been grandfathered in. New grammars
# must have a license that allows redistribution.
@@ -16,6 +17,23 @@ class TestGrammars < Minitest::Test
"vendor/grammars/x86-assembly-textmate-bundle"
].freeze
# List of allowed SPDX license names
LICENSE_WHITELIST = %w[
apache-2.0
bsd-2-clause
bsd-3-clause
cc-by-sa-3.0
gpl-2.0
gpl-3.0
lgpl-3.0
mit
mpl-2.0
textmate
unlicense
wtfpl
zlib
].freeze
def setup
@grammars = YAML.load(File.read(File.join(ROOT, "grammars.yml")))
end
@@ -62,48 +80,38 @@ class TestGrammars < Minitest::Test
end
end
def test_submodules_have_recognized_licenses
unrecognized = submodule_licenses.select { |k,v| v.nil? && Licensee::Project.new(k).license_file }
unrecognized.reject! { |k,v| PROJECT_WHITELIST.include?(k) }
message = "The following submodules have unrecognized licenses:\n* #{unrecognized.keys.join("\n* ")}\n"
message << "Please ensure that the project's LICENSE file contains the full text of the license."
assert_equal Hash.new, unrecognized, message
end
def test_submodules_have_licenses
categories = submodule_paths.group_by do |submodule|
files = Dir[File.join(ROOT, submodule, "*")]
license = files.find { |path| File.basename(path) =~ /\b(un)?licen[cs]e\b/i } || files.find { |path| File.basename(path) =~ /\bcopying\b/i }
if license.nil?
if readme = files.find { |path| File.basename(path) =~ /\Areadme\b/i }
license = readme if File.read(readme) =~ /\blicen[cs]e\b/i
end
end
if license.nil?
:unlicensed
elsif classify_license(license)
:licensed
else
:unrecognized
end
end
unlicensed = submodule_licenses.select { |k,v| v.nil? }.reject { |k,v| PROJECT_WHITELIST.include?(k) }
message = "The following submodules don't have licenses:\n* #{unlicensed.keys.join("\n* ")}\n"
message << "Please ensure that the project has a LICENSE file, and that the LICENSE file contains the full text of the license."
assert_equal Hash.new, unlicensed, message
end
unlicensed = categories[:unlicensed] || []
unrecognized = categories[:unrecognized] || []
disallowed_unlicensed = unlicensed - LICENSE_WHITELIST
disallowed_unrecognized = unrecognized - LICENSE_WHITELIST
extra_whitelist_entries = LICENSE_WHITELIST - (unlicensed | unrecognized)
def test_submodules_have_approved_licenses
unapproved = submodule_licenses.reject { |k,v| LICENSE_WHITELIST.include?(v) || PROJECT_WHITELIST.include?(k) }.map { |k,v| "#{k}: #{v}"}
message = "The following submodules have unapproved licenses:\n* #{unapproved.join("\n* ")}\n"
message << "The license must be added to the LICENSE_WHITELIST in /test/test_grammars.rb once approved."
assert_equal [], unapproved, message
end
message = ""
if disallowed_unlicensed.any?
message << "The following grammar submodules don't seem to have a license. All grammars must have a license that permits redistribution.\n"
message << disallowed_unlicensed.sort.join("\n")
end
if disallowed_unrecognized.any?
message << "\n\n" unless message.empty?
message << "The following grammar submodules have an unrecognized license. Please update #{__FILE__} to recognize the license.\n"
message << disallowed_unrecognized.sort.join("\n")
end
if extra_whitelist_entries.any?
message << "\n\n" unless message.empty?
message << "The following grammar submodules are listed in LICENSE_WHITELIST but either have a license (yay!)\n"
message << "or have been removed from the repository. Please remove them from the whitelist.\n"
message << extra_whitelist_entries.sort.join("\n")
end
def test_submodules_whitelist_has_no_extra_entries
extra_whitelist_entries = PROJECT_WHITELIST - submodule_licenses.select { |k,v| v.nil? }.keys
not_present = extra_whitelist_entries.reject { |k,v| Dir.exists?(k) }
licensed = extra_whitelist_entries.select { |k,v| submodule_licenses[k] }
assert disallowed_unlicensed.empty? && disallowed_unrecognized.empty? && extra_whitelist_entries.empty?, message
msg = "The following whitelisted submodules don't appear to be part of the project:\n* #{not_present.join("\n* ")}"
assert_equal [], not_present, msg
msg = "The following whitelisted submodules actually have licenses and don't need to be whitelisted:\n* #{licensed.join("\n* ")}"
assert_equal [], licensed, msg
end
private
@@ -112,30 +120,57 @@ class TestGrammars < Minitest::Test
@submodule_paths ||= `git config --list --file "#{File.join(ROOT, ".gitmodules")}"`.lines.grep(/\.path=/).map { |line| line.chomp.split("=", 2).last }
end
# Returns a hash of submodules in the form of submodule_path => license
def submodule_licenses
@@submodule_licenses ||= begin
submodules = {}
submodule_paths.each { |submodule| submodules[submodule] = submodule_license(submodule) }
submodules
end
end
# Given the path to a submodule, return its SPDX-compliant license key
def submodule_license(submodule)
# Prefer Licensee to detect a submodule's license
project = Licensee::Project.new(submodule)
return project.license.key if project.license
# We know a license file exists, but Licensee wasn't able to detect the license,
# Let's try our own more permissive regex method
if project.license_file
path = File.expand_path project.license_file.path, submodule
license = classify_license(path)
return license if license
end
# Neither Licensee nor our own regex was able to detect the license, let's check the readme
files = Dir[File.join(ROOT, submodule, "*")]
if readme = files.find { |path| File.basename(path) =~ /\Areadme\b/i }
classify_license(readme)
end
end
def classify_license(path)
content = File.read(path)
return unless content =~ /\blicen[cs]e\b/i
if content.include?("Apache License") && content.include?("2.0")
"Apache 2.0"
"apache-2.0"
elsif content.include?("GNU") && content =~ /general/i && content =~ /public/i
if content =~ /version 2/i
"GPLv2"
"gpl-2.0"
elsif content =~ /version 3/i
"GPLv3"
"gpl-3.0"
end
elsif content.include?("GPL") && content.include?("http://www.gnu.org/licenses/gpl.html")
"GPLv3"
elsif content.include?("Creative Commons")
"CC"
"gpl-3.0"
elsif content.include?("Creative Commons Attribution-Share Alike 3.0")
"cc-by-sa-3.0"
elsif content.include?("tidy-license.txt") || content.include?("If not otherwise specified (see below)")
"textmate"
elsif content =~ /^\s*[*-]\s+Redistribution/ || content.include?("Redistributions of source code")
"BSD"
elsif content.include?("Permission is hereby granted") || content =~ /\bMIT\b/
"MIT"
elsif content.include?("unlicense.org")
"unlicense"
"mit"
elsif content.include?("http://www.wtfpl.net/txt/copying/")
"WTFPL"
"wtfpl"
elsif content.include?("zlib") && content.include?("license") && content.include?("2. Altered source versions must be plainly marked as such")
"zlib"
end

View File

@@ -33,6 +33,101 @@ class TestHeuristcs < Minitest::Test
end
end
def test_detect_still_works_if_nothing_matches
blob = Linguist::FileBlob.new(File.join(samples_path, "Objective-C/hello.m"))
match = Language.detect(blob)
assert_equal Language["Objective-C"], match
end
# Candidate languages = ["AGS Script", "AsciiDoc", "Public Key"]
def test_asc_by_heuristics
assert_heuristics({
"AsciiDoc" => all_fixtures("AsciiDoc", "*.asc"),
"AGS Script" => all_fixtures("AGS Script", "*.asc"),
"Public Key" => all_fixtures("Public Key", "*.asc")
})
end
def test_bb_by_heuristics
assert_heuristics({
"BitBake" => all_fixtures("BitBake", "*.bb"),
"BlitzBasic" => all_fixtures("BlitzBasic", "*.bb")
})
end
def test_ch_by_heuristics
assert_heuristics({
"xBase" => all_fixtures("xBase", ".ch")
})
end
def test_cl_by_heuristics
assert_heuristics({
"Common Lisp" => all_fixtures("Common Lisp", "*.cl"),
"OpenCL" => all_fixtures("OpenCL", "*.cl")
})
end
def test_cs_by_heuristics
assert_heuristics({
"C#" => all_fixtures("C#", "*.cs"),
"Smalltalk" => all_fixtures("Smalltalk", "*.cs")
})
end
# Candidate languages = ["ECL", "ECLiPSe"]
def test_ecl_by_heuristics
assert_heuristics({
"ECL" => all_fixtures("ECL", "*.ecl"),
"ECLiPSe" => all_fixtures("ECLiPSe", "*.ecl")
})
end
def test_f_by_heuristics
assert_heuristics({
"FORTRAN" => all_fixtures("FORTRAN", "*.f") + all_fixtures("FORTRAN", "*.for"),
"Forth" => all_fixtures("Forth", "*.f") + all_fixtures("Forth", "*.for")
})
end
def test_fr_by_heuristics
assert_heuristics({
"Frege" => all_fixtures("Frege", "*.fr"),
"Forth" => all_fixtures("Forth", "*.fr"),
"Text" => all_fixtures("Text", "*.fr")
})
end
def test_fs_by_heuristics
assert_heuristics({
"F#" => all_fixtures("F#", "*.fs"),
"Forth" => all_fixtures("Forth", "*.fs"),
"GLSL" => all_fixtures("GLSL", "*.fs")
})
end
# Candidate languages = ["Hack", "PHP"]
def test_hack_by_heuristics
assert_heuristics({
"Hack" => all_fixtures("Hack", "*.php"),
"PHP" => all_fixtures("PHP", "*.php")
})
end
def test_ls_by_heuristics
assert_heuristics({
"LiveScript" => all_fixtures("LiveScript", "*.ls"),
"LoomScript" => all_fixtures("LoomScript", "*.ls")
})
end
def test_lsp_by_heuristics
assert_heuristics({
"Common Lisp" => all_fixtures("Common Lisp", "*.lsp") + all_fixtures("Common Lisp", "*.lisp"),
"NewLisp" => all_fixtures("NewLisp", "*.lsp") + all_fixtures("NewLisp", "*.lisp")
})
end
# Candidate languages = ["C++", "Objective-C"]
def test_obj_c_by_heuristics
# Only calling out '.h' filenames as these are the ones causing issues
@@ -43,12 +138,6 @@ class TestHeuristcs < Minitest::Test
})
end
def test_detect_still_works_if_nothing_matches
blob = Linguist::FileBlob.new(File.join(samples_path, "Objective-C/hello.m"))
match = Language.detect(blob)
assert_equal Language["Objective-C"], match
end
# Candidate languages = ["Perl", "Perl6", "Prolog"]
def test_pl_prolog_perl_by_heuristics
assert_heuristics({
@@ -66,14 +155,6 @@ class TestHeuristcs < Minitest::Test
})
end
# Candidate languages = ["ECL", "Prolog"]
def test_ecl_prolog_by_heuristics
assert_heuristics({
"ECL" => all_fixtures("ECL", "*.ecl"),
"Prolog" => all_fixtures("Prolog", "*.ecl")
})
end
# Candidate languages = ["IDL", "Prolog", "QMake", "INI"]
def test_pro_by_heuristics
assert_heuristics({
@@ -84,34 +165,10 @@ class TestHeuristcs < Minitest::Test
})
end
# Candidate languages = ["AGS Script", "AsciiDoc", "Public Key"]
def test_asc_by_heuristics
def test_r_by_heuristics
assert_heuristics({
"AsciiDoc" => all_fixtures("AsciiDoc", "*.asc"),
"AGS Script" => all_fixtures("AGS Script", "*.asc"),
"Public Key" => all_fixtures("Public Key", "*.asc")
})
end
def test_cl_by_heuristics
assert_heuristics({
"Common Lisp" => all_fixtures("Common Lisp", "*.cl"),
"OpenCL" => all_fixtures("OpenCL", "*.cl")
})
end
def test_f_by_heuristics
assert_heuristics({
"FORTRAN" => all_fixtures("FORTRAN", "*.f") + all_fixtures("FORTRAN", "*.for"),
"Forth" => all_fixtures("Forth", "*.f") + all_fixtures("Forth", "*.for")
})
end
# Candidate languages = ["Hack", "PHP"]
def test_hack_by_heuristics
assert_heuristics({
"Hack" => all_fixtures("Hack", "*.php"),
"PHP" => all_fixtures("PHP", "*.php")
"R" => all_fixtures("R", "*.r") + all_fixtures("R", "*.R"),
"Rebol" => all_fixtures("Rebol", "*.r")
})
end
@@ -123,47 +180,13 @@ class TestHeuristcs < Minitest::Test
})
end
def test_fs_by_heuristics
# Candidate languages = ["Perl", "Perl6"]
def test_t_perl_by_heuristics
assert_heuristics({
"F#" => all_fixtures("F#", "*.fs"),
"Forth" => all_fixtures("Forth", "*.fs"),
"GLSL" => all_fixtures("GLSL", "*.fs")
})
end
def test_fr_by_heuristics
assert_heuristics({
"Frege" => all_fixtures("Frege", "*.fr"),
"Forth" => all_fixtures("Forth", "*.fr"),
"Text" => all_fixtures("Text", "*.fr")
})
end
def test_bb_by_heuristics
assert_heuristics({
"BitBake" => all_fixtures("BitBake", "*.bb"),
"BlitzBasic" => all_fixtures("BlitzBasic", "*.bb")
})
end
def test_lsp_by_heuristics
assert_heuristics({
"Common Lisp" => all_fixtures("Common Lisp", "*.lsp") + all_fixtures("Common Lisp", "*.lisp"),
"NewLisp" => all_fixtures("NewLisp", "*.lsp") + all_fixtures("NewLisp", "*.lisp")
})
end
def test_cs_by_heuristics
assert_heuristics({
"C#" => all_fixtures("C#", "*.cs"),
"Smalltalk" => all_fixtures("Smalltalk", "*.cs")
})
end
def test_ls_by_heuristics
assert_heuristics({
"LiveScript" => all_fixtures("LiveScript", "*.ls"),
"LoomScript" => all_fixtures("LoomScript", "*.ls")
"Perl" => all_fixtures("Perl", "*.t"),
"Perl6" => ["Perl6/01-dash-uppercase-i.t", "Perl6/01-parse.t", "Perl6/advent2009-day16.t",
"Perl6/basic-open.t", "Perl6/calendar.t", "Perl6/for.t", "Perl6/hash.t",
"Perl6/listquote-whitespace.t"]
})
end
@@ -173,17 +196,4 @@ class TestHeuristcs < Minitest::Test
"XML" => all_fixtures("XML", "*.ts")
})
end
def test_ch_by_heuristics
assert_heuristics({
"xBase" => all_fixtures("xBase", ".ch")
})
end
def test_r_by_heuristics
assert_heuristics({
"R" => all_fixtures("R", "*.r") + all_fixtures("R", "*.R"),
"Rebol" => all_fixtures("Rebol", "*.r")
})
end
end

View File

@@ -32,6 +32,18 @@ class TestPedantic < Minitest::Test
end
end
def test_heuristics_are_sorted
file = File.expand_path("../../lib/linguist/heuristics.rb", __FILE__)
heuristics = open(file).each.grep(/^ *disambiguate/)
assert_sorted heuristics
end
def test_heuristics_tests_are_sorted
file = File.expand_path("../test_heuristics.rb", __FILE__)
tests = open(file).each.grep(/^ *def test_[a-z_]+_by_heuristics/)
assert_sorted tests
end
def assert_sorted(list)
list.each_cons(2) do |previous, item|
flunk "#{previous} should come after #{item}" if previous > item

1
vendor/grammars/X10 vendored Submodule

Submodule vendor/grammars/X10 added at 2bae6e77fa

1
vendor/grammars/st2-zonefile vendored Submodule