Skip to content

Commit

Permalink
[wip] Rebase opal#591
Browse files Browse the repository at this point in the history
  • Loading branch information
boblail committed May 6, 2016
1 parent c3c4b87 commit 982e530
Show file tree
Hide file tree
Showing 5 changed files with 1,973 additions and 43 deletions.
3 changes: 2 additions & 1 deletion lib/opal/compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ def compile

@result = @fragments.map(&:code).join('')
rescue Exception => error
message = "An error occurred while compiling: #{self.file}\n#{error.message}"
_source = self.file == "(file)" ? @source.inspect : self.file
message = "An error occurred while compiling: #{_source}\n#{error.message}"
raise error.class, message, error.backtrace
end

Expand Down
21 changes: 15 additions & 6 deletions lib/opal/nodes/literal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,23 @@ class RegexpNode < Base
children :value, :flags

def compile
case value
when ''
if value == ''
push('/(?:)/')
when %r{\?<\w+\>}
message = "named captures are not supported in javascript: #{value.inspect}"
push "self.$raise(new SyntaxError('#{message}'))"
else
push "#{Regexp.new(value).inspect}#{flags}"
# push "#{Regexp.new(value).inspect}#{flags}"
escaped = value.dup
escaped.gsub!("\\", "\\\\\\\\")
escaped.gsub!("\n", "\\n\\\n")
escaped.gsub!("'", "\\\\'")
unsupported = /[^gimx]/.match flags
raise SyntaxError, "unknown regexp flag '#{unsupported[0]}' in /#{value}/#{flags}" if unsupported
options = 0
if flags
options = options | Regexp::IGNORECASE if flags.include?("i")
options = options | Regexp::EXTENDED if flags.include?("x")
options = options | Regexp::MULTILINE if flags.include?("m")
end
push "$scope.Regexp.$new('#{escaped}', #{options})"
end
end
end
Expand Down
106 changes: 71 additions & 35 deletions opal/corelib/regexp.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
class RegexpError < StandardError; end

class Regexp < `RegExp`
class Regexp < `XRegExp`
IGNORECASE = 1
EXTENDED = 2
MULTILINE = 4

`def.$$is_regexp = true`
Expand Down Expand Up @@ -43,7 +44,7 @@ def union(*parts)
is_first_part_array = parts[0].$$is_array;
if (parts.length > 1 && is_first_part_array) {
#{raise TypeError, 'no implicit conversion of Array into String'}
}
}
// deal with splat issues (related to https://github.com/opal/opal/issues/858)
if (is_first_part_array) {
parts = parts[0];
Expand Down Expand Up @@ -72,10 +73,10 @@ def union(*parts)
new(`quoted_validated`.join('|'), `options`)
end

def new(regexp, options = undefined)
def new(regexp, options = undefined, lang = nil)
%x{
if (regexp.$$is_regexp) {
return new RegExp(regexp);
return new XRegExp(regexp);
}
regexp = #{Opal.coerce_to!(regexp, String, :to_str)};
Expand All @@ -85,26 +86,27 @@ def new(regexp, options = undefined)
}
if (options === undefined || #{!options}) {
return new RegExp(regexp);
return new XRegExp(regexp);
}
if (options.$$is_number) {
var temp = '';
if (#{IGNORECASE} & options) { temp += 'i'; }
if (#{EXTENDED} & options) { temp += 'x'; }
if (#{MULTILINE} & options) { temp += 'm'; }
options = temp;
}
else {
options = 'i';
}
return new RegExp(regexp, options);
return new XRegExp(regexp, options);
}
end
end

def ==(other)
`other.constructor == RegExp && self.toString() === other.toString()`
`other.constructor == XRegExp && self.toString() === other.toString()`
end

def ===(string)
Expand Down Expand Up @@ -155,7 +157,7 @@ def match(string, pos = undefined, &block)
}
// global RegExp maintains state, so not using self/this
var md, re = new RegExp(source, flags + (self.ignoreCase ? 'i' : ''));
var md, re = new XRegExp(source, flags + (self.multiline ? 'm' : '') + (self.ignoreCase ? 'i' : ''));
while (true) {
md = re.exec(string);
Expand All @@ -176,25 +178,45 @@ def ~
end

def source
`self.source`
`self.xregexp.source`
end

def options
# Flags would be nice to use with this, but still experimental - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags
def flags
`self.xregexp.flags`
end

def names
re = self
%x{
if (self.uninitialized) {
#{raise TypeError, 'uninitialized Regexp'}
}
var result = 0;
// should be supported in IE6 according to https://msdn.microsoft.com/en-us/library/7f5z26w4(v=vs.94).aspx
if (self.multiline) {
result |= #{MULTILINE};
}
if (self.ignoreCase) {
result |= #{IGNORECASE};
if (re.xregexp.captureNames == null) {
return nil
}
else {
return re.xregexp.captureNames
}
}
return result;
}
end

def options
result = 0
result = result | IGNORECASE if `self.ignoreCase`
result = result | EXTENDED if @extended
result = result | MULTILINE if `self.multiline`
# # Flags would be nice to use with this, but still experimental - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags
# %x{
# if (self.uninitialized) {
# #{raise TypeError, 'uninitialized Regexp'}
# }
# var result = 0;
# // should be supported in IE6 according to https://msdn.microsoft.com/en-us/library/7f5z26w4(v=vs.94).aspx
# if (self.multiline) {
# result |= #{MULTILINE};
# }
# if (self.ignoreCase) {
# result |= #{IGNORECASE};
# }
# return result;
# }
end

def casefold?
Expand All @@ -219,23 +241,33 @@ def initialize(regexp, match_groups)
@pre_match = `match_groups.input.slice(0, match_groups.index)`
@post_match = `match_groups.input.slice(match_groups.index + match_groups[0].length)`
@matches = []
@named_matches = {}

%x{
for (var i = 0, length = match_groups.length; i < length; i++) {
var group = match_groups[i];
names = regexp.names

if (group == null) {
#@matches.push(nil);
}
else {
#@matches.push(group);
}
}
}
match_groups.each_index do |i|
if `match_groups[i] == null`
@matches << nil
else
@matches << match_groups[i]
end
if i > 0 && !names.nil?
@named_matches[names[i-1]] = i
end
end
self
end

def [](*args)
@matches[*args]
if args.length == 1 && (args[0].is_a? String) #FIXME: Should also include: || args[0].is_a? Symbol
if @named_matches.has_key? args[0]
@matches[@named_matches[args[0]]]
else
raise IndexError, "undefined group name reference: #{args[0]}"
end
else
@matches[*args]
end
end

def offset(n)
Expand Down Expand Up @@ -299,6 +331,10 @@ def length

alias size length

def names
@regexp.names
end

def to_a
@matches
end
Expand Down
Loading

0 comments on commit 982e530

Please sign in to comment.