Mailing List Archive

[master] 417bf145a Find VMOD objects methods via their typed symbols
commit 417bf145a8682c21ee62be0ee4862cff458aa90f
Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
Date: Fri Dec 13 18:44:08 2019 +0100

Find VMOD objects methods via their typed symbols

VMODs can now use the same facility as native types to find methods
based on the type of the instance instead of the instance itself.

Because SYM_METHOD symbols are tied to a type instead of an instance
we lose that "extra" argument. To circumvent this, an expression will
keep track of the instance before evaluating a method.

With this, VCL expression evaluation is no longer aware of methods
implementation details, and feeds entirely from the symbol table.

diff --git a/bin/varnishtest/tests/v00018.vtc b/bin/varnishtest/tests/v00018.vtc
index 572fde61e..32583760b 100644
--- a/bin/varnishtest/tests/v00018.vtc
+++ b/bin/varnishtest/tests/v00018.vtc
@@ -133,3 +133,17 @@ varnish v1 -syntax 4.0 -errvcl {Symbol not found:} {
return (vcl(vcl_recv));
}
}
+
+varnish v1 -errvcl {Syntax error} {
+ import directors;
+ sub vcl_recv {
+ set req.backend_hint = directors.round_robin.backend();
+ }
+}
+
+varnish v1 -errvcl {Syntax error} {
+ import directors;
+ sub vcl_recv {
+ directors.round_robin.backend();
+ }
+}
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 1fda4241b..47f3e51d0 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -333,6 +333,7 @@ char *TlDup(struct vcc *tl, const char *s);
/* vcc_expr.c */
void vcc_Expr(struct vcc *tl, vcc_type_t typ);
sym_act_f vcc_Act_Call;
+sym_act_f vcc_Act_Obj;
void vcc_Expr_Init(struct vcc *tl);
sym_expr_t vcc_Eval_Var;
sym_expr_t vcc_Eval_Handle;
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 71c618a83..02e67d92d 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -50,6 +50,7 @@ struct expr {
#define EXPR_CONST (1<<1)
#define EXPR_STR_CONST (1<<2) // Last STRING_LIST elem is "..."
struct token *t1, *t2;
+ struct symbol *instance;
int nstr;
};

@@ -484,6 +485,17 @@ vcc_func(struct vcc *tl, struct expr **e, const void *priv,
sa = NULL;
}
vv = VTAILQ_NEXT(vv, list);
+ if (sym->kind == SYM_METHOD) {
+ if (*e == NULL) {
+ VSB_cat(tl->sb, "Syntax error.");
+ tl->err = 1;
+ return;
+ }
+ vcc_NextToken(tl);
+ AZ(extra);
+ AN((*e)->instance);
+ extra = (*e)->instance->rname;
+ }
SkipToken(tl, '(');
if (extra == NULL) {
extra = "";
@@ -651,7 +663,7 @@ vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, struct token *t,

(void)t;
(void)fmt;
- assert(sym->kind == SYM_FUNC);
+ assert(sym->kind == SYM_FUNC || sym->kind == SYM_METHOD);
AN(sym->eval_priv);

vcc_func(tl, e, sym->eval_priv, sym->extra, sym);
@@ -701,6 +713,12 @@ vcc_expr5(struct vcc *tl, struct expr **e, vcc_type_t fmt)
XREF_REF);
ERRCHK(tl);
AN(sym);
+ if (sym->kind == SYM_INSTANCE) {
+ AZ(*e);
+ *e = vcc_new_expr(sym->type);
+ (*e)->instance = sym;
+ return;
+ }
if (sym->kind == SYM_FUNC && sym->type == VOID) {
VSB_cat(tl->sb, "Function returns VOID:\n");
vcc_ErrWhere(tl, tl->t);
@@ -849,8 +867,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
if (sym == NULL) {
VSB_cat(tl->sb, "Unknown property ");
vcc_ErrToken(tl, tl->t);
- VSB_printf(tl->sb,
- " for type %s\n", (*e)->fmt->name);
+ VSB_printf(tl->sb, " for type %s\n", (*e)->fmt->name);
vcc_ErrWhere(tl, tl->t);
return;
}
@@ -1406,6 +1423,23 @@ vcc_Act_Call(struct vcc *tl, struct token *t, struct symbol *sym)
}
vcc_delete_expr(e);
}
+
+void v_matchproto_(sym_act_f)
+vcc_Act_Obj(struct vcc *tl, struct token *t, struct symbol *sym)
+{
+
+ struct expr *e = NULL;
+
+ assert(sym->kind == SYM_INSTANCE);
+ tl->t = t;
+ vcc_expr4(tl, &e, sym->type);
+ ERRCHK(tl);
+ vcc_expr_fmt(tl->fb, tl->indent, e);
+ vcc_delete_expr(e);
+ SkipToken(tl, ';');
+ VSB_cat(tl->fb, ";\n");
+}
+
/*--------------------------------------------------------------------
*/

diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c
index ec7b5e614..3331d961c 100644
--- a/lib/libvcc/vcc_parse.c
+++ b/lib/libvcc/vcc_parse.c
@@ -183,7 +183,7 @@ vcc_Compound(struct vcc *tl)
return;
case ID:
sym = VCC_SymbolGet(tl, SYM_MAIN, SYM_NONE,
- SYMTAB_NOERR, XREF_NONE);
+ SYMTAB_PARTIAL, XREF_NONE);
if (sym == NULL) {
VSB_printf(tl->sb, "Symbol not found.\n");
vcc_ErrWhere(tl, tl->t);
diff --git a/lib/libvcc/vcc_symb.c b/lib/libvcc/vcc_symb.c
index ea2d78d4c..b97b20bca 100644
--- a/lib/libvcc/vcc_symb.c
+++ b/lib/libvcc/vcc_symb.c
@@ -364,8 +364,8 @@ VCC_SymbolGet(struct vcc *tl, vcc_ns_t ns, vcc_kind_t kind,
return (sym);
}

-struct symbol *
-VCC_TypeSymbol(struct vcc *tl, vcc_kind_t kind, vcc_type_t type)
+static struct symbol *
+vcc_TypeSymbol(struct vcc *tl, vcc_ns_t ns, vcc_kind_t kind, vcc_type_t type)
{
struct token t[1], *t0;
struct symbol *sym;
@@ -383,13 +383,24 @@ VCC_TypeSymbol(struct vcc *tl, vcc_kind_t kind, vcc_type_t type)

t0 = tl->t;
tl->t = t;
- sym = VCC_SymbolGet(tl, SYM_TYPE, kind, SYMTAB_NOERR, XREF_NONE);
+ sym = VCC_SymbolGet(tl, ns, kind, SYMTAB_NOERR, XREF_NONE);
tl->t = t0;
VSB_destroy(&buf);

return (sym);
}

+struct symbol *
+VCC_TypeSymbol(struct vcc *tl, vcc_kind_t kind, vcc_type_t type)
+{
+
+ if (strchr(type->name, '.') == NULL)
+ return (vcc_TypeSymbol(tl, SYM_TYPE, kind, type));
+
+ /* NB: type imported from a VMOD */
+ return (vcc_TypeSymbol(tl, SYM_MAIN, kind, type));
+}
+
struct symbol *
VCC_MkSym(struct vcc *tl, const char *b, vcc_ns_t ns, vcc_kind_t kind,
int vlo, int vhi)
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index be31db8cd..ecf977a16 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -203,7 +203,7 @@ vcc_vmod_kind(const char *type)
return (kind); \
} while (0)
VMOD_KIND("$OBJ", SYM_OBJECT);
- VMOD_KIND("$METHOD", SYM_FUNC);
+ VMOD_KIND("$METHOD", SYM_METHOD);
VMOD_KIND("$FUNC", SYM_FUNC);
#undef VMOD_KIND
return (SYM_NONE);
@@ -244,7 +244,7 @@ vcc_VmodSymbols(struct vcc *tl, struct symbol *msym)
if (msym->kind == SYM_VMOD) {
CAST_OBJ_NOTNULL(vj, msym->eval_priv, VJSN_MAGIC);
vv = VTAILQ_FIRST(&vj->value->children);
- } else if (msym->kind == SYM_INSTANCE || msym->kind == SYM_OBJECT) {
+ } else if (msym->kind == SYM_OBJECT) {
CAST_OBJ_NOTNULL(vv, msym->eval_priv, VJSN_VAL_MAGIC);
} else {
WRONG("symbol kind");
@@ -290,13 +290,10 @@ vcc_VmodSymbols(struct vcc *tl, struct symbol *msym)

if (kind == SYM_FUNC) {
func_sym(fsym, msym->vmod_name, VTAILQ_NEXT(vv2, list));
- /* XXX: until we use SYM_METHOD only, string check. */
- if (!strcmp(vv1->value, "$METHOD")) {
- fsym->extra = msym->rname;
- /* XXX: cohabitation temporary hack */
- if (msym->kind == SYM_OBJECT)
- fsym->kind = SYM_METHOD;
- }
+ } else if (kind == SYM_METHOD) {
+ func_sym(fsym, msym->vmod_name, VTAILQ_NEXT(vv2, list));
+ fsym->extra = msym->rname;
+ fsym->kind = SYM_METHOD;
} else {
assert(kind == SYM_OBJECT);
fsym->eval_priv = vv2;
@@ -490,6 +487,7 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)
ERRCHK(tl);
AN(isym);
isym->noref = 1;
+ isym->action = vcc_Act_Obj;

SkipToken(tl, '=');
ExpectErr(tl, ID);
@@ -506,7 +504,6 @@ vcc_Act_New(struct vcc *tl, struct token *t, struct symbol *sym)

isym->vmod_name = osym->vmod_name;
isym->eval_priv = vv;
- vcc_VmodSymbols(tl, isym);

vv = VTAILQ_NEXT(vv, list);
// vv = flags
_______________________________________________
varnish-commit mailing list
varnish-commit@varnish-cache.org
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-commit