diff options
author | Jo-Philipp Wich <jo@mein.io> | 2021-09-25 19:34:14 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2021-10-11 09:39:12 +0200 |
commit | 4ee06d8138a107908a9fb45220fea32055b3c48a (patch) | |
tree | 2f0bd421931b2dd2daf504719beb63cc2885d23a /include | |
parent | e43b751aab997c5e74a0712f7569d90bd3d6b429 (diff) |
syntax: introduce optional chaining operators
Introduce new operators `?.`, `?.[…]` and `?.(…)` to simplify looking up
deeply nested property chain in a secure manner.
The `?.` operator behaves like the `.` property access operator but yields
`null` if the left hand side is `null` or not an object.
Like `?.`, the `?.[…]` operator behaves like the `[…]` computed property
access but yields `null` if the left hand side is `null` or neither an
object or array.
Finally the `?.(…)` operator behaves like the function call operator `(…)`
but yields `null` if the left hand side is `null` or not a callable
function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'include')
-rw-r--r-- | include/ucode/compiler.h | 25 | ||||
-rw-r--r-- | include/ucode/lexer.h | 3 | ||||
-rw-r--r-- | include/ucode/vm.h | 3 |
3 files changed, 29 insertions, 2 deletions
diff --git a/include/ucode/compiler.h b/include/ucode/compiler.h index 19fcf37..04fc0ef 100644 --- a/include/ucode/compiler.h +++ b/include/ucode/compiler.h @@ -64,11 +64,23 @@ typedef enum { P_PRIMARY /* (…) */ } uc_precedence_t; +typedef enum { + F_ASSIGNABLE = (1 << 0), + F_OPTCHAINING = (1 << 1), + F_ALTBLOCKMODE = (1 << 2), +} uc_exprflag_t; + typedef struct uc_patchlist { struct uc_patchlist *parent; size_t depth, count, *entries; } uc_patchlist_t; +typedef struct uc_exprstack { + struct uc_exprstack *parent; + uint32_t flags; + uc_tokentype_t token; +} uc_exprstack_t; + typedef struct { uc_value_t *name; ssize_t depth; @@ -101,17 +113,26 @@ typedef struct uc_compiler { uc_locals_t locals; uc_upvals_t upvals; uc_patchlist_t *patchlist; + uc_exprstack_t *exprstack; uc_value_t *function; uc_parser_t *parser; size_t scope_depth, current_srcpos, last_insn; } uc_compiler_t; typedef struct { - void (*prefix)(uc_compiler_t *, bool); - void (*infix)(uc_compiler_t *, bool); + void (*prefix)(uc_compiler_t *); + void (*infix)(uc_compiler_t *); uc_precedence_t precedence; } uc_parse_rule_t; uc_function_t *uc_compile(uc_parse_config_t *config, uc_source_t *source, char **errp); +#define uc_compiler_exprstack_push(compiler, token, flags) \ + uc_exprstack_t expr = { compiler->exprstack, flags, token }; \ + compiler->exprstack = &expr + +#define uc_compiler_exprstack_pop(compiler) \ + if (compiler->exprstack) \ + compiler->exprstack = compiler->exprstack->parent + #endif /* __COMPILER_H_ */ diff --git a/include/ucode/lexer.h b/include/ucode/lexer.h index ee8a0a5..05f5336 100644 --- a/include/ucode/lexer.h +++ b/include/ucode/lexer.h @@ -106,6 +106,9 @@ typedef enum { TK_THIS, TK_DELETE, TK_CONST, + TK_QLBRACK, + TK_QLPAREN, + TK_QDOT, TK_EOF, TK_ERROR diff --git a/include/ucode/vm.h b/include/ucode/vm.h index 553cf61..1e9357f 100644 --- a/include/ucode/vm.h +++ b/include/ucode/vm.h @@ -40,6 +40,7 @@ __insn(LLOC) \ __insn(LUPV) \ __insn(LVAR) \ __insn(LVAL) \ +__insn(QLVAL) \ __insn(CLFN) \ __insn(ARFN) \ __insn(SLOC) \ @@ -87,6 +88,8 @@ __insn(CUPV) \ __insn(RETURN) \ __insn(CALL) \ __insn(MCALL) \ +__insn(QCALL) \ +__insn(QMCALL) \ __insn(PRINT) \ __insn(NEXTK) \ __insn(NEXTKV) \ |