Age | Commit message (Collapse) | Author |
|
Do not expose the json-c compat functions in ucode's public headers to
avoid clashes when building on systems with modern json-c.
Also remove some explicit json-c/json-c.h includes in places where it is
not needed.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Do not continue loading other libraries or executing the main code if
loading one of the preload libraries fails.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Turn the ucode executable into a multicall binary and select default flags
based on the name it was invoked with. Introduce two new symlinks "ucc" and
"utpl" which start ucode in compile and template mode respectively.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
We now include `json-c/json-c.h` on all supported environments.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Change command line flags to be align better with those of other
interpreters and with the gcc compiler, e.g. `-D` and `-U` to
define and undefine globals, `-e` to execute script expression etc.
- Pass only excess CLI arguments as `ARGV` to scripts, e.g.
`ucode -e 'print("Hello world")' -- -x -y` would pass only
`[ "-x", "-y" ]` as ARGV contents
- Default to raw mode and introduce flag to enable template mode
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Instead of treating individual program functions as managed ucode types,
demote uc_function_t values to pointers into a uc_program_t entity
- Promote uc_program_t to a managed type
- Let uc_closure_t claim references to the owning program of the enclosed
uc_function_t
- Redefine public APIs uc_compile() and uc_vm_execute() APIs to return and
expect an uc_program_t object respectively
- Remove vallist indirection for function loading and let the compiler
emit the function id directly when producing function construction code
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Extend source objects with a `runpath` field which contains the original
path of the source being executed by the VM.
When instantiating source objects from file paths, the `runpath` will be
set to the `filename`. When instantiating source buffers using
`uc_source_new_buffer()`, the runpath is initially unset.
A new function `uc_source_runpath_set()` can be used to adjust the runtime
path being associated with a source object.
Extend bytecode loading logic to set the source buffer runtime path to the
precompiled bytecode file path being loaded and executed. This is required
for `sourcepath()` and relative paths in `include()` to function correctly
when executing precompiled programs.
Finally rename `uc_program_from_file()` and `uc_program_to_file()` to
`uc_program_load()` and `uc_program_write()` respectively since the load
part now operates on an `uc_source_t` input buffer instead of a plain
`FILE *` handle.
Adjust users of these API functions accordingly.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Introduce new command line flags `-o` and `-O` to write compiled program
code into the specified output file
- Add support for transparently executing precompiled files, the
lexical analyzing and com,pilation phase is skipped in this case
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Ensure that most functions follow the subject_verb naming schema
- Move type related function from value.c to types.c
- Rename value.c to vallist.c
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Set VM options and environment variables and load modules on the fly
while parsing the cli options instead of aggregating all the values in
memory first.
This vastly reduces the amount of arguments we need to pass to the
parse() function. Also rename parse() to compile() while we're at it.
Also slightly adjust the usage output.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Ensure that all custom typedef and vector declaration type names end with
a "_t" suffix.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Add a public getter and setter to read and set the VM trace level
respectively. Use the new API to control the trace mode with a newly
introduced `-t` command line switch.
Drop support for honouring the `TRACE` environment variable as
host programs embedding ucode might want to prevent that behaviour
or handle it differently.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of invoking exit(3) from uc_exit(), use a new EXCEPTION_EXIT
exception type to instruct the VM to shutdown cleanly.
This is required to not terminate the host program in case libucode
is embedded and loaded scripts invoke the exit() function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Module preloading is a cli frontend specific feature, it does not belong
into the VM API, therfore do the module preloading directly in main.c to
allow removing the corresponding VM code in a subsequent commit.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Enabling raw code mode allows writing ucode scripts without any template
tag decorations (that is, without the need to provide an initial opening
'{%' tag).
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Do not require parsing in C, pre-split string in cmake and pass it as
command separated string array down to CPP, so that it can be interpolated
directly into a char *path[] array.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Skip interpreter lines in any source buffer and handle the skipping in the
lexer itself, to avoid reporting wrongly shifted token offsets to the
compiler, resulting in wrong error locations and source contexts.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
This allows accessing the arguments of the invoked command line.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Shuffle typedefs to avoid need for non-compliant forward declarations
- Fix non-compliant empty struct initializers
- Remove use of braced expressions
- Remove use of anonymous unions
- Avoid `void *` pointer arithmetic
- Fix several warnings reported by gcc -pedantic mode and clang 11 compilation
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of relying on json_object values internally, use custom types to
represent the different ucode value types which brings a number of
advantages compared to the previous approach:
- Due to the use of tagged pointers, small integer, string and bool
values can be stored directly in the pointer addresses, vastly
reducing required heap memory
- Ability to create circular data structures such as
`let o; o = { test: o };`
- Ability to register custom `tostring()` function through prototypes
- Initial mark/sweep GC implementation to tear down circular object
graphs on VM deinit
The change also paves the way for possible future extensions such as
constant variables and meta methods for custom ressource types.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Otherwise it prints out complete path which is probably not desired and
we would need to filter out paths in the test's output etc.
Signed-off-by: Petr Štetiar <ynezz@true.cz>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Replace the former AST walking interpreter implementation with a single pass
bytecode compiler and a corresponding virtual machine.
The rewrite lays the groundwork for a couple of improvements with will be
subsequently implemented:
- Ability to precompile ucode sources into binary byte code
- Strippable debug information
- Reduced runtime memory usage
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of obtaining and caching direct opcode pointers, use relative
references when dealing with opcodes since direct or indirect calls to
uc_execute_op() might lead to reallocations of the opcode array, shifting
memory addresses and invalidating pointers taken before the invocation.
Such stale pointer accesses could be commonly triggered when one part
of the processed expression was a require() or include() call loading
relatively large ucode sources.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
By specifying a name, followed by an equal sign before the actual option
value, the corresponding JSON data is stored as global variable with the
given name, instead of turning each object key into a variable itself.
For example while `utpl -e '{ "foo": true, "bar": false }' ...` will set
two variables `foo` and `bar`, the alternative syntax
`utpl -e 'baz={ "foo": true, "bar": false }' ...` will declare a single
variable `baz` holding the object `{ "foo": true, "bar": false }`.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Reverse the order of the ungetc() calls to properly restore the first two
probed bytes.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Get rid of the distinction between lexer/parser errors and runtime
exceptions, use exceptions everywhere instead.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Keep an open FILE* reference to processed source files in order to
be able to rewind and extract error context later
- Build a proper call stack when invoking utpl functions
- Report call stack in exceptions
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Rewrite the lexer into a restartable state machine to support parsing from
file streams without the need to read the entire source text into memory
first.
As a side effect, the length of labels and strings is unlimited now.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Do not emit additional newline when formatting error context and print it
instead when outputting the exception.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of propagating failures to the caller, print a generic error
message and terminate program execution through abort().
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Release the parsed intermediate object after copying its values into the
global env object.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The -m option instructs the interpreter to automatically require the named
module and to register the module context as global variable.
The following two commands are equivalent, with the former one serving as
a shortcut for the latter:
utpl -m fs -s '{{ fs.open("test.txt").read("all") }}'
utpl -s '{% fs = require("fs"); print(fs.open("test.txt").read("all")) %}'
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|