aboutsummaryrefslogtreecommitdiffstats
path: root/core/pattern.moon
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-02-29 13:35:42 +0000
committers-ol <s-ol@users.noreply.github.com>2020-02-29 16:27:34 +0000
commit79aa35d237395cc98c39986b211c57c77b7750e2 (patch)
treec930670dd82bea41a39717a2da906b7f38e326bb /core/pattern.moon
parentdoc and tag spec (diff)
downloadalive-79aa35d237395cc98c39986b211c57c77b7750e2.tar.gz
alive-79aa35d237395cc98c39986b211c57c77b7750e2.zip
add type-pattern matching language
Diffstat (limited to 'core/pattern.moon')
-rw-r--r--core/pattern.moon58
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
+}