diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-02-29 13:35:42 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-02-29 16:27:34 +0000 |
| commit | 79aa35d237395cc98c39986b211c57c77b7750e2 (patch) | |
| tree | c930670dd82bea41a39717a2da906b7f38e326bb /core/pattern.moon | |
| parent | doc and tag spec (diff) | |
| download | alive-79aa35d237395cc98c39986b211c57c77b7750e2.tar.gz alive-79aa35d237395cc98c39986b211c57c77b7750e2.zip | |
add type-pattern matching language
Diffstat (limited to 'core/pattern.moon')
| -rw-r--r-- | core/pattern.moon | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/core/pattern.moon b/core/pattern.moon new file mode 100644 index 0000000..45701e6 --- /dev/null +++ b/core/pattern.moon @@ -0,0 +1,58 @@ +unpack or= table.unpack + +class Pattern + new: (opts) => + if 'string' == type opts + splat, const, type, opt = opts\match '^(%*?)(=?)([%w%-%_%/]+)(%??)$' + assert type, "couldn't parse type pattern '#{opts}'" + opts = { + :type + splat: splat == '*' + const: const == '=' + opt: opt == '?' + } + + @type = opts.type + @const = opts.const + @opt = opts.opt + @splat = opts.splat + + matches: (result) => + return false unless result + + if @const + return false unless result\is_const! + + if not result.value + return @type == 'nil' + + return true if @type == 'any' + + result.value.type == @type + + match: (results) => + if @splat + matched = while @matches results[1] + table.remove results, 1 + + assert @opt or #matched > 0, "expected at least one argument for spread!" + matched + else + matches = @matches results[1] + assert @opt or matches, "couldn't match argument #{results[1]} as type #{@type}!" + matches and table.remove results, 1 + +match = (pattern, results) -> + patterns = while pattern + pat, rest = pattern\match '^([^ ]+) (.*)$' + pat = pattern unless pat + pattern = rest + Pattern pat + values = [p\match results for p in *patterns] + assert #results == 0, "#{#results} extra arguments given!" + unpack values + +{ + :Pattern + :match +} |
