broken code, but added attempt at writing grammar
This commit is contained in:
parent
fb95e5d026
commit
20e3757f44
18 changed files with 1145 additions and 142 deletions
93
src/msph/README.md
Normal file
93
src/msph/README.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
# msph/micro sappho
|
||||
|
||||
Micro sappho is a minimalistic language for demonstration of the SPHO type
|
||||
system. It is implemented using a simple parser and lexer that implements the
|
||||
grammar below. The indended use is to allow experimentation and familiarization
|
||||
with the SPHO types and subtyping.
|
||||
|
||||
## Grammar
|
||||
|
||||
Grammar in pseudo-bnf
|
||||
|
||||
```
|
||||
|
||||
MSph ::= Body
|
||||
|
||||
Body ::= Dirs
|
||||
|
||||
Dir ::= Typedef (directives, with lack of a better name)
|
||||
| Memberdef
|
||||
| Nominaldecl
|
||||
| Checkdir
|
||||
|
||||
Typedef ::= 'type' Name '=' TExpr (type definition/binding)
|
||||
| 'type' Name '[' Names ']' '=' TExpr
|
||||
| 'type' Name (declaration, donno if useful)
|
||||
|
||||
Memberdef ::= 'member' Name ':' TExpr
|
||||
|
||||
Nominaldecl ::= 'nominal' Name
|
||||
|
||||
Checkdir ::= 'check' TExpr '<:' TExpr
|
||||
|
||||
TExpr ::= 'True'
|
||||
| 'False'
|
||||
| Var
|
||||
| Nominal
|
||||
| Trait
|
||||
| TExpr '&' TExpr
|
||||
| TExpr '|' TExpr
|
||||
| TExpr '=>' TExpr
|
||||
| TExpr '->' TExpr
|
||||
| 'box' TExpr
|
||||
| 'forall' Name '.' TExpr
|
||||
| '(' TExpr ')'
|
||||
|
||||
Trait ::= '{' Body '}' (trait, this introduces scoping)
|
||||
|
||||
Var ::= Name (type variables)
|
||||
Nominal ::= Name (nominal type)
|
||||
|
||||
Name ::= '[a-zA-Z0-9_]+' & !Reserved (name/identifier)
|
||||
|
||||
Reserved ::= 'type' (reserved/keywords)
|
||||
| 'member'
|
||||
| 'nominal'
|
||||
| 'check'
|
||||
| 'forall'
|
||||
| 'box'
|
||||
| 'True'
|
||||
| 'False'
|
||||
```
|
||||
|
||||
Precedence of binary operators:
|
||||
'&' <
|
||||
'|' <
|
||||
'->' <
|
||||
'=>'
|
||||
|
||||
< means "binds closer"
|
||||
|
||||
## Example
|
||||
|
||||
A simple example msph program
|
||||
|
||||
```
|
||||
|
||||
nominal ExampleN
|
||||
|
||||
type ExampleDecl
|
||||
type ExampleDecl2
|
||||
|
||||
type Example = {
|
||||
member example_m : C -> C
|
||||
type FA = forall X. X -> X
|
||||
|
||||
type b = forall X. (box X => ExampleDecl) => ExampleDecl2
|
||||
}
|
||||
|
||||
member example_global : Example & ExampleN
|
||||
|
||||
type TripleConj[X, Y, Z] = X & Y & Z
|
||||
|
||||
```
|
40
src/msph/msph.c
Normal file
40
src/msph/msph.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <stdio.h>
|
||||
|
||||
|
||||
|
||||
#include "msph_token.h"
|
||||
|
||||
#define PRINTERR(ctx) \
|
||||
do { \
|
||||
fprintf(stderr, "msph_err: %d (%d)\n", (ctx).err, (ctx).err_info); \
|
||||
} while (0)
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
char *path;
|
||||
struct msph_ctx ctx;
|
||||
struct msph_token_stream *s;
|
||||
|
||||
|
||||
if (argc != 2)
|
||||
return (-1);
|
||||
|
||||
|
||||
path = argv[1];
|
||||
|
||||
ctx.err = 0;
|
||||
ctx.err_info = 0;
|
||||
|
||||
if ((s = msph_token_stream_fopen(&ctx, path)) == NULL) {
|
||||
PRINTERR(ctx);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
ret = msph_token_stream_close(s);
|
||||
|
||||
return (ret);
|
||||
}
|
247
src/msph/msph_token.c
Normal file
247
src/msph/msph_token.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
#include <sys/errno.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "spho/err.h"
|
||||
|
||||
|
||||
|
||||
#define MSPH_ERR_SYS 0x0001
|
||||
#define MSPH_ERR_TOOLONG 0x0002
|
||||
|
||||
#define MSPH_ERR(ctx, e) SPHO_ERR(ctx, e)
|
||||
#define MSPH_TOKS_ERR(toks, e) MSPH_ERR((toks)->ctx, e)
|
||||
|
||||
struct msph_token_stream *
|
||||
msph_token_stream_fopen(struct msph_ctx *ctx, const char *path)
|
||||
{
|
||||
FILE *f;
|
||||
size_t res;
|
||||
struct msph_token_stream *ret;
|
||||
|
||||
if ((f = fopen(path, "r")) == NULL) {
|
||||
MSPH_ERR(ctx, MSPH_ERR_SYS);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((ret = calloc(1, sizeof(struct msph_token_stream))) == NULL) {
|
||||
MSPH_ERR(ctx, MSPH_ERR_SYS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret->ctx = ctx;
|
||||
ret->src.type = MSPH_TOKEN_SRC_FILE;
|
||||
ret->src.inner.file.f = f;
|
||||
ret->src.inner.file.eof = 0;
|
||||
ret->src.inner.file.pos = ret->src.file.buf;
|
||||
ret->src.inner.file.end = ret->src.file.buf;
|
||||
ret->src.inner.file.read_ptr = ret->src.file.buf;
|
||||
|
||||
res = strlcpy(ret->src.file.name, path, sizeof(ret->src.file.name));
|
||||
if (res >= sizeof(ret->src.file.name)) {
|
||||
MSPH_ERR(ctx, MSPH_ERR_TOOLONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
err:
|
||||
if (fclose(f) == EOF)
|
||||
abort();
|
||||
|
||||
if (ret != NULL)
|
||||
free(ret);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct msph_token_stream *
|
||||
msph_token_stream_frombuf(struct msph_ctx *ctx, const char *buf, size_t len)
|
||||
{
|
||||
struct msph_token_stream *ret;
|
||||
|
||||
if ((ret = calloc(1, sizeof(struct msph_token_stream))) == NULL) {
|
||||
MSPH_ERR(ctx, MSPH_ERR_SYS);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ret->ctx = ctx;
|
||||
ret->type = MSPH_TOKEN_SRC_STR;
|
||||
ret->src.str.s = buf;
|
||||
ret->src.str.len = len;
|
||||
ret->src.str.pos = 0;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
msph_token_stream_close(struct msph_token_stream *s)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = -1;
|
||||
|
||||
switch (s->type) {
|
||||
case MSPH_TOKEN_SRC_FILE:
|
||||
ret = fclose(s->src.file.f);
|
||||
break;
|
||||
case MSPH_TOKEN_SRC_STR:
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
/* -1 or num tokens read */
|
||||
ssize_t
|
||||
msph_token_stream_read_tok(struct msph_token *ptr, size_t n,
|
||||
struct msph_token_stream *s)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t i;
|
||||
int res;
|
||||
|
||||
ret = 0;
|
||||
res = -1;
|
||||
while ((res = read_single_tok(&ptr[i], s)) == 1) {
|
||||
if (res == -1) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
ret++;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
struct msph_token_matcher {
|
||||
size_t pos_off;
|
||||
size_t matchlen;
|
||||
|
||||
const int tok_type;
|
||||
} msph_matcher[] = {
|
||||
{ 0, 0, TOK_START },
|
||||
{ 0, 0, TOK_IDENT },
|
||||
{ 0, 0, TOK_END }
|
||||
};
|
||||
|
||||
#define BUF_LEN(b) (sizeof(b) / sizeof(b[0]))
|
||||
static int
|
||||
file_char_at(struct msph_ctx *ctx, struct msph_token_src *src, size_t i,
|
||||
char *out)
|
||||
{
|
||||
size_t nread;
|
||||
size_t maxread;
|
||||
struct msph_token_src_file *file;
|
||||
|
||||
ret = -1;
|
||||
file = &src->inner.file;
|
||||
|
||||
if (file->pos + i < file->end) {
|
||||
*out = file->buf[file->pos + i];
|
||||
return (0);
|
||||
}
|
||||
if (file->end < file->pos &&
|
||||
((file->pos + i) % BUF_LEN(file->buf)) < file->end) {
|
||||
*out = file->buf[(file->pos + i) % BUF_LEN(file->buf)];
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (file->eof) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (file->end < file->pos)
|
||||
maxread = file->pos - file->end;
|
||||
else
|
||||
maxread = BUF_LEN(file->buf) - file->end;
|
||||
|
||||
maxread = file->end < file->pos ? file->pos - file->end :
|
||||
BUF_LEN(file->buf) - file->end;
|
||||
|
||||
if (maxread == 0) {
|
||||
MSPH_ERR(ctx, MSPH_ERR_TOOLONG);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ret = fread(&file->buf[file->end], sizeof(file->buf[0]), maxread,
|
||||
file->f);
|
||||
|
||||
if (ret == 0) {
|
||||
if (ferror(file->f)) {
|
||||
MSPH_ERR(ctx, MSPH_ERR_SYS);
|
||||
return (-1);
|
||||
}
|
||||
file->eof = 1;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
char_at(struct msph_token_src *src, size_t i, char *out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (src->type) {
|
||||
case MSPH_TOKEN_SRC_FILE:
|
||||
ret = file_char_at(s, i, out);
|
||||
break;
|
||||
case MSPH_TOKEN_SRC_STR:
|
||||
ret = str_char_at(s, i, out);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
tok_match(struct msph_token_matcher *m, struct msph_token_stream *s)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
tok_commit(struct msph_token *ptr, struct msph_token_stream *s,
|
||||
struct msph_matcher *m)
|
||||
{
|
||||
SPHO_PRECOND(p != NULL && m != NULL);
|
||||
SPHO_PRECOND(m->matchlen != 0);
|
||||
|
||||
}
|
||||
|
||||
/* 1: success, 0: failed match, -1: error */
|
||||
static int
|
||||
read_single_tok(struct msph_token *ptr, struct msph_token_stream *s)
|
||||
{
|
||||
int res;
|
||||
size_t m;
|
||||
size_t max_m;
|
||||
|
||||
max_m = 0;
|
||||
for (m = 0; msph_matcher[m].type != TOK_END; m++) {
|
||||
res = tok_match(&msph_matcher[m], s);
|
||||
|
||||
if (res == -1)
|
||||
return (-1);
|
||||
|
||||
if (res == 0 &&
|
||||
msph_matcher[m].matchlen > msph_matcher[max_m].matchlen) {
|
||||
max_m = m;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_m == 0)
|
||||
return (0);
|
||||
|
||||
tok_commit(ptr, &msph_matcher[max_m]);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
179
src/msph/msph_token.h
Normal file
179
src/msph/msph_token.h
Normal file
|
@ -0,0 +1,179 @@
|
|||
#ifndef _MSPH_EXPR_H
|
||||
#define _MSPH_EXPR_H
|
||||
|
||||
/*
|
||||
* TYPES:
|
||||
* Conj
|
||||
* Disj
|
||||
* Impl
|
||||
* Arrow
|
||||
* Box
|
||||
* (Sub)
|
||||
* Forall
|
||||
*
|
||||
* True
|
||||
* False
|
||||
* Var
|
||||
* Nominal
|
||||
*
|
||||
* Record
|
||||
*
|
||||
* DEFINITIONS/DIRECTIVES:
|
||||
* Type definition (type A[X..] = T)
|
||||
* Nominal definition (nominal N)
|
||||
* Member definition (member mname : T)
|
||||
*
|
||||
* {
|
||||
* member a: A
|
||||
* member b: B
|
||||
* }
|
||||
*
|
||||
* Subtyping check (check A <: B, checks if A <: B)
|
||||
*
|
||||
* EXTRA DEFINITIONS
|
||||
* Class definition (class C[...] { ... }, shorthand)
|
||||
*
|
||||
* EXPRESSIONS
|
||||
* Conj
|
||||
* Disj
|
||||
* Impl
|
||||
* Arrow
|
||||
* Box
|
||||
* (Sub)
|
||||
* Forall
|
||||
*
|
||||
* True
|
||||
* False
|
||||
* Var
|
||||
* Nominal
|
||||
*
|
||||
* Trait ({ ... }, creates scoping)
|
||||
*
|
||||
*
|
||||
* TOKENS
|
||||
* lbrace {
|
||||
* rbrace }
|
||||
* lbrak [
|
||||
* rbrak ]
|
||||
* lparen (
|
||||
* rparen )
|
||||
* colon :
|
||||
* equals =
|
||||
*
|
||||
* op_and &
|
||||
* op_or |
|
||||
* op_impl =>
|
||||
* op_sub <:
|
||||
*
|
||||
* kw_type type
|
||||
* kw_nominal nominal
|
||||
* kw_member member
|
||||
* kw_check check
|
||||
* kw_box box
|
||||
* kw_forall forall
|
||||
*
|
||||
* k_true True
|
||||
* k_false False
|
||||
*
|
||||
* ident C, anid, ...
|
||||
*
|
||||
*/
|
||||
|
||||
struct msph_ctx {
|
||||
int err;
|
||||
int err_info;
|
||||
};
|
||||
|
||||
enum msph_tok_type {
|
||||
TOK_START,
|
||||
TOK_LBRACE, // {
|
||||
TOK_RBRACE, // }
|
||||
TOK_LBRAK, // [
|
||||
TOK_RBRAK, // ]
|
||||
TOK_LPAREN, // (
|
||||
TOK_RPAREN, // )
|
||||
TOK_OP_COLON, // :
|
||||
TOK_OP_EQUALS, // =
|
||||
|
||||
TOK_OP_AMP, // &
|
||||
TOK_OP_PIPE, // |
|
||||
TOK_OP_RARROW, // =>
|
||||
TOK_OP_SUB, // <:
|
||||
|
||||
TOK_KW_TYPE, // type
|
||||
TOK_KW_NOMINAL, // nominal
|
||||
TOK_KW_MEMBER, // member
|
||||
TOK_KW_CHECK, // check
|
||||
TOK_KW_BOX, // box
|
||||
TOK_KW_FORALL, // forall
|
||||
|
||||
TOK_CONST_TRUE, // True
|
||||
TOK_CONST_FALSE, // False
|
||||
|
||||
TOK_IDENT, // identifiers
|
||||
TOK_END
|
||||
};
|
||||
|
||||
#define MSPH_TOKEN_BUF_SZ 128
|
||||
|
||||
struct token_s {
|
||||
char buf[MSPH_TOKEN_BUF_SZ];
|
||||
};
|
||||
|
||||
union token_data {
|
||||
struct token_s s;
|
||||
};
|
||||
|
||||
struct msph_token {
|
||||
int type;
|
||||
union token_data d;
|
||||
};
|
||||
|
||||
#define MSPH_PATH_LEN 1024
|
||||
#define MSPH_FILE_BUF_LEN 4096
|
||||
#define MSPH_TOKEN_SRC_FILE 1
|
||||
|
||||
struct msph_token_src_file {
|
||||
FILE *f;
|
||||
int eof;
|
||||
size_t pos; // TODO rename bufpos
|
||||
size_t end; // TODO rename bufend
|
||||
size_t read_pos;
|
||||
char buf[MSPH_FILE_BUF_LEN];
|
||||
|
||||
char name[MSPH_PATH_LEN];
|
||||
};
|
||||
|
||||
#define MSPH_TOKEN_SRC_STR 2
|
||||
struct msph_token_src_str {
|
||||
const char *s;
|
||||
size_t len;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
union msph_token_src_data {
|
||||
struct msph_token_src_file file;
|
||||
struct msph_token_src_str str;
|
||||
};
|
||||
|
||||
struct msph_token_src {
|
||||
int type
|
||||
union msph_token_src_data inner;
|
||||
};
|
||||
|
||||
struct msph_token_stream {
|
||||
struct msph_ctx *ctx;
|
||||
|
||||
struct msph_token_src src;
|
||||
};
|
||||
|
||||
struct msph_token_stream *msph_token_stream_fopen(struct msph_ctx *,
|
||||
const char *);
|
||||
struct msph_token_stream *msph_token_stream_frombuf(struct msph_ctx *,
|
||||
const char *, size_t);
|
||||
|
||||
int msph_token_stream_close(struct msph_token_stream*);
|
||||
|
||||
struct msph_token *msph_token_source_pop(struct msph_token_stream *);
|
||||
|
||||
#endif /* _MSPH_EXPR_H */
|
|
@ -11,7 +11,7 @@ int main(void)
|
|||
|
||||
if ((ctx = spho_ctx_create()) == NULL)
|
||||
return (-1);
|
||||
|
||||
|
||||
spho_ctx_destroy(ctx);
|
||||
|
||||
return (0);
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "spho/err.h"
|
||||
#include "spho/ctx.h"
|
||||
|
||||
static const char *spho_ctx_sys_strerror(struct spho_ctx *);
|
||||
|
@ -16,8 +15,11 @@ struct spho_err {
|
|||
};
|
||||
|
||||
struct spho_err spho_errmsgs[] = {
|
||||
{ SPHO_ERR_SYSTEM, "spho system error" },
|
||||
{ SPHO_ERR_INTERNAL, "spho internal error" },
|
||||
{ SPHO_ERR_SYS, "spho system error" },
|
||||
{ SPHO_ERR_INTERNAL, "spho internal error" },
|
||||
{ SPHO_ERR_TOOBIG, "parameter size too big" },
|
||||
{ SPHO_ERR_ARGINVAL, "invalid argument" },
|
||||
{ SPHO_ERR_NAMEINUSE, "name in use" },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
|
@ -26,14 +28,20 @@ spho_ctx_create(void)
|
|||
{
|
||||
struct spho_ctx *c;
|
||||
|
||||
c = NULL;
|
||||
|
||||
if ((c = malloc(sizeof(struct spho_ctx))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
c->err = 0;
|
||||
c->err_info = 0;
|
||||
|
||||
SLIST_INIT(&c->noms);
|
||||
SLIST_INIT(&c->cnsts);
|
||||
if (spho_scope_init(&c->glob, c, NULL) == -1) {
|
||||
free(c);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
SPHO_POSTCOND(c != NULL);
|
||||
|
||||
return (c);
|
||||
}
|
||||
|
@ -41,22 +49,11 @@ spho_ctx_create(void)
|
|||
void
|
||||
spho_ctx_destroy(struct spho_ctx *ctx)
|
||||
{
|
||||
struct spho_nom_le *nom;
|
||||
struct spho_cnst_le *cnst;
|
||||
|
||||
SPHO_PRECOND(ctx != NULL);
|
||||
|
||||
while (! SLIST_EMPTY(&ctx->noms)) {
|
||||
nom = SLIST_FIRST(&ctx->noms);
|
||||
SLIST_REMOVE_HEAD(&ctx->noms, next);
|
||||
free(nom);
|
||||
}
|
||||
spho_scope_term(&ctx->glob);
|
||||
|
||||
while (! SLIST_EMPTY(&ctx->cnsts)) {
|
||||
cnst = SLIST_FIRST(&ctx->cnsts);
|
||||
SLIST_REMOVE_HEAD(&ctx->cnsts, next);
|
||||
free(cnst);
|
||||
}
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
|
||||
|
|
156
src/spho/scope.c
Normal file
156
src/spho/scope.c
Normal file
|
@ -0,0 +1,156 @@
|
|||
#include <sys/queue.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "spho/ctx.h"
|
||||
#include "spho/scope.h"
|
||||
#include "spho/util.h"
|
||||
|
||||
static void spho_nom_term(struct spho_nom *);
|
||||
|
||||
int
|
||||
spho_scope_init(struct spho_scope *sc, struct spho_ctx *ctx,
|
||||
struct spho_scope *p)
|
||||
{
|
||||
SLIST_INIT(&sc->subs);
|
||||
SLIST_INIT(&sc->noms);
|
||||
|
||||
sc->parent = p;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
spho_scope_term(struct spho_scope *sc)
|
||||
{
|
||||
SPHO_UTIL_SLIST_DESTROY(&sc->subs, spho_scope, next, spho_scope_term);
|
||||
|
||||
SPHO_UTIL_SLIST_DESTROY(&sc->noms, spho_nom, next, spho_nom_term);
|
||||
|
||||
sc->parent = NULL;
|
||||
}
|
||||
|
||||
struct spho_scope *
|
||||
spho_scope_global(struct spho_ctx *ctx)
|
||||
{
|
||||
SPHO_PRECOND(ctx != NULL);
|
||||
|
||||
return (&ctx->glob);
|
||||
}
|
||||
|
||||
|
||||
struct spho_scope *
|
||||
spho_scope_create(struct spho_scope *sc)
|
||||
{
|
||||
struct spho_scope *sub;
|
||||
|
||||
if ((sub = malloc(sizeof(struct spho_scope))) == NULL) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_SYS);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (spho_scope_init(sub, sc->ctx, sc) == -1) {
|
||||
free(sub);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
SLIST_INSERT_HEAD(&sc->subs, sub, next);
|
||||
|
||||
return (sub);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
spho_nom_term(struct spho_nom *nom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
spho_scope_destroy(struct spho_scope *sc)
|
||||
{
|
||||
struct spho_scope *sub;
|
||||
struct spho_scope *p;
|
||||
|
||||
p = sc->parent;
|
||||
SLIST_REMOVE(&p->subs, sc, spho_scope, next);
|
||||
spho_scope_term(sc);
|
||||
free(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;
|
||||
|
||||
|
||||
if (spho_scope_nom_get(sc, nomstr, sz, &nom) == -1)
|
||||
return (NULL);
|
||||
|
||||
if (nom != NULL) {
|
||||
SPHO_SC_ERR(sc, SPHO_ERR_NAMEINUSE);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((nom = malloc(sizeof(struct spho_nom))) == NULL) {
|
||||
SPHO_SC_ERR(sc, SPHO_ERR_SYS);
|
||||
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);
|
||||
|
||||
return (nom);
|
||||
err:
|
||||
free(nom);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
spho_scope_nom_get(struct spho_scope *sc, const char *nomstr, size_t sz,
|
||||
struct spho_nom **out)
|
||||
{
|
||||
struct spho_nom *nom;
|
||||
|
||||
nom = NULL;
|
||||
|
||||
if (sz > sizeof(nom->s)) {
|
||||
SPHO_ERR(sc->ctx, SPHO_ERR_TOOBIG);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
out = NULL;
|
||||
SLIST_FOREACH(nom, &sc->noms, next) {
|
||||
if (strncmp(nom->s, nomstr, sz) == 0) {
|
||||
*out = nom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
185
src/spho/tp.c
185
src/spho/tp.c
|
@ -1,9 +1,11 @@
|
|||
#include <sys/queue.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "spho/ctx.h"
|
||||
#include "spho/scope.h"
|
||||
#include "spho/tp.h"
|
||||
|
||||
struct spho_nom *
|
||||
spho_nom_add(struct spho_ctx *ctx, char *nom, size_t nomlen)
|
||||
{
|
||||
}
|
||||
|
||||
//struct spho_tp *
|
||||
//spho_tp_create_disj(struct spho_ctx *, struct spho_tp *, struct spho_tp *,
|
||||
|
@ -11,3 +13,178 @@ spho_nom_add(struct spho_ctx *ctx, char *nom, size_t nomlen)
|
|||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
struct spho_tp *
|
||||
spho_tp_alloc(struct spho_scope *sc, int form)
|
||||
{
|
||||
struct spho_tp *tp;
|
||||
|
||||
SPHO_PRECOND(SPHO_TP_FORM_IS_VALID(form));
|
||||
|
||||
if ((tp = calloc(1, sizeof(struct spho_tp))) == NULL) {
|
||||
SPHO_SC_ERR(sc, SPHO_ERR_SYS);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
tp->sc = sc;
|
||||
tp->form = form;
|
||||
|
||||
return (tp);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
spho_tp_init_disj(struct spho_tp *tp, struct spho_tp *a, struct spho_tp *b)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_DISJ) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.binop.left = a;
|
||||
tp->data.binop.right = b;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_conj(struct spho_tp *tp, struct spho_tp *a, struct spho_tp *b)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_CONJ) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.binop.left = a;
|
||||
tp->data.binop.right = b;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_impl(struct spho_tp *tp, struct spho_tp *a, struct spho_tp *b)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_IMPL) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.binop.left = a;
|
||||
tp->data.binop.right = b;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_arrow(struct spho_tp *tp, struct spho_tp *a, struct spho_tp *b)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_ARROW) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.binop.left = a;
|
||||
tp->data.binop.right = b;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_box(struct spho_tp *tp, struct spho_tp *inr)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_BOX) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.box.inr = inr;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_forall(struct spho_tp *tp, struct spho_var *var,
|
||||
struct spho_tp *inr)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_FORALL) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.fa.var = var;
|
||||
tp->data.fa.inr = inr;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_bappl(struct spho_tp *tp, struct spho_bind *bind,
|
||||
struct spho_tp_l *args)
|
||||
{
|
||||
struct spho_tp *arg;
|
||||
|
||||
if (tp->form != SPHO_TP_FORM_BAPPL) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.bappl.bind = bind;
|
||||
tp->data.bappl.args = args;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_false(struct spho_tp *tp)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_FALSE) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.konst.k = SPHO_K_FALSE;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_true(struct spho_tp *tp)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_TRUE) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.konst.k = SPHO_K_TRUE;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_var(struct spho_tp *tp, struct spho_var *var)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_VAR) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.var.v = var;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
spho_tp_init_rec(struct spho_tp *tp, struct spho_rec *rec)
|
||||
{
|
||||
if (tp->form != SPHO_TP_FORM_REC) {
|
||||
SPHO_TP_ERR(tp, SPHO_ERR_ARGINVAL);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tp->data.rec.r = rec;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue