Commit 417bf145 authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

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.
parent 7cd19157
......@@ -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();
}
}
......@@ -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;
......
......@@ -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");
}
/*--------------------------------------------------------------------
*/
......
......@@ -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);
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment