summaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-09-25 19:34:14 +0200
committerJo-Philipp Wich <jo@mein.io>2021-10-11 09:39:12 +0200
commit4ee06d8138a107908a9fb45220fea32055b3c48a (patch)
tree2f0bd421931b2dd2daf504719beb63cc2885d23a /include
parente43b751aab997c5e74a0712f7569d90bd3d6b429 (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.h25
-rw-r--r--include/ucode/lexer.h3
-rw-r--r--include/ucode/vm.h3
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) \