summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/languages.rst1
-rw-r--r--pygments/lexers/_mapping.py4
-rw-r--r--pygments/lexers/c_cpp.py4
-rw-r--r--pygments/lexers/chapel.py7
-rw-r--r--pygments/lexers/css.py1
-rw-r--r--pygments/lexers/javascript.py2
-rw-r--r--pygments/lexers/julia.py4
-rw-r--r--pygments/lexers/jvm.py2
-rw-r--r--pygments/lexers/python.py9
-rw-r--r--pygments/lexers/robotframework.py30
-rw-r--r--pygments/lexers/rust.py113
-rw-r--r--pygments/lexers/shell.py2
-rw-r--r--pygments/lexers/templates.py2
-rw-r--r--tests/examplefiles/99_bottles_of_beer.chpl13
-rw-r--r--tests/examplefiles/eval.rs606
-rw-r--r--tests/examplefiles/robotframework_test.txt1
-rw-r--r--tests/examplefiles/rust_example.rs235
-rw-r--r--tests/examplefiles/test.gradle20
18 files changed, 745 insertions, 311 deletions
diff --git a/doc/languages.rst b/doc/languages.rst
index 1d5c3155..13555ccf 100644
--- a/doc/languages.rst
+++ b/doc/languages.rst
@@ -86,7 +86,6 @@ Programming languages
* Visual FoxPro
* XQuery
* Zephir
- </ul>
Template languages
------------------
diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py
index 2b836ac6..6595131c 100644
--- a/pygments/lexers/_mapping.py
+++ b/pygments/lexers/_mapping.py
@@ -142,7 +142,7 @@ LEXERS = {
'GosuLexer': ('pygments.lexers.jvm', 'Gosu', ('gosu',), ('*.gs', '*.gsx', '*.gsp', '*.vark'), ('text/x-gosu',)),
'GosuTemplateLexer': ('pygments.lexers.jvm', 'Gosu Template', ('gst',), ('*.gst',), ('text/x-gosu-template',)),
'GroffLexer': ('pygments.lexers.markup', 'Groff', ('groff', 'nroff', 'man'), ('*.[1234567]', '*.man'), ('application/x-troff', 'text/troff')),
- 'GroovyLexer': ('pygments.lexers.jvm', 'Groovy', ('groovy',), ('*.groovy',), ('text/x-groovy',)),
+ 'GroovyLexer': ('pygments.lexers.jvm', 'Groovy', ('groovy',), ('*.groovy', '*.gradle'), ('text/x-groovy',)),
'HamlLexer': ('pygments.lexers.html', 'Haml', ('haml',), ('*.haml',), ('text/x-haml',)),
'HandlebarsHtmlLexer': ('pygments.lexers.templates', 'HTML+Handlebars', ('html+handlebars',), ('*.handlebars', '*.hbs'), ('text/html+handlebars', 'text/x-handlebars-template')),
'HandlebarsLexer': ('pygments.lexers.templates', 'Handlebars', ('handlebars',), (), ()),
@@ -175,7 +175,7 @@ LEXERS = {
'JavascriptDjangoLexer': ('pygments.lexers.templates', 'JavaScript+Django/Jinja', ('js+django', 'javascript+django', 'js+jinja', 'javascript+jinja'), (), ('application/x-javascript+django', 'application/x-javascript+jinja', 'text/x-javascript+django', 'text/x-javascript+jinja', 'text/javascript+django', 'text/javascript+jinja')),
'JavascriptErbLexer': ('pygments.lexers.templates', 'JavaScript+Ruby', ('js+erb', 'javascript+erb', 'js+ruby', 'javascript+ruby'), (), ('application/x-javascript+ruby', 'text/x-javascript+ruby', 'text/javascript+ruby')),
'JavascriptGenshiLexer': ('pygments.lexers.templates', 'JavaScript+Genshi Text', ('js+genshitext', 'js+genshi', 'javascript+genshitext', 'javascript+genshi'), (), ('application/x-javascript+genshi', 'text/x-javascript+genshi', 'text/javascript+genshi')),
- 'JavascriptLexer': ('pygments.lexers.javascript', 'JavaScript', ('js', 'javascript'), ('*.js',), ('application/javascript', 'application/x-javascript', 'text/x-javascript', 'text/javascript')),
+ 'JavascriptLexer': ('pygments.lexers.javascript', 'JavaScript', ('js', 'javascript'), ('*.js', '*.jsm'), ('application/javascript', 'application/x-javascript', 'text/x-javascript', 'text/javascript')),
'JavascriptPhpLexer': ('pygments.lexers.templates', 'JavaScript+PHP', ('js+php', 'javascript+php'), (), ('application/x-javascript+php', 'text/x-javascript+php', 'text/javascript+php')),
'JavascriptSmartyLexer': ('pygments.lexers.templates', 'JavaScript+Smarty', ('js+smarty', 'javascript+smarty'), (), ('application/x-javascript+smarty', 'text/x-javascript+smarty', 'text/javascript+smarty')),
'JsonLdLexer': ('pygments.lexers.data', 'JSON-LD', ('jsonld', 'json-ld'), ('*.jsonld',), ('application/ld+json',)),
diff --git a/pygments/lexers/c_cpp.py b/pygments/lexers/c_cpp.py
index bbac406e..35ea517f 100644
--- a/pygments/lexers/c_cpp.py
+++ b/pygments/lexers/c_cpp.py
@@ -28,8 +28,10 @@ class CFamilyLexer(RegexLexer):
#: optional Comment or Whitespace
_ws = r'(?:\s|//.*?\n|/[*].*?[*]/)+'
+
+ # The trailing ?, rather than *, avoids a geometric performance drop here.
#: only one /* */ style comment
- _ws1 = r'\s*(?:/[*].*?[*]/\s*)*'
+ _ws1 = r'\s*(?:/[*].*?[*]/\s*)?'
tokens = {
'whitespace': [
diff --git a/pygments/lexers/chapel.py b/pygments/lexers/chapel.py
index 520be37b..6fb6920c 100644
--- a/pygments/lexers/chapel.py
+++ b/pygments/lexers/chapel.py
@@ -46,9 +46,10 @@ class ChapelLexer(RegexLexer):
'continue', 'delete', 'dmapped', 'do', 'domain', 'else', 'enum',
'export', 'extern', 'for', 'forall', 'if', 'index', 'inline',
'iter', 'label', 'lambda', 'let', 'local', 'new', 'noinit', 'on',
- 'otherwise', 'pragma', 'reduce', 'return', 'scan', 'select',
- 'serial', 'single', 'sparse', 'subdomain', 'sync', 'then', 'use',
- 'when', 'where', 'while', 'with', 'yield', 'zip'), suffix=r'\b'),
+ 'otherwise', 'pragma', 'private', 'public', 'reduce', 'return',
+ 'scan', 'select', 'serial', 'single', 'sparse', 'subdomain',
+ 'sync', 'then', 'use', 'when', 'where', 'while', 'with', 'yield',
+ 'zip'), suffix=r'\b'),
Keyword),
(r'(proc)((?:\s|\\\s)+)', bygroups(Keyword, Text), 'procname'),
(r'(class|module|record|union)(\s+)', bygroups(Keyword, Text),
diff --git a/pygments/lexers/css.py b/pygments/lexers/css.py
index c11e7ec0..6f27d63c 100644
--- a/pygments/lexers/css.py
+++ b/pygments/lexers/css.py
@@ -484,6 +484,7 @@ class ScssLexer(RegexLexer):
(r'[^\s:="\[]+', Name.Attribute),
(r'#\{', String.Interpol, 'interpolation'),
(r'[ \t]*:', Operator, 'value'),
+ default('#pop'),
],
'inline-comment': [
diff --git a/pygments/lexers/javascript.py b/pygments/lexers/javascript.py
index aed8438e..7dcfbb4b 100644
--- a/pygments/lexers/javascript.py
+++ b/pygments/lexers/javascript.py
@@ -36,7 +36,7 @@ class JavascriptLexer(RegexLexer):
name = 'JavaScript'
aliases = ['js', 'javascript']
- filenames = ['*.js', ]
+ filenames = ['*.js', '*.jsm', ]
mimetypes = ['application/javascript', 'application/x-javascript',
'text/x-javascript', 'text/javascript', ]
diff --git a/pygments/lexers/julia.py b/pygments/lexers/julia.py
index 1b7d543a..1304b395 100644
--- a/pygments/lexers/julia.py
+++ b/pygments/lexers/julia.py
@@ -30,6 +30,8 @@ class JuliaLexer(RegexLexer):
filenames = ['*.jl']
mimetypes = ['text/x-julia', 'application/x-julia']
+ flags = re.MULTILINE | re.UNICODE
+
builtins = [
'exit', 'whos', 'edit', 'load', 'is', 'isa', 'isequal', 'typeof', 'tuple',
'ntuple', 'uid', 'hash', 'finalizer', 'convert', 'promote', 'subtype',
@@ -89,7 +91,7 @@ class JuliaLexer(RegexLexer):
# names
(r'@[\w.]+', Name.Decorator),
- (r'[a-zA-Z_]\w*', Name),
+ (u'[a-zA-Z_\u00A1-\U0010FFFF][a-zA-Z_0-9\u00A1-\U0010FFFF]*!*', Name),
# numbers
(r'(\d+(_\d+)+\.\d*|\d*\.\d+(_\d+)+)([eEf][+-]?[0-9]+)?', Number.Float),
diff --git a/pygments/lexers/jvm.py b/pygments/lexers/jvm.py
index 6b302c7e..4d3c9159 100644
--- a/pygments/lexers/jvm.py
+++ b/pygments/lexers/jvm.py
@@ -457,7 +457,7 @@ class GroovyLexer(RegexLexer):
name = 'Groovy'
aliases = ['groovy']
- filenames = ['*.groovy']
+ filenames = ['*.groovy','*.gradle']
mimetypes = ['text/x-groovy']
flags = re.MULTILINE | re.DOTALL
diff --git a/pygments/lexers/python.py b/pygments/lexers/python.py
index 49c15b6d..ea97b855 100644
--- a/pygments/lexers/python.py
+++ b/pygments/lexers/python.py
@@ -215,10 +215,10 @@ class Python3Lexer(RegexLexer):
tokens = PythonLexer.tokens.copy()
tokens['keywords'] = [
(words((
- 'assert', 'break', 'continue', 'del', 'elif', 'else', 'except',
- 'finally', 'for', 'global', 'if', 'lambda', 'pass', 'raise',
- 'nonlocal', 'return', 'try', 'while', 'yield', 'yield from', 'as',
- 'with'), suffix=r'\b'),
+ 'assert', 'async', 'await', 'break', 'continue', 'del', 'elif',
+ 'else', 'except', 'finally', 'for', 'global', 'if', 'lambda', 'pass',
+ 'raise', 'nonlocal', 'return', 'try', 'while', 'yield', 'yield from',
+ 'as', 'with'), suffix=r'\b'),
Keyword),
(words((
'True', 'False', 'None'), suffix=r'\b'),
@@ -272,6 +272,7 @@ class Python3Lexer(RegexLexer):
tokens['backtick'] = []
tokens['name'] = [
(r'@\w+', Name.Decorator),
+ (r'@', Operator), # new matrix multiplication operator
(uni_name, Name),
]
tokens['funcname'] = [
diff --git a/pygments/lexers/robotframework.py b/pygments/lexers/robotframework.py
index 56996fa8..eab06efe 100644
--- a/pygments/lexers/robotframework.py
+++ b/pygments/lexers/robotframework.py
@@ -87,7 +87,7 @@ class RobotFrameworkLexer(Lexer):
class VariableTokenizer(object):
def tokenize(self, string, token):
- var = VariableSplitter(string, identifiers='$@%')
+ var = VariableSplitter(string, identifiers='$@%&')
if var.start < 0 or token in (COMMENT, ERROR):
yield string, token
return
@@ -205,7 +205,7 @@ class Tokenizer(object):
def _is_assign(self, value):
if value.endswith('='):
value = value[:-1].strip()
- var = VariableSplitter(value, identifiers='$@')
+ var = VariableSplitter(value, identifiers='$@&')
return var.start == 0 and var.end == len(value)
@@ -262,7 +262,7 @@ class TestCaseSetting(Setting):
class KeywordSetting(TestCaseSetting):
_keyword_settings = ('teardown',)
- _other_settings = ('documentation', 'arguments', 'return', 'timeout')
+ _other_settings = ('documentation', 'arguments', 'return', 'timeout', 'tags')
class Variable(Tokenizer):
@@ -465,13 +465,13 @@ class VariableSplitter:
self.identifier = self._variable_chars[0]
self.base = ''.join(self._variable_chars[2:-1])
self.end = self.start + len(self._variable_chars)
- if self._has_list_variable_index():
- self.index = ''.join(self._list_variable_index_chars[1:-1])
- self.end += len(self._list_variable_index_chars)
+ if self._has_list_or_dict_variable_index():
+ self.index = ''.join(self._list_and_dict_variable_index_chars[1:-1])
+ self.end += len(self._list_and_dict_variable_index_chars)
- def _has_list_variable_index(self):
- return self._list_variable_index_chars\
- and self._list_variable_index_chars[-1] == ']'
+ def _has_list_or_dict_variable_index(self):
+ return self._list_and_dict_variable_index_chars\
+ and self._list_and_dict_variable_index_chars[-1] == ']'
def _split(self, string):
start_index, max_index = self._find_variable(string)
@@ -479,7 +479,7 @@ class VariableSplitter:
self._open_curly = 1
self._state = self._variable_state
self._variable_chars = [string[start_index], '{']
- self._list_variable_index_chars = []
+ self._list_and_dict_variable_index_chars = []
self._string = string
start_index += 2
for index, char in enumerate(string[start_index:]):
@@ -530,14 +530,14 @@ class VariableSplitter:
if char == '}' and not self._is_escaped(self._string, index):
self._open_curly -= 1
if self._open_curly == 0:
- if not self._is_list_variable():
+ if not self._is_list_or_dict_variable():
raise StopIteration
self._state = self._waiting_list_variable_index_state
elif char in self._identifiers:
self._state = self._internal_variable_start_state
- def _is_list_variable(self):
- return self._variable_chars[0] == '@'
+ def _is_list_or_dict_variable(self):
+ return self._variable_chars[0] in ('@','&')
def _internal_variable_start_state(self, char, index):
self._state = self._variable_state
@@ -551,10 +551,10 @@ class VariableSplitter:
def _waiting_list_variable_index_state(self, char, index):
if char != '[':
raise StopIteration
- self._list_variable_index_chars.append(char)
+ self._list_and_dict_variable_index_chars.append(char)
self._state = self._list_variable_index_state
def _list_variable_index_state(self, char, index):
- self._list_variable_index_chars.append(char)
+ self._list_and_dict_variable_index_chars.append(char)
if char == ']':
raise StopIteration
diff --git a/pygments/lexers/rust.py b/pygments/lexers/rust.py
index 2ca860d6..d8939678 100644
--- a/pygments/lexers/rust.py
+++ b/pygments/lexers/rust.py
@@ -10,7 +10,7 @@
"""
from pygments.lexer import RegexLexer, include, bygroups, words, default
-from pygments.token import Comment, Operator, Keyword, Name, String, \
+from pygments.token import Text, Comment, Operator, Keyword, Name, String, \
Number, Punctuation, Whitespace
__all__ = ['RustLexer']
@@ -18,33 +18,40 @@ __all__ = ['RustLexer']
class RustLexer(RegexLexer):
"""
- Lexer for the Rust programming language (version 0.9).
+ Lexer for the Rust programming language (version 1.0).
.. versionadded:: 1.6
"""
name = 'Rust'
filenames = ['*.rs']
aliases = ['rust']
- mimetypes = ['text/x-rustsrc']
+ mimetypes = ['text/rust']
tokens = {
'root': [
+ # rust allows a file to start with a shebang, but if the first line
+ # starts with #![ then it’s not a shebang but a crate attribute.
+ (r'#![^[\r\n].*$', Comment.Preproc),
+ default('base'),
+ ],
+ 'base': [
# Whitespace and Comments
(r'\n', Whitespace),
(r'\s+', Whitespace),
- (r'//[/!](.*?)\n', Comment.Doc),
+ (r'//!.*?\n', String.Doc),
+ (r'///(\n|[^/].*?\n)', String.Doc),
(r'//(.*?)\n', Comment.Single),
+ (r'/\*\*(\n|[^/*])', String.Doc, 'doccomment'),
+ (r'/\*!', String.Doc, 'doccomment'),
(r'/\*', Comment.Multiline, 'comment'),
- # Lifetime
- (r"""'[a-zA-Z_]\w*""", Name.Label),
# Macro parameters
(r"""\$([a-zA-Z_]\w*|\(,?|\),?|,?)""", Comment.Preproc),
# Keywords
(words((
- 'as', 'box', 'break', 'continue', 'do', 'else', 'enum', 'extern',
+ 'as', 'box', 'crate', 'do', 'else', 'enum', 'extern', # break and continue are in labels
'fn', 'for', 'if', 'impl', 'in', 'loop', 'match', 'mut', 'priv',
- 'proc', 'pub', 'ref', 'return', 'static', '\'static', 'struct',
+ 'proc', 'pub', 'ref', 'return', 'static', 'struct',
'trait', 'true', 'type', 'unsafe', 'while'), suffix=r'\b'),
Keyword),
(words(('alignof', 'be', 'const', 'offsetof', 'pure', 'sizeof',
@@ -53,44 +60,45 @@ class RustLexer(RegexLexer):
(r'(mod|use)\b', Keyword.Namespace),
(r'(true|false)\b', Keyword.Constant),
(r'let\b', Keyword.Declaration),
- (words(('u8', 'u16', 'u32', 'u64', 'i8', 'i16', 'i32', 'i64', 'uint',
- 'int', 'f32', 'f64', 'str', 'bool'), suffix=r'\b'),
+ (words(('u8', 'u16', 'u32', 'u64', 'i8', 'i16', 'i32', 'i64', 'usize',
+ 'isize', 'f32', 'f64', 'str', 'bool'), suffix=r'\b'),
Keyword.Type),
(r'self\b', Name.Builtin.Pseudo),
- # Prelude
+ # Prelude (taken from Rust’s src/libstd/prelude.rs)
(words((
- 'Freeze', 'Pod', 'Send', 'Sized', 'Add', 'Sub', 'Mul', 'Div', 'Rem', 'Neg', 'Not', 'BitAnd',
- 'BitOr', 'BitXor', 'Drop', 'Shl', 'Shr', 'Index', 'Option', 'Some', 'None', 'Result',
- 'Ok', 'Err', 'from_str', 'range', 'print', 'println', 'Any', 'AnyOwnExt', 'AnyRefExt',
- 'AnyMutRefExt', 'Ascii', 'AsciiCast', 'OnwedAsciiCast', 'AsciiStr',
- 'IntoBytes', 'Bool', 'ToCStr', 'Char', 'Clone', 'DeepClone', 'Eq', 'ApproxEq',
- 'Ord', 'TotalEq', 'Ordering', 'Less', 'Equal', 'Greater', 'Equiv', 'Container',
- 'Mutable', 'Map', 'MutableMap', 'Set', 'MutableSet', 'Default', 'FromStr',
- 'Hash', 'FromIterator', 'Extendable', 'Iterator', 'DoubleEndedIterator',
- 'RandomAccessIterator', 'CloneableIterator', 'OrdIterator',
- 'MutableDoubleEndedIterator', 'ExactSize', 'Times', 'Algebraic',
- 'Trigonometric', 'Exponential', 'Hyperbolic', 'Bitwise', 'BitCount',
- 'Bounded', 'Integer', 'Fractional', 'Real', 'RealExt', 'Num', 'NumCast',
- 'CheckedAdd', 'CheckedSub', 'CheckedMul', 'Orderable', 'Signed',
- 'Unsigned', 'Round', 'Primitive', 'Int', 'Float', 'ToStrRadix',
- 'ToPrimitive', 'FromPrimitive', 'GenericPath', 'Path', 'PosixPath',
- 'WindowsPath', 'RawPtr', 'Buffer', 'Writer', 'Reader', 'Seek',
- 'SendStr', 'SendStrOwned', 'SendStrStatic', 'IntoSendStr', 'Str',
- 'StrVector', 'StrSlice', 'OwnedStr', 'IterBytes', 'ToStr', 'IntoStr',
- 'CopyableTuple', 'ImmutableTuple', 'ImmutableEqVector', 'ImmutableTotalOrdVector',
- 'ImmutableCopyableVector', 'OwnedVector', 'OwnedCopyableVector',
- 'OwnedEqVector', 'MutableVector', 'MutableTotalOrdVector',
- 'Vector', 'VectorVector', 'CopyableVector', 'ImmutableVector',
- 'Port', 'Chan', 'SharedChan', 'spawn', 'drop'), suffix=r'\b'),
+ # Reexported core operators
+ 'Copy', 'Send', 'Sized', 'Sync',
+ 'Drop', 'Fn', 'FnMut', 'FnOnce',
+
+ # Reexported functions
+ 'drop',
+
+ # Reexported types and traits
+ 'Box',
+ 'ToOwned',
+ 'Clone',
+ 'PartialEq', 'PartialOrd', 'Eq', 'Ord',
+ 'AsRef', 'AsMut', 'Into', 'From',
+ 'Default',
+ 'Iterator', 'Extend', 'IntoIterator',
+ 'DoubleEndedIterator', 'ExactSizeIterator',
+ 'Option',
+ 'Some', 'None',
+ 'Result',
+ 'Ok', 'Err',
+ 'SliceConcatExt',
+ 'String', 'ToString',
+ 'Vec',
+ ), suffix=r'\b'),
Name.Builtin),
- (r'(ImmutableTuple\d+|Tuple\d+)\b', Name.Builtin),
- # Borrowed pointer
- (r'(&)(\'[A-Za-z_]\w*)?', bygroups(Operator, Name)),
# Labels
- (r'\'[A-Za-z_]\w*:', Name.Label),
+ (r'(break|continue)(\s*)(\'[A-Za-z_]\w*)?', bygroups(Keyword, Text.Whitespace, Name.Label)),
# Character Literal
- (r"""'(\\['"\\nrt]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}"""
- r"""|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|.)'""",
+ (r"""'(\\['"\\nrt]|\\x[0-7][0-9a-fA-F]|\\0"""
+ r"""|\\u\{[0-9a-fA-F]{1,6}\}|.)'""",
+ String.Char),
+ (r"""b'(\\['"\\nrt]|\\x[0-9a-fA-F]{2}|\\0"""
+ r"""|\\u\{[0-9a-fA-F]{1,6}\}|.)'""",
String.Char),
# Binary Literal
(r'0b[01_]+', Number.Bin, 'number_lit'),
@@ -100,11 +108,16 @@ class RustLexer(RegexLexer):
(r'0[xX][0-9a-fA-F_]+', Number.Hex, 'number_lit'),
# Decimal Literal
(r'[0-9][0-9_]*(\.[0-9_]+[eE][+\-]?[0-9_]+|'
- r'\.[0-9_]*|[eE][+\-]?[0-9_]+)', Number.Float, 'number_lit'),
+ r'\.[0-9_]*(?!\.)|[eE][+\-]?[0-9_]+)', Number.Float, 'number_lit'),
(r'[0-9][0-9_]*', Number.Integer, 'number_lit'),
# String Literal
+ (r'b"', String, 'bytestring'),
(r'"', String, 'string'),
- (r'r(#*)".*?"\1', String.Raw),
+ (r'b?r(#*)".*?"\1', String),
+
+ # Lifetime
+ (r"""'static""", Name.Builtin),
+ (r"""'[a-zA-Z_]\w*""", Name.Attribute),
# Operators and Punctuation
(r'[{}()\[\],.;]', Punctuation),
@@ -129,18 +142,28 @@ class RustLexer(RegexLexer):
(r'\*/', Comment.Multiline, '#pop'),
(r'[*/]', Comment.Multiline),
],
+ 'doccomment': [
+ (r'[^*/]+', String.Doc),
+ (r'/\*', String.Doc, '#push'),
+ (r'\*/', String.Doc, '#pop'),
+ (r'[*/]', String.Doc),
+ ],
'number_lit': [
- (r'[ui](8|16|32|64)', Keyword, '#pop'),
+ (r'[ui](8|16|32|64|size)', Keyword, '#pop'),
(r'f(32|64)', Keyword, '#pop'),
default('#pop'),
],
'string': [
(r'"', String, '#pop'),
- (r"""\\['"\\nrt]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}"""
- r"""|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}""", String.Escape),
+ (r"""\\['"\\nrt]|\\x[0-7][0-9a-fA-F]|\\0"""
+ r"""|\\u\{[0-9a-fA-F]{1,6}\}""", String.Escape),
(r'[^\\"]+', String),
(r'\\', String),
],
+ 'bytestring': [
+ (r"""\\x[89a-fA-F][0-9a-fA-F]""", String.Escape),
+ include('string'),
+ ],
'macro{': [
(r'\{', Operator, '#push'),
(r'\}', Operator, '#pop'),
diff --git a/pygments/lexers/shell.py b/pygments/lexers/shell.py
index a9c1e6b9..1e3640bf 100644
--- a/pygments/lexers/shell.py
+++ b/pygments/lexers/shell.py
@@ -47,7 +47,7 @@ class BashLexer(RegexLexer):
(r'\$\(\(', Keyword, 'math'),
(r'\$\(', Keyword, 'paren'),
(r'\$\{#?', String.Interpol, 'curly'),
- (r'\$#?(\w+|.)', Name.Variable),
+ (r'\$(\w+|.)', Name.Variable),
],
'basic': [
(r'\b(if|fi|else|while|do|done|for|then|return|function|case|'
diff --git a/pygments/lexers/templates.py b/pygments/lexers/templates.py
index 3cb73059..bfca0d38 100644
--- a/pygments/lexers/templates.py
+++ b/pygments/lexers/templates.py
@@ -369,7 +369,7 @@ class DjangoLexer(RegexLexer):
r'with(?:(?:out)?\s*context)?|scoped|ignore\s+missing)\b',
Keyword),
(r'(loop|block|super|forloop)\b', Name.Builtin),
- (r'[a-zA-Z][\w-]*', Name.Variable),
+ (r'[a-zA-Z_][\w-]*', Name.Variable),
(r'\.\w+', Name.Variable),
(r':?"(\\\\|\\"|[^"])*"', String.Double),
(r":?'(\\\\|\\'|[^'])*'", String.Single),
diff --git a/tests/examplefiles/99_bottles_of_beer.chpl b/tests/examplefiles/99_bottles_of_beer.chpl
index 47fcaaf6..3629028d 100644
--- a/tests/examplefiles/99_bottles_of_beer.chpl
+++ b/tests/examplefiles/99_bottles_of_beer.chpl
@@ -159,3 +159,16 @@ var wideOpen = 0o777,
clique_y = 0O660,
zeroOct = 0o0,
minPosOct = 0O1;
+
+private module M3 {
+ private proc foo() {
+
+ }
+
+ private iter bar() {
+
+ }
+
+ private var x: int;
+
+} \ No newline at end of file
diff --git a/tests/examplefiles/eval.rs b/tests/examplefiles/eval.rs
new file mode 100644
index 00000000..17e585a0
--- /dev/null
+++ b/tests/examplefiles/eval.rs
@@ -0,0 +1,606 @@
+// -------------------------------------------------------------------------------------------------
+// Rick, a Rust intercal compiler. Save your souls!
+//
+// Copyright (c) 2015 Georg Brandl
+//
+// This program is free software; you can redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+// even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with this program;
+// if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+// -------------------------------------------------------------------------------------------------
+
+/// Interprets INTERCAL source.
+///
+/// The evaluator is used when rick is called with `-i`, or when the compiler generates
+/// the output while compiling (in the constant-output case).
+
+use std::fmt::{ Debug, Display };
+use std::io::Write;
+use std::u16;
+
+use err::{ Res, IE123, IE129, IE252, IE275, IE555, IE633, IE774, IE994 };
+use ast::{ self, Program, Stmt, StmtBody, ComeFrom, Expr, Var, VType };
+use stdops::{ Bind, Array, write_number, read_number, check_chance, check_ovf, pop_jumps,
+ get_random_seed, mingle, select, and_16, and_32, or_16, or_32, xor_16, xor_32 };
+
+
+/// Represents a value (either 16-bit or 32-bit) at runtime.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum Val {
+ I16(u16),
+ I32(u32),
+}
+
+impl Val {
+ /// Cast as a 16-bit value; returns an error if 32-bit and too big.
+ pub fn as_u16(&self) -> Res<u16> {
+ match *self {
+ Val::I16(v) => Ok(v),
+ Val::I32(v) => {
+ if v > (u16::MAX as u32) {
+ return IE275.err();
+ }
+ Ok(v as u16)
+ }
+ }
+ }
+
+ /// Cast as a 32-bit value; always succeeds.
+ pub fn as_u32(&self) -> u32 {
+ match *self {
+ Val::I16(v) => v as u32,
+ Val::I32(v) => v
+ }
+ }
+
+ /// Cast as an usize value; always succeeds.
+ pub fn as_usize(&self) -> usize {
+ self.as_u32() as usize
+ }
+
+ /// Create from a 32-bit value; will select the smallest possible type.
+ pub fn from_u32(v: u32) -> Val {
+ if v & 0xFFFF == v {
+ Val::I16(v as u16)
+ } else {
+ Val::I32(v)
+ }
+ }
+}
+
+/// The state of the interpreter's evaluator.
+pub struct Eval<'a> {
+ /// Program to execute.
+ program: &'a Program,
+ /// Stream to use for printing output.
+ stdout: &'a mut Write,
+ /// Whether to print debugging output during execution.
+ debug: bool,
+ /// Variable bindings for the four types of variables.
+ spot: Vec<Bind<u16>>,
+ twospot: Vec<Bind<u32>>,
+ tail: Vec<Bind<Array<u16>>>,
+ hybrid: Vec<Bind<Array<u32>>>,
+ /// The infamous NEXT stack, capable of holding 80 elements.
+ jumps: Vec<ast::LogLine>,
+ /// Abstain counter for each statement.
+ abstain: Vec<u32>,
+ /// Binary I/O "tape" state.
+ last_in: u8,
+ last_out: u8,
+ /// Random number generator state.
+ rand_st: u32,
+ /// Counts the number of executed statements.
+ stmt_ctr: usize,
+}
+
+/// Represents the control flow effect of an executed statement.
+enum StmtRes {
+ /// normal execution, next statement
+ Next,
+ /// jump around, from DO ... NEXT
+ Jump(usize),
+ /// jump back, from RESUME
+ Back(usize),
+ /// start from the first statement, from TRY AGAIN
+ FromTop,
+ /// end the program, from GIVE UP
+ End,
+}
+
+impl<'a> Eval<'a> {
+ /// Construct a new evaluator.
+ pub fn new(program: &'a Program, stdout: &'a mut Write, debug: bool,
+ random: bool) -> Eval<'a> {
+ let abs = program.stmts.iter().map(|stmt| stmt.props.disabled as u32).collect();
+ let nvars = (program.var_info.0.len(),
+ program.var_info.1.len(),
+ program.var_info.2.len(),
+ program.var_info.3.len());
+ Eval {
+ program: program,
+ stdout: stdout,
+ debug: debug,
+ spot: vec![Bind::new(0); nvars.0],
+ twospot: vec![Bind::new(0); nvars.1],
+ tail: vec![Bind::new(Array::empty()); nvars.2],
+ hybrid: vec![Bind::new(Array::empty()); nvars.3],
+ jumps: Vec::with_capacity(80),
+ rand_st: if random { get_random_seed() } else { 0 },
+ abstain: abs,
+ last_in: 0,
+ last_out: 0,
+ stmt_ctr: 0,
+ }
+ }
+
+ /// Interpret the program. Returns either the number of executed statements,
+ /// or an error (RtError).
+ pub fn eval(&mut self) -> Res<usize> {
+ let mut pctr = 0; // index of current statement
+ let program = self.program.clone();
+ let nstmts = program.stmts.len();
+ loop {
+ // check for falling off the end
+ if pctr >= nstmts {
+ // if the last statement was a TRY AGAIN, falling off the end is fine
+ if let StmtBody::TryAgain = program.stmts[program.stmts.len() - 1].body {
+ break;
+ }
+ return IE633.err();
+ }
+ self.stmt_ctr += 1;
+ let stmt = &program.stmts[pctr];
+ // execute statement if not abstained
+ if self.abstain[pctr] == 0 {
+ // check execution chance
+ let (passed, rand_st) = check_chance(stmt.props.chance, self.rand_st);
+ self.rand_st = rand_st;
+ if passed {
+ // try to eval this statement
+ let res = match self.eval_stmt(stmt) {
+ // on error, set the correct line number and bubble up
+ Err(mut err) => {
+ err.set_line(stmt.props.onthewayto);
+ // special treatment for NEXT
+ if let StmtBody::DoNext(n) = stmt.body {
+ if let Some(i) = program.labels.get(&n) {
+ err.set_line(program.stmts[*i as usize].props.srcline);
+ }
+ }
+ return Err(err);
+ }
+ Ok(res) => res
+ };
+ // handle control flow effects
+ match res {
+ StmtRes::Next => { }
+ StmtRes::Jump(n) => {
+ self.jumps.push(pctr as u16); // push the line with the NEXT
+ pctr = n;
+ continue; // do not increment or check for COME FROMs
+ }
+ StmtRes::Back(n) => {
+ pctr = n; // will be incremented below after COME FROM check
+ }
+ StmtRes::FromTop => {
+ pctr = 0; // start from the beginning, do not push any stack
+ continue;
+ }
+ StmtRes::End => break,
+ }
+ }
+ }
+ // if we are on the line with the compiler bug, error out
+ if pctr == self.program.bugline as usize {
+ return IE774.err_with(None, stmt.props.onthewayto);
+ }
+ // try to determine if we have to go to a COME FROM statement
+ // (note: in general, program.stmts[pctr] != stmt)
+ //
+ // the static COME FROM is always a possibility
+ let mut maybe_next = program.stmts[pctr].comefrom;
+ // the complicated case: evaluate all computed-come-from expressions
+ let my_label = program.stmts[pctr].props.label;
+ if program.uses_complex_comefrom && my_label > 0 {
+ for (i, stmt) in program.stmts.iter().enumerate() {
+ if let StmtBody::ComeFrom(ComeFrom::Expr(ref e)) = stmt.body {
+ let v = try!(try!(self.eval_expr(e)).as_u16());
+ if v == my_label {
+ // as soon as we have multiple candidates, we can bail out
+ if maybe_next.is_some() {
+ return IE555.err();
+ }
+ maybe_next = Some(i as u16);
+ }
+ }
+ }
+ }
+ // check for COME FROMs from this line
+ if let Some(next) = maybe_next {
+ let next = next as usize;
+ // check for abstained COME FROM
+ if self.abstain[next] == 0 {
+ // the COME FROM can also have a % chance
+ let (passed, rand_st) = check_chance(program.stmts[next].props.chance,
+ self.rand_st);
+ self.rand_st = rand_st;
+ if passed {
+ pctr = next;
+ continue;
+ }
+ }
+ }
+ // no COME FROM, normal execution
+ pctr += 1;
+ }
+ Ok(self.stmt_ctr)
+ }
+
+ /// Interpret a single statement.
+ fn eval_stmt(&mut self, stmt: &Stmt) -> Res<StmtRes> {
+ if self.debug {
+ println!("\nExecuting Stmt #{} (state before following)", self.stmt_ctr);
+ self.dump_state();
+ println!("{}", stmt);
+ }
+ match stmt.body {
+ StmtBody::Calc(ref var, ref expr) => {
+ let val = try!(self.eval_expr(expr));
+ try!(self.assign(var, val));
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Dim(ref var, ref exprs) => {
+ try!(self.array_dim(var, exprs));
+ Ok(StmtRes::Next)
+ }
+ StmtBody::DoNext(n) => {
+ match self.program.labels.get(&n) {
+ // too many jumps on stack already?
+ Some(_) if self.jumps.len() >= 80 => IE123.err(),
+ Some(i) => Ok(StmtRes::Jump(*i as usize)),
+ None => IE129.err(),
+ }
+ }
+ StmtBody::ComeFrom(_) => {
+ // nothing to do here at runtime
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Resume(ref expr) => {
+ let n = try!(self.eval_expr(expr)).as_u32();
+ // this expect() is safe: if the third arg is true, there will
+ // be no Ok(None) returns
+ let next = try!(pop_jumps(&mut self.jumps, n, true, 0))
+ .expect("https://xkcd.com/378/ ?!");
+ Ok(StmtRes::Back(next as usize))
+ }
+ StmtBody::Forget(ref expr) => {
+ let n = try!(self.eval_expr(expr)).as_u32();
+ try!(pop_jumps(&mut self.jumps, n, false, 0));
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Ignore(ref vars) => {
+ for var in vars {
+ self.set_rw(var, false);
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Remember(ref vars) => {
+ for var in vars {
+ self.set_rw(var, true);
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Stash(ref vars) => {
+ for var in vars {
+ self.stash(var);
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Retrieve(ref vars) => {
+ for var in vars {
+ try!(self.retrieve(var));
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Abstain(ref expr, ref whats) => {
+ let f: Box<Fn(u32) -> u32> = if let Some(ref e) = *expr {
+ let n = try!(self.eval_expr(e)).as_u32();
+ box move |v: u32| v.saturating_add(n)
+ } else {
+ box |_| 1
+ };
+ for what in whats {
+ self.abstain(what, &*f);
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::Reinstate(ref whats) => {
+ for what in whats {
+ self.abstain(what, &|v: u32| v.saturating_sub(1));
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::ReadOut(ref vars) => {
+ for var in vars {
+ match *var {
+ // read out whole array
+ Expr::Var(ref var) if var.is_dim() => {
+ try!(self.array_readout(var));
+ }
+ // read out single var or array element
+ Expr::Var(ref var) => {
+ let varval = try!(self.lookup(var));
+ try!(write_number(self.stdout, varval.as_u32(), 0));
+ }
+ // read out constant
+ Expr::Num(_, v) => try!(write_number(self.stdout, v, 0)),
+ // others will not be generated
+ _ => return IE994.err(),
+ };
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::WriteIn(ref vars) => {
+ for var in vars {
+ if var.is_dim() {
+ // write in whole array
+ try!(self.array_writein(var));
+ } else {
+ // write in single var or array element
+ let n = try!(read_number(0));
+ try!(self.assign(var, Val::from_u32(n)));
+ }
+ }
+ Ok(StmtRes::Next)
+ }
+ // this one is only generated by the constant-program optimizer
+ StmtBody::Print(ref s) => {
+ if let Err(_) = self.stdout.write(&s) {
+ return IE252.err();
+ }
+ Ok(StmtRes::Next)
+ }
+ StmtBody::TryAgain => Ok(StmtRes::FromTop),
+ StmtBody::GiveUp => Ok(StmtRes::End),
+ StmtBody::Error(ref e) => Err((*e).clone()),
+ }
+ }
+
+ /// Evaluate an expression to a value.
+ fn eval_expr(&self, expr: &Expr) -> Res<Val> {
+ match *expr {
+ Expr::Num(vtype, v) => match vtype {
+ VType::I16 => Ok(Val::I16(v as u16)),
+ VType::I32 => Ok(Val::I32(v)),
+ },
+ Expr::Var(ref var) => self.lookup(var),
+ Expr::Mingle(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx)).as_u32();
+ let w = try!(self.eval_expr(wx)).as_u32();
+ let v = try!(check_ovf(v, 0));
+ let w = try!(check_ovf(w, 0));
+ Ok(Val::I32(mingle(v, w)))
+ }
+ Expr::Select(vtype, ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ if vtype == VType::I16 {
+ Ok(Val::I16(select(v.as_u32(), try!(w.as_u16()) as u32) as u16))
+ } else {
+ Ok(Val::I32(select(v.as_u32(), w.as_u32())))
+ }
+ }
+ Expr::And(vtype, ref vx) => {
+ let v = try!(self.eval_expr(vx));
+ match vtype {
+ VType::I16 => Ok(Val::I16(and_16(try!(v.as_u16()) as u32) as u16)),
+ VType::I32 => Ok(Val::I32(and_32(v.as_u32()))),
+ }
+ }
+ Expr::Or(vtype, ref vx) => {
+ let v = try!(self.eval_expr(vx));
+ match vtype {
+ VType::I16 => Ok(Val::I16(or_16(try!(v.as_u16()) as u32) as u16)),
+ VType::I32 => Ok(Val::I32(or_32(v.as_u32()))),
+ }
+ }
+ Expr::Xor(vtype, ref vx) => {
+ let v = try!(self.eval_expr(vx));
+ match vtype {
+ VType::I16 => Ok(Val::I16(xor_16(try!(v.as_u16()) as u32) as u16)),
+ VType::I32 => Ok(Val::I32(xor_32(v.as_u32()))),
+ }
+ }
+ Expr::RsNot(ref vx) => {
+ let v = try!(self.eval_expr(vx));
+ Ok(Val::I32(!v.as_u32()))
+ }
+ Expr::RsAnd(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32(v.as_u32() & w.as_u32()))
+ }
+ Expr::RsOr(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32(v.as_u32() | w.as_u32()))
+ }
+ Expr::RsXor(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32(v.as_u32() ^ w.as_u32()))
+ }
+ Expr::RsRshift(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32(v.as_u32() >> w.as_u32()))
+ }
+ Expr::RsLshift(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32(v.as_u32() << w.as_u32()))
+ }
+ // Expr::RsEqual(ref vx, ref wx) => {
+ // let v = try!(self.eval_expr(vx));
+ // let w = try!(self.eval_expr(wx));
+ // Ok(Val::I32((v.as_u32() == w.as_u32()) as u32))
+ // }
+ Expr::RsNotEqual(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32((v.as_u32() != w.as_u32()) as u32))
+ }
+ Expr::RsPlus(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32(v.as_u32() + w.as_u32()))
+ }
+ Expr::RsMinus(ref vx, ref wx) => {
+ let v = try!(self.eval_expr(vx));
+ let w = try!(self.eval_expr(wx));
+ Ok(Val::I32(v.as_u32() - w.as_u32()))
+ }
+ }
+ }
+
+ #[inline]
+ fn eval_subs(&self, subs: &Vec<Expr>) -> Res<Vec<usize>> {
+ subs.iter().map(|v| self.eval_expr(v).map(|w| w.as_usize())).collect()
+ }
+
+ /// Dimension an array.
+ fn array_dim(&mut self, var: &Var, dims: &Vec<Expr>) -> Res<()> {
+ let dims = try!(self.eval_subs(dims));
+ match *var {
+ Var::A16(n, _) => self.tail[n].dimension(dims, 0),
+ Var::A32(n, _) => self.hybrid[n].dimension(dims, 0),
+ _ => return IE994.err(),
+ }
+ }
+
+ /// Assign to a variable.
+ fn assign(&mut self, var: &Var, val: Val) -> Res<()> {
+ match *var {
+ Var::I16(n) => Ok(self.spot[n].assign(try!(val.as_u16()))),
+ Var::I32(n) => Ok(self.twospot[n].assign(val.as_u32())),
+ Var::A16(n, ref subs) => {
+ let subs = try!(self.eval_subs(subs));
+ self.tail[n].set_md(subs, try!(val.as_u16()), 0)
+ }
+ Var::A32(n, ref subs) => {
+ let subs = try!(self.eval_subs(subs));
+ self.hybrid[n].set_md(subs, val.as_u32(), 0)
+ }
+ }
+ }
+
+ /// Look up the value of a variable.
+ fn lookup(&self, var: &Var) -> Res<Val> {
+ match *var {
+ Var::I16(n) => Ok(Val::I16(self.spot[n].val)),
+ Var::I32(n) => Ok(Val::I32(self.twospot[n].val)),
+ Var::A16(n, ref subs) => {
+ let subs = try!(self.eval_subs(subs));
+ self.tail[n].get_md(subs, 0).map(Val::I16)
+ }
+ Var::A32(n, ref subs) => {
+ let subs = try!(self.eval_subs(subs));
+ self.hybrid[n].get_md(subs, 0).map(Val::I32)
+ }
+ }
+ }
+
+ /// Process a STASH statement.
+ fn stash(&mut self, var: &Var) {
+ match *var {
+ Var::I16(n) => self.spot[n].stash(),
+ Var::I32(n) => self.twospot[n].stash(),
+ Var::A16(n, _) => self.tail[n].stash(),
+ Var::A32(n, _) => self.hybrid[n].stash(),
+ }
+ }
+
+ /// Process a RETRIEVE statement.
+ fn retrieve(&mut self, var: &Var) -> Res<()> {
+ match *var {
+ Var::I16(n) => self.spot[n].retrieve(0),
+ Var::I32(n) => self.twospot[n].retrieve(0),
+ Var::A16(n, _) => self.tail[n].retrieve(0),
+ Var::A32(n, _) => self.hybrid[n].retrieve(0),
+ }
+ }
+
+ /// Process an IGNORE or REMEMBER statement. Cannot fail.
+ fn set_rw(&mut self, var: &Var, rw: bool) {
+ match *var {
+ Var::I16(n) => self.spot[n].rw = rw,
+ Var::I32(n) => self.twospot[n].rw = rw,
+ Var::A16(n, _) => self.tail[n].rw = rw,
+ Var::A32(n, _) => self.hybrid[n].rw = rw,
+ }
+ }
+
+ /// P()rocess an ABSTAIN or REINSTATE statement. Cannot fail.
+ fn abstain(&mut self, what: &ast::Abstain, f: &Fn(u32) -> u32) {
+ if let &ast::Abstain::Label(lbl) = what {
+ let idx = self.program.labels[&lbl] as usize;
+ if self.program.stmts[idx].body != StmtBody::GiveUp {
+ self.abstain[idx] = f(self.abstain[idx]);
+ }
+ } else {
+ for (i, stype) in self.program.stmt_types.iter().enumerate() {
+ if stype == what {
+ self.abstain[i] = f(self.abstain[i]);
+ }
+ }
+ }
+ }
+
+ /// Array readout helper.
+ fn array_readout(&mut self, var: &Var) -> Res<()> {
+ let state = &mut self.last_out;
+ match *var {
+ Var::A16(n, _) => self.tail[n].readout(self.stdout, state, 0),
+ Var::A32(n, _) => self.hybrid[n].readout(self.stdout, state, 0),
+ _ => return IE994.err(),
+ }
+ }
+
+ /// Array writein helper.
+ fn array_writein(&mut self, var: &Var) -> Res<()> {
+ let state = &mut self.last_in;
+ match *var {
+ Var::A16(n, _) => self.tail[n].writein(state, 0),
+ Var::A32(n, _) => self.hybrid[n].writein(state, 0),
+ _ => return IE994.err(),
+ }
+ }
+
+ /// Debug helpers.
+ fn dump_state(&self) {
+ self.dump_state_one(&self.spot, ".");
+ self.dump_state_one(&self.twospot, ":");
+ self.dump_state_one(&self.tail, ",");
+ self.dump_state_one(&self.hybrid, ";");
+ if self.jumps.len() > 0 {
+ println!("Next stack: {:?}", self.jumps);
+ }
+ //println!("Abstained: {:?}", self.abstain);
+ }
+
+ fn dump_state_one<T: Debug + Display>(&self, vec: &Vec<Bind<T>>, sigil: &str) {
+ if vec.len() > 0 {
+ for (i, v) in vec.iter().enumerate() {
+ print!("{}{} = {}, ", sigil, i, v);
+ }
+ println!("");
+ }
+ }
+}
diff --git a/tests/examplefiles/robotframework_test.txt b/tests/examplefiles/robotframework_test.txt
index 63ba63e6..0d8179c0 100644
--- a/tests/examplefiles/robotframework_test.txt
+++ b/tests/examplefiles/robotframework_test.txt
@@ -6,6 +6,7 @@ Test Setup Keyword argument argument with ${VARIABLE}
*** Variables ***
${VARIABLE} Variable value
@{LIST} List variable here
+&{DICT} Key1=Value1 Key2=Value2
*** Test Cases ***
Keyword-driven example
diff --git a/tests/examplefiles/rust_example.rs b/tests/examplefiles/rust_example.rs
deleted file mode 100644
index 8c44af1d..00000000
--- a/tests/examplefiles/rust_example.rs
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// based on:
-// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java
-
-/* nest some /* comments */ */
-
-extern mod std;
-
-use core::os;
-
-// Using sqrt from the standard library is way slower than using libc
-// directly even though std just calls libc, I guess it must be
-// because the the indirection through another dynamic linker
-// stub. Kind of shocking. Might be able to make it faster still with
-// an llvm intrinsic.
-#[nolink]
-extern mod libc {
- #![legacy_exports];
- fn sqrt(n: float) -> float;
-}
-
-fn main() {
- let args = os::args();
- let args = if os::getenv(~"RUST_BENCH").is_some() {
- ~[~"", ~"4000000"]
- } else if args.len() <= 1u {
- ~[~"", ~"100000"]
- } else {
- args
- };
- let n = int::from_str(args[1]).get();
- let mut bodies: ~[Body::props] = NBodySystem::make();
- io::println(fmt!("%f", NBodySystem::energy(bodies)));
- let mut i = 0;
- while i < n {
- NBodySystem::advance(bodies, 0.01);
- i += 1;
- }
- io::println(fmt!("%f", NBodySystem::energy(bodies)));
-}
-
-mod NBodySystem {
- use Body;
-
- pub fn make() -> ~[Body::props] {
- let mut bodies: ~[Body::props] =
- ~[Body::sun(),
- Body::jupiter(),
- Body::saturn(),
- Body::uranus(),
- Body::neptune()];
-
- let mut px = 0.0;
- let mut py = 0.0;
- let mut pz = 0.0;
-
- let mut i = 0;
- while i < 5 {
- px += bodies[i].vx * bodies[i].mass;
- py += bodies[i].vy * bodies[i].mass;
- pz += bodies[i].vz * bodies[i].mass;
-
- i += 1;
- }
-
- // side-effecting
- Body::offset_momentum(&mut bodies[0], px, py, pz);
-
- return bodies;
- }
-
- pub fn advance(bodies: &mut [Body::props], dt: float) {
- let mut i = 0;
- while i < 5 {
- let mut j = i + 1;
- while j < 5 {
- advance_one(&mut bodies[i],
- &mut bodies[j], dt);
- j += 1;
- }
-
- i += 1;
- }
-
- i = 0;
- while i < 5 {
- move_(&mut bodies[i], dt);
- i += 1;
- }
- }
-
- pub fn advance_one(bi: &mut Body::props,
- bj: &mut Body::props,
- dt: float) unsafe {
- let dx = bi.x - bj.x;
- let dy = bi.y - bj.y;
- let dz = bi.z - bj.z;
-
- let dSquared = dx * dx + dy * dy + dz * dz;
-
- let distance = ::libc::sqrt(dSquared);
- let mag = dt / (dSquared * distance);
-
- bi.vx -= dx * bj.mass * mag;
- bi.vy -= dy * bj.mass * mag;
- bi.vz -= dz * bj.mass * mag;
-
- bj.vx += dx * bi.mass * mag;
- bj.vy += dy * bi.mass * mag;
- bj.vz += dz * bi.mass * mag;
- }
-
- pub fn move_(b: &mut Body::props, dt: float) {
- b.x += dt * b.vx;
- b.y += dt * b.vy;
- b.z += dt * b.vz;
- }
-
- pub fn energy(bodies: &[Body::props]) -> float unsafe {
- let mut dx;
- let mut dy;
- let mut dz;
- let mut distance;
- let mut e = 0.0;
-
- let mut i = 0;
- while i < 5 {
- e +=
- 0.5 * bodies[i].mass *
- (bodies[i].vx * bodies[i].vx + bodies[i].vy * bodies[i].vy
- + bodies[i].vz * bodies[i].vz);
-
- let mut j = i + 1;
- while j < 5 {
- dx = bodies[i].x - bodies[j].x;
- dy = bodies[i].y - bodies[j].y;
- dz = bodies[i].z - bodies[j].z;
-
- distance = ::libc::sqrt(dx * dx + dy * dy + dz * dz);
- e -= bodies[i].mass * bodies[j].mass / distance;
-
- j += 1;
- }
-
- i += 1;
- }
- return e;
-
- }
-}
-
-mod Body {
- use Body;
-
- pub const PI: float = 3.141592653589793;
- pub const SOLAR_MASS: float = 39.478417604357432;
- // was 4 * PI * PI originally
- pub const DAYS_PER_YEAR: float = 365.24;
-
- pub type props =
- {mut x: float,
- mut y: float,
- mut z: float,
- mut vx: float,
- mut vy: float,
- mut vz: float,
- mass: float};
-
- pub fn jupiter() -> Body::props {
- return {mut x: 4.84143144246472090e+00,
- mut y: -1.16032004402742839e+00,
- mut z: -1.03622044471123109e-01,
- mut vx: 1.66007664274403694e-03 * DAYS_PER_YEAR,
- mut vy: 7.69901118419740425e-03 * DAYS_PER_YEAR,
- mut vz: -6.90460016972063023e-05 * DAYS_PER_YEAR,
- mass: 9.54791938424326609e-04 * SOLAR_MASS};
- }
-
- pub fn saturn() -> Body::props {
- return {mut x: 8.34336671824457987e+00,
- mut y: 4.12479856412430479e+00,
- mut z: -4.03523417114321381e-01,
- mut vx: -2.76742510726862411e-03 * DAYS_PER_YEAR,
- mut vy: 4.99852801234917238e-03 * DAYS_PER_YEAR,
- mut vz: 2.30417297573763929e-05 * DAYS_PER_YEAR,
- mass: 2.85885980666130812e-04 * SOLAR_MASS};
- }
-
- pub fn uranus() -> Body::props {
- return {mut x: 1.28943695621391310e+01,
- mut y: -1.51111514016986312e+01,
- mut z: -2.23307578892655734e-01,
- mut vx: 2.96460137564761618e-03 * DAYS_PER_YEAR,
- mut vy: 2.37847173959480950e-03 * DAYS_PER_YEAR,
- mut vz: -2.96589568540237556e-05 * DAYS_PER_YEAR,
- mass: 4.36624404335156298e-05 * SOLAR_MASS};
- }
-
- pub fn neptune() -> Body::props {
- return {mut x: 1.53796971148509165e+01,
- mut y: -2.59193146099879641e+01,
- mut z: 1.79258772950371181e-01,
- mut vx: 2.68067772490389322e-03 * DAYS_PER_YEAR,
- mut vy: 1.62824170038242295e-03 * DAYS_PER_YEAR,
- mut vz: -9.51592254519715870e-05 * DAYS_PER_YEAR,
- mass: 5.15138902046611451e-05 * SOLAR_MASS};
- }
-
- pub fn sun() -> Body::props {
- return {mut x: 0.0,
- mut y: 0.0,
- mut z: 0.0,
- mut vx: 0.0,
- mut vy: 0.0,
- mut vz: 0.0,
- mass: SOLAR_MASS};
- }
-
- pub fn offset_momentum(props: &mut Body::props,
- px: float, py: float, pz: float) {
- props.vx = -px / SOLAR_MASS;
- props.vy = -py / SOLAR_MASS;
- props.vz = -pz / SOLAR_MASS;
- }
-
-}
diff --git a/tests/examplefiles/test.gradle b/tests/examplefiles/test.gradle
new file mode 100644
index 00000000..0bc834c1
--- /dev/null
+++ b/tests/examplefiles/test.gradle
@@ -0,0 +1,20 @@
+apply plugin: 'java'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ testCompile 'junit:junit:4.12'
+}
+
+task sayHello << {
+ def x = SomeClass.worldString
+ println "Hello ${x}"
+}
+
+private class SomeClass {
+ public static String getWorldString() {
+ return "world"
+ }
+}