diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-03-20 20:07:37 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-03-20 20:08:25 +0000 |
| commit | 04eb8afc8367e51c15c507740b2c55fce2569b0d (patch) | |
| tree | 01c5a53fbcd72d9a05009792126af5c54c8486ae /core | |
| parent | docs/index: mention license + repo (diff) | |
| download | alive-04eb8afc8367e51c15c507740b2c55fce2569b0d.tar.gz alive-04eb8afc8367e51c15c507740b2c55fce2569b0d.zip | |
language Error tracking
Close #3
Diffstat (limited to 'core')
| -rw-r--r-- | core/base/init.moon | 4 | ||||
| -rw-r--r-- | core/base/match.moon | 7 | ||||
| -rw-r--r-- | core/error.moon | 85 | ||||
| -rw-r--r-- | core/init.moon | 4 | ||||
| -rw-r--r-- | core/invoke.moon | 7 | ||||
| -rw-r--r-- | core/value.moon | 3 | ||||
| -rw-r--r-- | core/version.moon | 4 |
7 files changed, 103 insertions, 11 deletions
diff --git a/core/base/init.moon b/core/base/init.moon index 64b34f4..bb35140 100644 --- a/core/base/init.moon +++ b/core/base/init.moon @@ -12,6 +12,7 @@ -- @see match -- @see Value -- @see Result +-- @see Error import IO from require 'core.base.io' import Op from require 'core.base.op' @@ -21,6 +22,7 @@ import Input from require 'core.base.input' import match from require 'core.base.match' import Value from require 'core.value' import Result from require 'core.result' +import Error from require 'core.error' { :IO @@ -31,5 +33,5 @@ import Result from require 'core.result' :match -- redundant exports, to keep anything an extension might need in one import - :Value, :Result + :Value, :Result, :Error } diff --git a/core/base/match.moon b/core/base/match.moon index a20bcdc..cb82ac4 100644 --- a/core/base/match.moon +++ b/core/base/match.moon @@ -2,6 +2,7 @@ -- Utilities for matching `Result` types. -- -- @module match +import Error from require 'core.error' unpack or= table.unpack class Pattern @@ -39,11 +40,11 @@ class Pattern matched = while @matches results[1] table.remove results, 1 - assert @opt or #matched > 0, "expected at least one argument for spread" + assert @opt or #matched > 0, Error 'argument', "expected at least one argument for spread" matched else matches = @matches results[1] - assert @opt or matches, "couldn't match argument #{results[1]} as #{@}" + assert @opt or matches, Error 'argument', "argument #{results[1].value} incompatible with expected type #{@}" if matches then table.remove results, 1 __tostring: => @@ -84,7 +85,7 @@ match = (pattern, inputs) -> pattern = rest Pattern pat values = [p\match inputs for p in *patterns] - assert #inputs == 0, "#{#inputs} extra arguments given!" + assert #inputs == 0, Error 'argument', "#{#inputs} extra arguments given!" values { diff --git a/core/error.moon b/core/error.moon new file mode 100644 index 0000000..a06c359 --- /dev/null +++ b/core/error.moon @@ -0,0 +1,85 @@ +---- +-- Language error and traceback. +-- +-- @classmod Error +class Error +--- members +-- @section members + + --- append a traceback frame. + -- + -- `where` should denote where the Error occured and fit grammatically to + -- complete the sentence `"{error} occured while {where}"` + -- + -- @tparam string where + add_frame: (where) => @trace ..= "\n while #{where}" + + __tostring: => "#{@kind} error: #{@message}#{@detail}#{@trace}" + +--- static functions +-- @section static + + --- create a new Error. + -- + -- `kind` should be one of: + -- + -- - `'reference'`: error concerning symbol resolution + -- - `'argument'`: error concerning Op argument matching + -- - `'implementation'`: error in the Lua/MoonScript implementation of alive. + -- Should not occur in normal operation, and constitutes a bug. + -- + -- @classmethod + -- @tparam string kind + -- @tparam string message + -- @tparam ?string detail + new: (@kind, @message, @detail) => + @trace = "" + + handler = (err) -> + if err.__class == Error + err + else + Error 'implementation', err, debug.traceback 'Lua error below:', 2 + --- Wrap function errors in a traceback frame. + -- + -- Execute `fn(...)`, and turn any error thrown as a result into an + -- `Error` instance, before re-throwing it. + -- + -- When `Error` instances are caught, `frame` is added to the traceback. + -- All other error values are turned into `'implementation'` Errors. + -- + -- @tparam string frame + -- @tparam function fn + @wrap: (frame, fn, ...) -> + results = { xpcall fn, handler, ... } + ok = table.remove results, 1 + if ok + unpack results + else + error with results[1] + \add_frame frame + + --- Capture and wrap function errors in traceback frame. + -- + -- Execute `fn(...)`, and turn any error thrown as a result into an + -- `Error` instance, before re-throwing it. + -- + -- When `Error` instances are caught, `frame` is added to the traceback. + -- All other error values are turned into `'implementation'` Errors. + -- + -- @tparam string frame + -- @tparam function fn + -- @treturn boolean `ok` true if exeuction suceeded without errors + -- @treturn Error|any `error_or_results` the `Error` instance or results + @try: (frame, fn, ...) -> + results = { xpcall fn, handler, ... } + ok = table.remove results, 1 + if ok + ok, unpack results + else + ok, with results[1] + \add_frame frame + +{ + :Error +} diff --git a/core/init.moon b/core/init.moon index a5e892d..00e3cd4 100644 --- a/core/init.moon +++ b/core/init.moon @@ -17,6 +17,7 @@ L or= setmetatable {}, __index: => -> import Value from require 'core.value' import Result from require 'core.result' import Scope from require 'core.scope' +import Error from require 'core.error' import Registry, SimpleRegistry from require 'core.registry' import Tag from require 'core.tag' @@ -35,6 +36,7 @@ globals = Scope.from_table require 'core.builtin' -- @tfield Cell Cell -- @tfield RootCell RootCell -- @tfield Scope Scope +-- @tfield Error Error -- @tfield Registry Registry -- @tfield Tag Tag -- @tfield Scope globals global definitons @@ -42,7 +44,7 @@ globals = Scope.from_table require 'core.builtin' { :Value, :Result :Cell, :RootCell - :Scope + :Scope, :Error :Registry, :SimpleRegistry, :Tag diff --git a/core/invoke.moon b/core/invoke.moon index 736f284..97d3949 100644 --- a/core/invoke.moon +++ b/core/invoke.moon @@ -6,6 +6,7 @@ import Value from require 'core.value' import Result from require 'core.result' import Action from require 'core.base' import Scope from require 'core.scope' +import Error from require 'core.error' --- `Action` implementation that invokes an `Op`. -- @@ -40,7 +41,7 @@ class op_invoke extends Action -- @treturn Result eval: (scope, tail) => children = [L\push expr\eval, scope for expr in *tail] - @op\setup [result for result in *children], scope + Error.wrap "invoking #{@op}#{@tag}", @op\setup, [result for result in *children], scope any_dirty = false for input in @op\all_inputs! @@ -91,8 +92,8 @@ class fn_invoke extends Action with L\push tail[i]\eval, outer_scope fn_scope\set name, \make_ref! - body = body\clone @tag - result = body\eval fn_scope + clone = body\clone @tag + result = Error.wrap "invoking function #{body.tag} at #{@tag}", clone\eval, fn_scope table.insert children, result Result :children, value: result.value diff --git a/core/value.moon b/core/value.moon index bda6127..7f5a93d 100644 --- a/core/value.moon +++ b/core/value.moon @@ -3,6 +3,7 @@ -- -- @classmod Value import Result from require 'core.result' +import Error from require 'core.error' import scope, base, registry from require 'core.cycle' ancestor = (klass) -> @@ -107,7 +108,7 @@ class Value when 'num', 'str' Result value: @ when 'sym' - assert (scope\get @value), "undefined reference to symbol '#{@value}'" + assert (scope\get @value), Error 'reference', "undefined symbol '#{@value}'" else error "cannot evaluate #{@}" diff --git a/core/version.moon b/core/version.moon index e5a965c..af97600 100644 --- a/core/version.moon +++ b/core/version.moon @@ -12,8 +12,8 @@ -- @tfield string web the repo web URL { tag: "v0.0" - rev_short: "23f893a" - rev_long: "23f893a1303b35e11d7103d892c40b7e8d209a06" + rev_short: "662def4" + rev_long: "662def4ef082412147ae8126e80065d245f4b426" repo: "https://github.com/s-ol/alivecoding.git" web: "https://github.com/s-ol/alivecoding/tree/v0.0" } |
