Skip to content

Exception support #12

@iBicha

Description

@iBicha

While I don't see how longjmp can be implemented, but perhaps exceptions can be implemented.
I understand that wasi doesn't have wasm exceptions yet WebAssembly/wasi-sdk#334 but emscripten does with -fwasm-exceptions https://emscripten.org/docs/porting/exceptions.html#webassembly-exception-handling-based-support

So an idea is to build wasm programs using emscripten, then leverage brightscript's try/catch error handling for that.
https://developer.roku.com/en-gb/docs/references/brightscript/language/error-handling.md

Throwing in brightscript can be done using a string throw "string" or associative array throw { "message" }
What's interesting here is that the associative array has backtrace, message and number.
The number here is the interesting one, as I think it can be used as a pointer to exception objects.
By default, user thrown exceptions are of value ERR_USER=&h28, but testing this, we can set this value to practically anything we want. We probably want to avoid the standard values that Roku itself uses (from bslCore.brs):

function bslBrightScriptErrorCodes()

    return {

' runtime errors
      ERR_OKAY          :  &hFF
      ERR_NORMAL_END    :  &hFC         ' normal, but terminate execution.  END, shell "exit", window closed, etc.
      ERR_VALUE_RETURN  :  &hE2         ' return executed, and a value returned on the stack


      ERR_INTERNAL      :  &hFE         ' A condition that shouldn't occur did
      ERR_UNDEFINED_OPCD:  &hFD         ' A opcode that we don't handle
      ERR_UNDEFINED_OP  :  &hFB         ' An expression operator that we don't handle
      ERR_MISSING_PARN  :  &hFA
      ERR_STACK_UNDER   :  &hF9         ' nothing on stack to pop
      ERR_BREAK         :  &hF8         ' scriptBreak() called
      ERR_STOP          :  &hF7         ' stop statement executed
      ERR_RO0           :  &hF6         ' bscNewComponent failed because object class not found
      ERR_RO1           :  &hF5         ' ro function call does not have the right number of parameters
      ERR_RO2           :  &hF4         ' member function not found in object or interface
      ERR_RO3           :  &hF3         ' Interface not a member of object
      ERR_TOO_MANY_PARAM    :  &hF2     ' Too many function parameters to handle
      ERR_WRONG_NUM_PARAM   :  &hF1     ' Incorect number of function parameters
      ERR_RVIG              :  &hF0     ' Function returns a value, but is ignored
      ERR_NOTPRINTABLE      :  &hEF     ' Non Printable value
      ERR_NOTWAITABLE       :  &hEE     ' Tried to Wait on a function that does not have MessagePort interface
      ERR_MUST_BE_STATIC    :  &hED     ' interface calls from type rotINTERFACE must by static
      ERR_RO4               :  &hEC     ' . operator used on a variable that does not contain a legal object or interface reference
      ERR_NOTYPEOP          :  &hEB     ' operation on two typless operands attempted
      ERR_USE_OF_UNINIT_VAR :  &hE9     ' illegal use of uninited var
      ERR_TM2               :  &hE8     ' non-numeric index to array
      ERR_ARRAYNOTDIMMED    :  &hE7
      ERR_USE_OF_UNINIT_BRSUBREF :  &hE6    ' used a reference to SUB that is not initilized
      ERR_MUST_HAVE_RETURN  :  &hE5
      ERR_INVALID_LVALUE    :  &hE4     ' invalid left side of expression
      ERR_INVALID_NUM_ARRAY_IDX :  &hE3 ' invalid number of array indexes
      ERR_UNICODE_NOT_SUPPORTED :  &hE1
      ERR_NOTFUNOPABLE      :  &hE0
      ERR_STACK_OVERFLOW    :  &hDF
      ERR_THROWN_EXCEPTION_ON_STACK     : &hDE  '(Internal use only)

      ERR_SYNTAX            :  &h02
      ERR_DIV_ZERO          :  &h14
      ERR_MISSING_LN        :  &h0E
      ERR_OUTOFMEM          :  &h0C
      ERR_STRINGTOLONG      :  &h1C
      ERR_TM                :  &h18     ' Type Mismatch (string / numeric operation mismatch)
      ERR_OS                :  &h1A     ' out of string space
      ERR_RG                :  &h04     ' Return without Gosub
      ERR_NF                :  &h00     ' Next without For
      ERR_FC                :  &h08     ' Invalid parameter passed to function/array (e.g neg matrix dim or squr root)
      ERR_DD                :  &h12     ' Attempted to redimension an array
      ERR_BS                :  &h10     ' Array subscript out of bounds
      ERR_OD                :  &h06     ' Out of Data (READ)
      ERR_CN                :  &h20     ' Continue Not Allowed
      ERR_BITSHIFT_BAD      :  &h1E     ' Invalid Bitwise Shift
      ERR_EXECUTION_TIMEOUT :  &h23     ' Timeout on critical thread
      ERR_CONSTANT_OVERFLOW :  &h22     ' Constant Out Of Range
      ERR_FORMAT_SPECIFIER  :  &h24     ' Invalid Format Specifier
      ERR_BAD_THROW         :  &h26     ' Invalid argument to Throw
      ERR_USER              :  &h28     ' User-specified exception
      ERR_OUTOFTASKS        :  &h29     ' Too many task threads

' compiler errors
      ERR_NW                :  &hBF     ' EndWhile with no While
      ERR_MISSING_ENDWHILE  :  &hBE     ' While Statement is missing a matching EndWhile
      ERR_MISSING_ENDIF     :  &hBC     ' end of code reached without finding ENDIF
      ERR_NOLN              :  &hBB     ' no line number found
      ERR_LNSEQ             :  &hBA     ' Line number sequence error
      ERR_LOADFILE          :  &hB9     ' Error loading a file
      ERR_NOMATCH           :  &hB8     ' "Match" statement did not match
      ERR_UNEXPECTED_EOF    :  &hB7     ' End of string being compiled encountered when not expected (missing end of block usually)
      ERR_FOR_NEXT_MISMATCH :  &hB6     ' Variable on a NEXT does not match that for the FOR
      ERR_NO_BLOCK_END      :  &hB5
      ERR_LABELTWICE        :  &hB4     ' Label defined more than once
      ERR_UNTERMED_STRING   :  &hB3     ' litteral string does not have ending quote
      ERR_FUN_NOT_EXPECTED  :  &hB2
      ERR_TOO_MANY_CONST    :  &hB1
      ERR_TOO_MANY_VAR      :  &hB0
      ERR_EXIT_WHILE_NOT_IN_WHILE   :  &hAF
      ERR_INTERNAL_LIMIT_EXCEDED    :  &hAE
      ERR_SUB_DEFINED_TWICE :  &hAD
      ERR_NOMAIN            :  &hAC
      ERR_FOREACH_INDEX_TM  :  &hAB
      ERR_RET_CANNOT_HAVE_VALUE     :  &hAA
      ERR_RET_MUST_HAVE_VALUE       :  &hA9
      ERR_FUN_MUST_HAVE_RET_TYPE    :  &hA8
      ERR_INVALID_TYPE              :  &hA7
      ERR_NOLONGER                  :  &hA6 ' no longer supported
      ERR_EXIT_FOR_NOT_IN_FOR       :  &hA5
      ERR_MISSING_INITILIZER        :  &hA4
      ERR_IF_TOO_LARGE              :  &hA3
      ERR_RO_NOT_FOUND              :  &hA2
      ERR_TOO_MANY_LABELS           :  &hA1
      ERR_VAR_CANNOT_BE_SUBNAME     :  &hA0
      ERR_INVALID_CONST_NAME        :  &h9F
      ERR_CONST_FOLDING             :  &h9E
      ERR_BUILTIN_FUNCTION          :  &h9D
      ERR_FUNCTION_NOT_IN_NAMESPACE :  &h91
      ERR_EVAL_UNSUPPORTED          :  &h90
      ERR_LABEL_INSIDE_TRY          :  &h8F
      ERR_CONTINUE_FOR_NOT_IN_FOR   :  &h8D
      ERR_CONTINUE_WHILE_NOT_IN_WHILE :  &h8E
      ERR_GOTO_INTO_FOR             :  &h8B

    }

end function

But any other value is fine.

After that, what's really left I think is implementing the expressions needed (I think there's a Try, a Throw, and a Rethrow, perhaps more needed? - it looks like BrOnExn is also an exception thing)
And I'm not sure, but perhaps exception functions need to be present in the runtime https://github.com/WebAssembly/wabt/blob/main/wasm2c/README.md#runtime-support-for-exception-handling

I think this would be interesting for working around the limitation of longjmp in some cases, one of which is duktape, which can work with exceptions instead of longjmp using DUK_USE_CPP_EXCEPTIONS - that would allow to run more than "one liner" javascript.

These are my findings so far, still need to clarify many things

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions