scoped bindings

This commit is contained in:
Ellen Arvidsson 2025-06-24 16:31:23 +02:00
parent 396716de09
commit 858f5c3eed
17 changed files with 1185 additions and 821 deletions

File diff suppressed because it is too large Load diff

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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),

View file

@ -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;

View file

@ -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: