recursive lockstep example

This commit is contained in:
Ellen Arvidsson 2025-06-13 17:36:36 +02:00
parent 26d0d3158f
commit e036fa16f8
15 changed files with 536 additions and 133 deletions

View file

@ -13,6 +13,11 @@ static int msph_tree_sphophi_decor_nom_lookup(struct spho_scope *,
struct msph_tree *);
static int msph_tree_sphophi_decor_tp(struct spho_scope *,
struct msph_tree *);
static int msph_tree_sphophi_bind_static_tp_name(struct spho_scope *,
struct msph_tree *);
static int msph_tree_sphophi_get_scope(struct msph_tree *, struct
spho_scope **);
/* foreach_pre: top down foreach */
static int msph_sphophi_foreach_pre(msph_tree_sphophi_f,
@ -135,6 +140,13 @@ msph_sphophi_tp(struct msph_tree_root *root)
return (msph_sphophi_foreach_post(msph_tree_sphophi_decor_tp, root));
}
int
msph_sphophi_bind_static_tp_names(struct msph_tree_root *root)
{
return (msph_sphophi_foreach_pre(msph_tree_sphophi_bind_static_tp_name,
root));
}
int msph_sphophi(struct msph_tree_root *root)
{
int ret;
@ -147,16 +159,18 @@ int msph_sphophi(struct msph_tree_root *root)
return (ret);
if ((ret = msph_sphophi_tp(root)) != 0)
return (ret);
if ((ret = msph_sphophi_bind_static_tp_names(root)) != 0)
return (ret);
return (ret);
}
#define IS_BINDING(tree) (((tree)->type == MSPH_TREE_TPDEF) || \
((tree)->type == MSPH_TREE_NOMINDECL) || \
((tree)->type == MSPH_TREE_MEMBDECL) || \
((tree)->type == MSPH_TREE_FORALL))
#define IS_TPEXPR(tree) (((tree)->type & MSPH_TREE_TPEXPR))
#define IS_BINDING(tree) ((tree)->type == MSPH_TREE_TPDEF || \
(tree)->type == MSPH_TREE_NOMINDECL || \
(tree)->type == MSPH_TREE_MEMBDECL || \
(tree)->type == MSPH_TREE_FORALL)
#define IS_TPEXPR(tree) ((tree)->type & MSPH_TREE_TPEXPR)
static int
msph_tree_sphophi_decor_scope(struct spho_scope *sc, struct msph_tree *tree)
@ -214,11 +228,8 @@ msph_tree_sphophi_decor_nom_lookup(struct spho_scope *sc,
if (tree->parent->type != MSPH_TREE_NAME)
break;
ident = (struct msph_tree_ident *)tree;
if ((ret = spho_scope_nom_lookup(sc, ident->str,
sizeof(ident->str), &ident->dec.nom)) != 0)
break;
if (ident->dec.nom == NULL)
ret = -1;
ret = spho_scope_nom_lookup_str_strict(sc, ident->str,
sizeof(ident->str), &ident->dec.nom);
break;
default:
break;
@ -265,31 +276,31 @@ msph_tree_sphophi_decor_tp(struct spho_scope *sc, struct msph_tree *tree)
switch (tree->type) {
case MSPH_TREE_CONJ:
conj = (struct msph_tree_conj *)tree;
if ((TP(&conj->htpe) = spho_tp_create_conj(sc, TP(conj->ltp),
if ((tpexpr->dec.tp = spho_tp_create_conj(sc, TP(conj->ltp),
TP(conj->rtp))) == NULL)
goto cleanup;
break;
case MSPH_TREE_DISJ:
disj = (struct msph_tree_disj *)tree;
if ((TP(&disj->htpe) = spho_tp_create_conj(sc, TP(disj->ltp),
if ((tpexpr->dec.tp = spho_tp_create_conj(sc, TP(disj->ltp),
TP(disj->rtp))) == NULL)
goto cleanup;
break;
case MSPH_TREE_IMPL:
impl = (struct msph_tree_impl *)tree;
if ((TP(&impl->htpe) = spho_tp_create_conj(sc, TP(impl->ltp),
if ((tpexpr->dec.tp = spho_tp_create_conj(sc, TP(impl->ltp),
TP(impl->rtp))) == NULL)
goto cleanup;
break;
case MSPH_TREE_ARROW:
arrow = (struct msph_tree_arrow *)tree;
if ((TP(&arrow->htpe) = spho_tp_create_conj(sc, TP(arrow->ltp),
if ((tpexpr->dec.tp = spho_tp_create_conj(sc, TP(arrow->ltp),
TP(arrow->rtp))) == NULL)
goto cleanup;
break;
case MSPH_TREE_NAME:
name = (struct msph_tree_name *)tree;
if ((TP(&name->htpe) = spho_tp_create_name(sc, NOM(name->id)))
if ((tpexpr->dec.tp = spho_tp_create_name(sc, NOM(name->id)))
== NULL)
goto cleanup;
break;
@ -303,34 +314,34 @@ msph_tree_sphophi_decor_tp(struct spho_scope *sc, struct msph_tree *tree)
STAILQ_FOREACH(tpexpr_i, &appl->head, entries) {
STAILQ_INSERT_TAIL(tps, tpexpr_i->dec.tp, entries);
}
if ((TP(&appl->htpe) = spho_tp_create_appl(sc, NOM(appl->id),
if ((tpexpr->dec.tp = spho_tp_create_appl(sc, NOM(appl->id),
tps)) == NULL)
goto cleanup;
tps = NULL;
break;
case MSPH_TREE_TRUE:
if ((TP(tpexpr) = spho_tp_create_true(sc)) == NULL)
if ((tpexpr->dec.tp = spho_tp_create_true(sc)) == NULL)
goto cleanup;
break;
case MSPH_TREE_FALSE:
if ((TP(tpexpr) = spho_tp_create_false(sc)) == NULL)
if ((tpexpr->dec.tp = spho_tp_create_false(sc)) == NULL)
goto cleanup;
break;
case MSPH_TREE_FORALL:
forall = (struct msph_tree_forall *)tree;
if ((TP(&forall->htpe) = spho_tp_create_forall(sc,
if ((tpexpr->dec.tp = spho_tp_create_forall(sc,
NOM(forall->id), TP(forall->inner))) == NULL)
goto cleanup;
break;
case MSPH_TREE_BOX:
box = (struct msph_tree_box *)tree;
if ((TP(&box->htpe) = spho_tp_create_box(sc, TP(box->inner)))
if ((tpexpr->dec.tp = spho_tp_create_box(sc, TP(box->inner)))
== NULL)
goto cleanup;
break;
case MSPH_TREE_PAREN:
paren = (struct msph_tree_paren *)tree;
if ((TP(&paren->htpe) = TP(paren->inner)) == NULL)
if ((tpexpr->dec.tp = TP(paren->inner)) == NULL)
goto cleanup;
break;
case MSPH_TREE_TRAIT:
@ -352,7 +363,7 @@ msph_tree_sphophi_decor_tp(struct spho_scope *sc, struct msph_tree *tree)
== NULL)
goto cleanup;
}
trait->htpe.dec.tp = tp;
tpexpr->dec.tp = tp;
}
break;
default:
@ -369,6 +380,71 @@ cleanup:
return (ret);
}
static int
msph_tree_sphophi_bind_static_tp_name(struct spho_scope *sc,
struct msph_tree *tree)
{
int ret;
struct spho_scope *sub_sc;
struct msph_tree_tpdef *tpdef;
struct msph_tree_nomindecl *nomdecl;
ret = 0;
if (MSPH_TREE_SCOPE(tree->type) &&
MSPH_TREE_STATIC_BIND(tree->type)) {
if ((ret = msph_tree_sphophi_get_scope(tree, &sub_sc)) == -1)
goto ret;
if ((ret = spho_scope_tp_bind_init(sub_sc)) == -1)
goto ret;
}
switch (tree->type) {
case MSPH_TREE_TPDEF:
tpdef = (struct msph_tree_tpdef *)tree;
ret = spho_scope_tp_bind_nom(sc, tpdef->id->dec.nom,
tpdef->tp->dec.tp);
break;
case MSPH_TREE_NOMINDECL:
nomdecl = (struct msph_tree_nomindecl *)tree;
ret = spho_scope_tp_bind_nom(sc, nomdecl->id->dec.nom,
nomdecl->tp->dec.tp);
break;
default:
break;
}
ret:
return (ret);
}
static int
msph_tree_sphophi_get_scope(struct msph_tree *tree, struct spho_scope **out)
{
SPHO_PRECOND(MSPH_TREE_SCOPE(tree->type));
*out = NULL;
switch (tree->type) {
case MSPH_TREE_ROOT:
*out = spho_scope_global(
((struct msph_tree_root *)tree)->ctx->spho);
break;
case MSPH_TREE_UNIT:
*out = ((struct msph_tree_unit *)tree)->dec.sc;
break;
case MSPH_TREE_TRAIT:
*out = ((struct msph_tree_trait *)tree)->dec.sc;
break;
default:
break;
}
SPHO_POSTCOND(*out != NULL);
return (0);
}
/* foreach pre: top down foreach node */
static int
msph_sphophi_foreach_pre(msph_tree_sphophi_f f, struct msph_tree_root *root)

View file

@ -1180,6 +1180,8 @@ struct msph_tree_dir *
tree_parse_nomindecl(struct tree_parse *p, struct msph_tree *parent)
{
int res;
struct msph_tree_ident *id;
struct msph_tree_name *name;
struct msph_tree_nomindecl *nomd;
EXPECT_CURR_TOKEN(p, TOK_KW_NOMINAL, MSPH_TREE_NOMINDECL,
@ -1193,11 +1195,28 @@ tree_parse_nomindecl(struct tree_parse *p, struct msph_tree *parent)
T(nomd)->parent = parent;
TXT(nomd)->pos = CURR_TOKEN(p)->pos;
nomd->id = NULL;
nomd->tp = NULL;
EXPECT_READ_NEXT(res, p, MSPH_TREE_NOMINDECL, goto err);
if ((nomd->id = tree_parse_ident(p, T(nomd))) == NULL)
if ((id = tree_parse_ident(p, T(nomd))) == NULL)
goto err;
/* name tpexpr to match tree shape of tpdef. This is not represented in
* msph language grammar. */
if ((name = malloc(sizeof(*name))) == NULL) {
MSPH_ERR(CTX(p), MSPH_ERR_SYS);
goto err;
}
T(name)->type = MSPH_TREE_NAME;
T(name)->parent = T(nomd);
TXT(name)->pos = TXT(nomd->id)->pos;
TP_DECOR_INIT(&name->htpe.dec);
name->id = id;
nomd->id = id;
nomd->tp = (struct msph_tree_tpexpr *)name;
return ((struct msph_tree_dir *)nomd);
err:
free_the_tree(T(nomd));

View file

@ -4,37 +4,74 @@
#include "spho/bind.h"
struct spho_bind *
spho_bind_create(struct spho_ctx *ctx, struct spho_bind *parent)
spho_bind_create(struct spho_ctx *ctx, struct spho_bind_scope *binder,
struct spho_bind *parent)
{
struct spho_bind *bind;
SPHO_PRECOND(ctx != NULL);
SPHO_PRECOND(binder != NULL);
if ((bind = malloc(sizeof(*bind))) == NULL) {
SPHO_ERR(ctx, SPHO_ERR_SYS);
SPHO_ERR(binder->sc->ctx, SPHO_ERR_SYS);
return (NULL);
}
STAILQ_INIT(&bind->head);
bind->ctx = ctx;
bind->binder = binder;
bind->parent = parent;
return (bind);
}
int
spho_bind_add(struct spho_bind *bind, struct spho_nom *nom, struct spho_tp *tp)
spho_bind_lkp(int, struct spho_bind *bind, struct spho_nom *nom,
union spho_bound **out)
{
struct spho_binding *b;
if ((b = malloc(sizeof(*b))) == NULL) {
SPHO_ERR(bind->ctx, SPHO_ERR_SYS);
return (-1);
}
b->nom = nom;
b->tp = tp;
STAILQ_INSERT_TAIL(&bind->head, b, entries);
return (0);
// TODO
return (-1);
}
void
spho_bind_destroy(struct spho_bind *bind)
{
free(bind);
}
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);
}
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);
}
int
spho_binder_add_tp(struct spho_bind_scope *bdr, struct spho_nom *nom,
struct spho_tp *tp)
{
}

View file

@ -3,14 +3,16 @@
#include <stdlib.h>
#include <string.h>
#include "spho/spho.h"
#include "spho/ctx.h"
#include "spho/scope.h"
#include "spho/util.h"
#include "spho/bind.h"
static void spho_nom_term(struct spho_nom *);
static int spho_scope_nom_get_norec(struct spho_scope *, const char *, size_t ,
struct spho_nom **);
static int scope_nom_lookup_str_loc(struct spho_scope *, const char *,
size_t, struct spho_nom **);
static int scope_nom_in_loc(struct spho_scope *, struct spho_nom *);
int
spho_scope_init(struct spho_scope *sc, struct spho_ctx *ctx,
@ -23,7 +25,7 @@ spho_scope_init(struct spho_scope *sc, struct spho_ctx *ctx,
SLIST_INIT(&sc->noms);
TAILQ_INIT(&sc->tps);
sc->bind = NULL;
sc->stat_bind = NULL;
return (0);
}
@ -36,6 +38,10 @@ spho_scope_term(struct spho_scope *sc)
SPHO_UTIL_SLIST_DESTROY(&sc->noms, spho_nom, next, spho_nom_term);
sc->parent = NULL;
if (sc->stat_bind == NULL)
spho_bind_scope_destroy(sc->stat_bind);
sc->stat_bind = NULL;
}
struct spho_scope *
@ -69,7 +75,7 @@ spho_scope_create(struct spho_scope *sc)
static void
spho_nom_term(struct spho_nom *nom)
spho_nom_term(__attribute__((unused)) struct spho_nom *nom)
{
return;
}
@ -98,7 +104,7 @@ spho_scope_nom_add(struct spho_scope *sc, const char *nomstr, size_t sz)
nom = NULL;
if (spho_scope_nom_get_norec(sc, nomstr, sz, &nom) == -1)
if (scope_nom_lookup_str_loc(sc, nomstr, sz, &nom) == -1)
return (NULL);
if (nom != NULL) {
@ -139,7 +145,7 @@ err:
int
spho_scope_nom_get(struct spho_scope *sc, const char *nomstr, size_t sz,
spho_scope_nom_lookup_str(struct spho_scope *sc, const char *nomstr, size_t sz,
struct spho_nom **out)
{
struct spho_nom *nom;
@ -166,12 +172,10 @@ spho_scope_nom_get(struct spho_scope *sc, const char *nomstr, size_t sz,
}
int
spho_scope_nom_lookup(struct spho_scope *sc, const char *nomstr, size_t sz,
struct spho_nom **out)
spho_scope_nom_lookup_str_strict(struct spho_scope *sc, const char *nomstr,
size_t sz, struct spho_nom **out)
{
int ret;
if (spho_scope_nom_get(sc, nomstr, sz, out) == -1)
if (spho_scope_nom_lookup_str(sc, nomstr, sz, out) == -1)
return (-1);
if (*out == NULL) {
@ -181,9 +185,33 @@ spho_scope_nom_lookup(struct spho_scope *sc, const char *nomstr, size_t sz,
return (0);
}
int
spho_scope_static_bind_init(struct spho_scope *sc)
{
if ((sc->stat_bind = spho_bind_scope_create(sc))
== NULL) {
return (-1);
}
return (0);
}
int
spho_scope_static_bind_add_tp(struct spho_scope *sc, struct spho_nom *nom,
struct spho_tp *tp)
{
if (! scope_nom_in_loc(sc, nom)) {
SPHO_ERR(sc->ctx, SPHO_ERR_NOM_NOTINSCOPE);
return (-1);
}
return (spho_bind_scope_add_tp(sc->stat_bind, nom, tp));
}
static int
spho_scope_nom_get_norec(struct spho_scope *sc, const char *nomstr, size_t sz,
struct spho_nom **out)
scope_nom_lookup_str_loc(struct spho_scope *sc, const char *nomstr,
size_t sz, struct spho_nom **out)
{
struct spho_nom *nom;
@ -204,3 +232,16 @@ spho_scope_nom_get_norec(struct spho_scope *sc, const char *nomstr, size_t sz,
return (0);
}
static int
scope_nom_in_loc(struct spho_scope *sc, struct spho_nom *nom)
{
struct spho_nom *sc_nom;
SLIST_FOREACH(sc_nom, &sc->noms, next) {
if (sc_nom == nom)
return (1);
}
return (0);
}

View file

@ -128,8 +128,8 @@ spho_tp_create_forall(struct spho_scope *sc, struct spho_nom *nom,
return (NULL);
ret->kind = SPHO_TP_FORM_FORALL;
ret->d.bind.nom = nom;
ret->d.bind.bound = tp;
ret->d.fa.nom = nom;
ret->d.fa.tp = tp;
return (ret);
}
@ -202,12 +202,28 @@ spho_tp_create_member(struct spho_scope *sc, struct spho_nom *nom,
return (NULL);
ret->kind = SPHO_TP_FORM_MEMBER;
ret->d.bind.nom = nom;
ret->d.bind.bound = tp;
ret->d.memb.nom = nom;
ret->d.memb.tp = tp;
return (ret);
}
struct spho_tp *
spho_tp_create_nominal(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_NOMINAL;
ret->d.nom.nom = nom;
return (ret);
}
/* Free type structure. External data (like nom) are freed elsewhere. */
void
spho_tp_destroy(struct spho_tp *tp)
@ -230,8 +246,10 @@ spho_tp_destroy(struct spho_tp *tp)
spho_tp_destroy(tp->d.unop.operand);
break;
case SPHO_TP_FORM_FORALL:
spho_tp_destroy(tp->d.fa.tp);
break;
case SPHO_TP_FORM_MEMBER:
spho_tp_destroy(tp->d.bind.bound);
spho_tp_destroy(tp->d.memb.tp);
break;
case SPHO_TP_FORM_APPL:
STAILQ_FOREACH(arg, tp->d.appl.args, entries) {