scoped bindings
This commit is contained in:
parent
396716de09
commit
858f5c3eed
17 changed files with 1185 additions and 821 deletions
File diff suppressed because it is too large
Load diff
|
@ -5,9 +5,12 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "spho/spho.h"
|
||||
|
||||
#include "msph/err.h"
|
||||
#include "msph/token.h"
|
||||
|
||||
|
||||
struct msph_matcher {
|
||||
size_t off;
|
||||
size_t matchlen;
|
||||
|
|
583
src/msph/tree.c
583
src/msph/tree.c
File diff suppressed because it is too large
Load diff
184
src/spho/bind.c
184
src/spho/bind.c
|
@ -1,77 +1,165 @@
|
|||
#include <sys/queue.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "spho/ctx.h"
|
||||
#include "spho/spho.h"
|
||||
#include "spho/scope.h"
|
||||
#include "spho/bind.h"
|
||||
|
||||
struct spho_bind *
|
||||
spho_bind_create(struct spho_ctx *ctx, struct spho_bind_scope *binder,
|
||||
struct spho_bind *parent)
|
||||
struct spho_prebind *
|
||||
spho_prebind_create(struct spho_scope *sc)
|
||||
{
|
||||
struct spho_bind *bind;
|
||||
size_t i;
|
||||
struct spho_nom *nom;
|
||||
struct spho_prebind *bind;
|
||||
|
||||
SPHO_PRECOND(ctx != NULL);
|
||||
SPHO_PRECOND(binder != NULL);
|
||||
SPHO_PRECOND(sc != NULL);
|
||||
|
||||
if ((bind = malloc(sizeof(*bind))) == NULL) {
|
||||
SPHO_ERR(binder->sc->ctx, SPHO_ERR_SYS);
|
||||
if ((bind = calloc(1, sizeof(*bind))) == NULL) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_SYS);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
bind->ctx = ctx;
|
||||
bind->binder = binder;
|
||||
bind->parent = parent;
|
||||
if ((bind->binds = calloc(sc->n_noms, sizeof(*bind->binds))) == NULL) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_SYS);
|
||||
free(bind);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
bind->sc = sc;
|
||||
bind->sz = sc->n_noms;
|
||||
|
||||
|
||||
i = 0;
|
||||
SLIST_FOREACH(nom, &sc->noms, next) {
|
||||
SPHO_ASSERT(i < bind->sz);
|
||||
bind->binds[i++] = (struct spho_prebind_pair) { NULL, 0, NULL };
|
||||
}
|
||||
|
||||
return (bind);
|
||||
}
|
||||
|
||||
int
|
||||
spho_bind_lkp(int, struct spho_bind *bind, struct spho_nom *nom,
|
||||
union spho_bound **out)
|
||||
spho_prebind_undef(struct spho_prebind *bind,
|
||||
const struct spho_nom *nom)
|
||||
{
|
||||
// TODO
|
||||
size_t i;
|
||||
SPHO_PRECOND(bind != NULL);
|
||||
SPHO_PRECOND(nom != NULL);
|
||||
|
||||
for (i = 0; i < bind->sz; i++) {
|
||||
if (nom == bind->binds[i].nom) {
|
||||
if (bind->binds[i].kind != SPHO_BIND_UNDECLARED) {
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_BIND_DUPL);
|
||||
return (-1);
|
||||
}
|
||||
bind->binds[i].kind = SPHO_BIND_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
int
|
||||
spho_prebind_tp(struct spho_prebind *bind, const struct spho_nom *nom,
|
||||
const struct spho_tp *tp)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
SPHO_PRECOND(bind != NULL);
|
||||
SPHO_PRECOND(nom != NULL);
|
||||
SPHO_PRECOND(tp != NULL);
|
||||
|
||||
for (i = 0; i < bind->sz; i++) {
|
||||
if (nom == bind->binds[i].nom) {
|
||||
if (bind->binds[i].kind != SPHO_BIND_UNDECLARED) {
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_BIND_DUPL);
|
||||
return (-1);
|
||||
}
|
||||
bind->binds[i].kind = SPHO_BIND_TP;
|
||||
bind->binds[i].val = (union spho_prebind_val) tp;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_BIND_NOTFOUND);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
spho_bind_destroy(struct spho_bind *bind)
|
||||
int
|
||||
spho_prebind_tp_op(struct spho_prebind *bind, const struct spho_nom *nom,
|
||||
const struct spho_tp_op *op)
|
||||
{
|
||||
free(bind);
|
||||
}
|
||||
size_t i;
|
||||
|
||||
SPHO_PRECOND(bind != NULL);
|
||||
SPHO_PRECOND(nom != NULL);
|
||||
SPHO_PRECOND(op != NULL);
|
||||
|
||||
struct spho_bind_scope *
|
||||
spho_bind_scope_create(struct spho_scope *sc)
|
||||
{
|
||||
size_t sz;
|
||||
struct spho_binding *bds;
|
||||
struct spho_bind_scope *ret;
|
||||
|
||||
SPHO_PRECOND(sc != NULL);
|
||||
|
||||
if ((ret = malloc(sizeof(*ret))) == NULL) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_SYS);
|
||||
return (NULL);
|
||||
for (i = 0; i < bind->sz; i++) {
|
||||
if (nom == bind->binds[i].nom) {
|
||||
if (bind->binds[i].kind != SPHO_BIND_UNDECLARED) {
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_BIND_DUPL);
|
||||
return (-1);
|
||||
}
|
||||
bind->binds[i].kind = SPHO_BIND_TP_OP;
|
||||
bind->binds[i].val = (union spho_prebind_val) op;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((bds = calloc(sz, sizeof(*bds))) == NULL) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_SYS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret->sc = sc;
|
||||
ret->cap_bds = sz;
|
||||
ret->n_bds = 0;
|
||||
ret->bds = bds;
|
||||
|
||||
err:
|
||||
free(ret);
|
||||
|
||||
return (NULL);
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_BIND_NOTFOUND);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
spho_binder_add_tp(struct spho_bind_scope *bdr, struct spho_nom *nom,
|
||||
struct spho_tp *tp)
|
||||
spho_prebind_member_tp(struct spho_prebind *bind, const struct spho_nom *nom,
|
||||
const struct spho_tp *memb_tp)
|
||||
{
|
||||
|
||||
size_t i;
|
||||
|
||||
SPHO_PRECOND(bind != NULL);
|
||||
SPHO_PRECOND(nom != NULL);
|
||||
SPHO_PRECOND(memb_tp != NULL);
|
||||
|
||||
for (i = 0; i < bind->sz; i++) {
|
||||
if (nom == bind->binds[i].nom) {
|
||||
if (bind->binds[i].kind != SPHO_BIND_UNDECLARED) {
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_BIND_DUPL);
|
||||
return (-1);
|
||||
}
|
||||
bind->binds[i].kind = SPHO_BIND_MEMB_TP;
|
||||
bind->binds[i].val = (union spho_prebind_val) memb_tp;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_BIND_NOTFOUND);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
struct spho_prebind *
|
||||
spho_prebind_dupl(const struct spho_prebind *bind)
|
||||
{
|
||||
struct spho_prebind *cp;
|
||||
|
||||
if ((cp = calloc(1, sizeof(*cp))) == NULL) {
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_SYS);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((cp->binds = calloc(bind->sz, sizeof(*cp->binds))) == NULL) {
|
||||
SPHO_ERR(bind->sc->ctx, SPHO_ERR_SYS);
|
||||
free(cp);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
memcpy(cp->binds, bind->binds, bind->sz * sizeof(*bind->binds));
|
||||
|
||||
return (cp);
|
||||
}
|
||||
|
||||
void
|
||||
spho_prebind_destroy(struct spho_prebind *bind)
|
||||
{
|
||||
free(bind->binds);
|
||||
free(bind);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "spho/ctx.h"
|
||||
#include "spho/spho.h"
|
||||
|
||||
static const char *spho_ctx_sys_strerror(struct spho_ctx *);
|
||||
static const char *spho_ctx_intern_strerror(struct spho_ctx *);
|
||||
|
@ -23,6 +23,10 @@ struct spho_err spho_errmsgs[] = {
|
|||
|
||||
{ SPHO_ERR_NOM_INUSE, "name already declared in current scope" },
|
||||
{ SPHO_ERR_NOM_NOTINSCOPE, "name not in scope" },
|
||||
|
||||
{ SPHO_ERR_BIND_NOTFOUND, "binding name not found in scope" },
|
||||
{ SPHO_ERR_BIND_DUPL, "duplicate binding" },
|
||||
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
|
@ -91,7 +95,7 @@ spho_ctx_sys_strerror(struct spho_ctx *ctx)
|
|||
res = snprintf(ctx->errbuf, sizeof(ctx->errbuf),
|
||||
"spho_syserr: %s (%d) (%s:%d)", strerror(ctx->err_info),
|
||||
ctx->err_info, ctx->filebuf, ctx->errline);
|
||||
if (res >= sizeof(ctx->errbuf))
|
||||
if (res >= (ssize_t)sizeof(ctx->errbuf))
|
||||
ctx->errbuf[sizeof(ctx->errbuf) - 1] = '\0';
|
||||
#else
|
||||
res = snprintf(ctx->errbuf, sizeof(ctx->errbuf),
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
static void spho_nom_term(struct spho_nom *);
|
||||
|
||||
static int scope_nom_lookup_str_loc(struct spho_scope *, const char *,
|
||||
static int scope_nom_lookup_str_local(struct spho_scope *, const char *,
|
||||
size_t, struct spho_nom **);
|
||||
static int scope_nom_in_loc(struct spho_scope *, struct spho_nom *);
|
||||
static int scope_nom_in_local(struct spho_scope *, struct spho_nom *);
|
||||
|
||||
int
|
||||
spho_scope_init(struct spho_scope *sc, struct spho_ctx *ctx,
|
||||
|
@ -22,10 +22,13 @@ spho_scope_init(struct spho_scope *sc, struct spho_ctx *ctx,
|
|||
sc->parent = p;
|
||||
|
||||
SLIST_INIT(&sc->subs);
|
||||
|
||||
SLIST_INIT(&sc->noms);
|
||||
sc->n_noms = 0;
|
||||
|
||||
TAILQ_INIT(&sc->tps);
|
||||
|
||||
sc->stat_bind = NULL;
|
||||
sc->bind = NULL;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -39,9 +42,9 @@ spho_scope_term(struct spho_scope *sc)
|
|||
|
||||
sc->parent = NULL;
|
||||
|
||||
if (sc->stat_bind == NULL)
|
||||
spho_bind_scope_destroy(sc->stat_bind);
|
||||
sc->stat_bind = NULL;
|
||||
if (sc->bind == NULL)
|
||||
spho_prebind_destroy(sc->bind);
|
||||
sc->bind = NULL;
|
||||
}
|
||||
|
||||
struct spho_scope *
|
||||
|
@ -95,16 +98,12 @@ spho_scope_destroy(struct spho_scope *sc)
|
|||
struct spho_nom *
|
||||
spho_scope_nom_add(struct spho_scope *sc, const char *nomstr, size_t sz)
|
||||
{
|
||||
#ifdef SPHO_USE_STRLCPY
|
||||
size_t res;
|
||||
#else
|
||||
ssize_t res;
|
||||
#endif
|
||||
struct spho_nom *nom;
|
||||
|
||||
nom = NULL;
|
||||
|
||||
if (scope_nom_lookup_str_loc(sc, nomstr, sz, &nom) == -1)
|
||||
if (scope_nom_lookup_str_local(sc, nomstr, sz, &nom) == -1)
|
||||
return (NULL);
|
||||
|
||||
if (nom != NULL) {
|
||||
|
@ -117,25 +116,14 @@ spho_scope_nom_add(struct spho_scope *sc, const char *nomstr, size_t sz)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
#ifdef SPHO_USE_STRLCPY
|
||||
res = strlcpy(nom->s, nomstr, sizeof(nom->s));
|
||||
if (res >= sizeof(nom->s)) {
|
||||
SPHO_SC_ERR(sc, SPHO_ERR_TOOBIG);
|
||||
goto err;
|
||||
}
|
||||
#else
|
||||
res = snprintf(nom->s, sizeof(nom->s), "%s", nomstr);
|
||||
if (res < 0) {
|
||||
SPHO_SC_ERR(sc, SPHO_ERR_SYS);
|
||||
goto err;
|
||||
}
|
||||
if (res >= (ssize_t)sizeof(nom->s)) {
|
||||
SPHO_SC_ERR(sc, SPHO_ERR_TOOBIG);
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
SLIST_INSERT_HEAD(&sc->noms, nom, next);
|
||||
sc->n_noms++;
|
||||
|
||||
return (nom);
|
||||
err:
|
||||
|
@ -187,9 +175,9 @@ spho_scope_nom_lookup_str_strict(struct spho_scope *sc, const char *nomstr,
|
|||
}
|
||||
|
||||
int
|
||||
spho_scope_static_bind_init(struct spho_scope *sc)
|
||||
spho_scope_prebind_init(struct spho_scope *sc)
|
||||
{
|
||||
if ((sc->stat_bind = spho_bind_scope_create(sc))
|
||||
if ((sc->bind = spho_prebind_create(sc))
|
||||
== NULL) {
|
||||
return (-1);
|
||||
}
|
||||
|
@ -198,19 +186,42 @@ spho_scope_static_bind_init(struct spho_scope *sc)
|
|||
}
|
||||
|
||||
int
|
||||
spho_scope_static_bind_add_tp(struct spho_scope *sc, struct spho_nom *nom,
|
||||
spho_scope_prebind_tp(struct spho_scope *sc, struct spho_nom *nom,
|
||||
struct spho_tp *tp)
|
||||
{
|
||||
if (! scope_nom_in_loc(sc, nom)) {
|
||||
if (! scope_nom_in_local(sc, nom)) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_NOM_NOTINSCOPE);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (spho_bind_scope_add_tp(sc->stat_bind, nom, tp));
|
||||
return (spho_prebind_tp(sc->bind, nom, tp));
|
||||
}
|
||||
|
||||
int
|
||||
spho_scope_prebind_tp_op(struct spho_scope *sc, struct spho_nom *nom,
|
||||
struct spho_tp_op *tp_op)
|
||||
{
|
||||
if (! scope_nom_in_local(sc, nom)) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_NOM_NOTINSCOPE);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (spho_prebind_tp_op(sc->bind, nom, tp_op));
|
||||
}
|
||||
|
||||
int
|
||||
spho_scope_prebind_undef(struct spho_scope *sc, struct spho_nom *nom)
|
||||
{
|
||||
if (! scope_nom_in_local(sc, nom)) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_NOM_NOTINSCOPE);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (spho_prebind_undef(sc->bind, nom));
|
||||
}
|
||||
|
||||
static int
|
||||
scope_nom_lookup_str_loc(struct spho_scope *sc, const char *nomstr,
|
||||
scope_nom_lookup_str_local(struct spho_scope *sc, const char *nomstr,
|
||||
size_t sz, struct spho_nom **out)
|
||||
{
|
||||
struct spho_nom *nom;
|
||||
|
@ -234,7 +245,7 @@ scope_nom_lookup_str_loc(struct spho_scope *sc, const char *nomstr,
|
|||
}
|
||||
|
||||
static int
|
||||
scope_nom_in_loc(struct spho_scope *sc, struct spho_nom *nom)
|
||||
scope_nom_in_local(struct spho_scope *sc, struct spho_nom *nom)
|
||||
{
|
||||
struct spho_nom *sc_nom;
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "spho/ctx.h"
|
||||
#include "spho/scope.h"
|
||||
#include "spho/spho.h"
|
||||
#include "spho/tp.h"
|
||||
|
||||
|
||||
|
@ -26,6 +25,22 @@ spho_tp_alloc(struct spho_scope *sc)
|
|||
return ((struct spho_tp *)tp_alloc);
|
||||
}
|
||||
|
||||
static struct spho_tp_op *
|
||||
spho_tp_op_alloc(struct spho_scope *sc)
|
||||
{
|
||||
struct spho_tp_alloc *tp_alloc;
|
||||
|
||||
if ((tp_alloc = calloc(1, sizeof(*tp_alloc))) == NULL) {
|
||||
SPHO_SC_ERR(sc, SPHO_ERR_SYS);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
((struct spho_tp_op *)tp_alloc)->sc = sc;
|
||||
TAILQ_INSERT_TAIL(&sc->tps, tp_alloc, allocs);
|
||||
|
||||
return ((struct spho_tp_op *)tp_alloc);
|
||||
}
|
||||
|
||||
static void
|
||||
spho_tp_free(struct spho_tp *tp)
|
||||
{
|
||||
|
@ -222,7 +237,39 @@ spho_tp_create_nominal(struct spho_scope *sc, struct spho_nom *nom)
|
|||
return (ret);
|
||||
}
|
||||
|
||||
struct spho_tp *
|
||||
spho_tp_create_var(struct spho_scope *sc, struct spho_nom *nom)
|
||||
{
|
||||
struct spho_tp *ret;
|
||||
|
||||
if ((ret = spho_tp_alloc(sc)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
ret->kind = SPHO_TP_FORM_VAR;
|
||||
ret->d.nom.nom = nom;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
struct spho_tp_op *
|
||||
spho_tp_op_create(struct spho_scope *sc, struct spho_scope *op_sc, struct spho_tp *tp)
|
||||
{
|
||||
struct spho_tp_op *op;
|
||||
|
||||
SPHO_PRECOND(sc != NULL);
|
||||
SPHO_PRECOND(op_sc != NULL);
|
||||
SPHO_PRECOND(tp != NULL);
|
||||
|
||||
if ((op = spho_tp_op_alloc(sc)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
op->sc = sc;
|
||||
op->op_sc = op_sc;
|
||||
op->op_tp = tp;
|
||||
|
||||
return (op);
|
||||
}
|
||||
|
||||
/* Free type structure. External data (like nom) are freed elsewhere. */
|
||||
void
|
||||
|
@ -234,6 +281,7 @@ spho_tp_destroy(struct spho_tp *tp)
|
|||
case SPHO_TP_FORM_TRUE:
|
||||
case SPHO_TP_FORM_FALSE:
|
||||
case SPHO_TP_FORM_NAME:
|
||||
case SPHO_TP_FORM_VAR:
|
||||
break;
|
||||
case SPHO_TP_FORM_CONJ:
|
||||
case SPHO_TP_FORM_DISJ:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue