1
0
forked from GitHub/gf-core

change the API to allow different grammar revisions

This commit is contained in:
krangelov
2021-09-06 15:49:39 +02:00
parent b7cddf206b
commit 9cea2cc70e
14 changed files with 298 additions and 226 deletions

View File

@@ -107,26 +107,12 @@ typedef struct {
Namespace<PgfAbsCat> cats; Namespace<PgfAbsCat> cats;
} PgfAbstr; } PgfAbstr;
struct PGF_INTERNAL_DECL PgfPGFRoot { typedef struct PGF_INTERNAL_DECL {
uint16_t major_version; uint16_t major_version;
uint16_t minor_version; uint16_t minor_version;
Namespace<PgfFlag> gflags; Namespace<PgfFlag> gflags;
PgfAbstr abstract; PgfAbstr abstract;
//PgfConcrs* concretes; //PgfConcrs* concretes;
}; } PgfPGF;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wattributes"
struct PgfPGF : DB {
PGF_INTERNAL_DECL PgfPGF(const char* fpath, int flags, int mode)
: DB(fpath, flags, mode)
{ };
PGF_INTERNAL_DECL ~PgfPGF()
{ };
};
#pragma GCC diagnostic pop
#endif #endif

View File

@@ -7,7 +7,7 @@
#include "data.h" #include "data.h"
PGF_INTERNAL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))) = NULL; PGF_INTERNAL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))) = NULL;
PGF_INTERNAL __thread DB* current_db __attribute__((tls_model("initial-exec"))) = NULL; PGF_INTERNAL __thread PgfDB* current_db __attribute__((tls_model("initial-exec"))) = NULL;
PGF_INTERNAL __thread DB_scope *last_db_scope __attribute__((tls_model("initial-exec"))) = NULL; PGF_INTERNAL __thread DB_scope *last_db_scope __attribute__((tls_model("initial-exec"))) = NULL;
#ifndef DEFAULT_TOP_PAD #ifndef DEFAULT_TOP_PAD
@@ -269,7 +269,7 @@ struct malloc_state
object root_offset; object root_offset;
}; };
DB::DB(const char* pathname, int flags, int mode) { PgfDB::PgfDB(const char* pathname, int flags, int mode) {
size_t file_size; size_t file_size;
bool is_new = false; bool is_new = false;
@@ -313,7 +313,7 @@ DB::DB(const char* pathname, int flags, int mode) {
} }
} }
DB::~DB() { PgfDB::~PgfDB() {
if (ms != NULL) { if (ms != NULL) {
size_t size = size_t size =
ms->top + chunksize(ptr(ms,ms->top)) + sizeof(size_t); ms->top + chunksize(ptr(ms,ms->top)) + sizeof(size_t);
@@ -327,7 +327,7 @@ DB::~DB() {
pthread_rwlock_destroy(&rwlock); pthread_rwlock_destroy(&rwlock);
} }
void DB::sync() void PgfDB::sync()
{ {
malloc_state *ms = current_db->ms; malloc_state *ms = current_db->ms;
size_t size = size_t size =
@@ -338,16 +338,16 @@ void DB::sync()
throw std::system_error(errno, std::generic_category()); throw std::system_error(errno, std::generic_category());
} }
object DB::get_root_internal() { object PgfDB::get_root_internal() {
return ms->root_offset; return ms->root_offset;
} }
void DB::set_root_internal(object root_offset) { void PgfDB::set_root_internal(object root_offset) {
ms->root_offset = root_offset; ms->root_offset = root_offset;
} }
void void
DB::init_state(size_t size) PgfDB::init_state(size_t size)
{ {
/* Init fastbins */ /* Init fastbins */
ms->have_fastchunks = false; ms->have_fastchunks = false;
@@ -483,7 +483,7 @@ static void malloc_consolidate(malloc_state *ms)
} }
object object
DB::malloc_internal(size_t bytes) PgfDB::malloc_internal(size_t bytes)
{ {
unsigned int idx; /* associated bin index */ unsigned int idx; /* associated bin index */
mbin* bin; /* associated bin */ mbin* bin; /* associated bin */
@@ -856,7 +856,7 @@ DB::malloc_internal(size_t bytes)
} }
void void
DB::free_internal(object o) PgfDB::free_internal(object o)
{ {
size_t size; /* its size */ size_t size; /* its size */
object *fb; /* associated fastbin */ object *fb; /* associated fastbin */
@@ -948,7 +948,7 @@ DB::free_internal(object o)
} }
DB_scope::DB_scope(DB *db, DB_scope_mode tp) DB_scope::DB_scope(PgfDB *db, DB_scope_mode tp)
{ {
int res = int res =
(tp == READER_SCOPE) ? pthread_rwlock_rdlock(&db->rwlock) (tp == READER_SCOPE) ? pthread_rwlock_rdlock(&db->rwlock)

View File

@@ -3,10 +3,10 @@
#define MALLOC_ALIGN_MASK (2*sizeof(size_t) - 1) #define MALLOC_ALIGN_MASK (2*sizeof(size_t) - 1)
class DB; class PgfDB;
extern PGF_INTERNAL_DECL __thread unsigned char* current_base __attribute__((tls_model("initial-exec"))); extern PGF_INTERNAL_DECL __thread unsigned char* current_base __attribute__((tls_model("initial-exec")));
extern PGF_INTERNAL_DECL __thread DB* current_db __attribute__((tls_model("initial-exec"))); extern PGF_INTERNAL_DECL __thread PgfDB* current_db __attribute__((tls_model("initial-exec")));
struct malloc_state; struct malloc_state;
@@ -14,7 +14,7 @@ template<class A> class PGF_INTERNAL_DECL ref {
private: private:
object offset; object offset;
friend class DB; friend class PgfDB;
public: public:
ref<A>() { } ref<A>() { }
@@ -54,7 +54,7 @@ public:
} }
}; };
class PGF_INTERNAL_DECL DB { class PgfDB {
private: private:
int fd; int fd;
malloc_state* ms; malloc_state* ms;
@@ -64,8 +64,8 @@ private:
friend class PgfReader; friend class PgfReader;
public: public:
DB(const char* pathname, int flags, int mode); PgfDB(const char* pathname, int flags, int mode);
~DB(); ~PgfDB();
template<class A> template<class A>
static ref<A> malloc() { static ref<A> malloc() {
@@ -112,11 +112,11 @@ enum DB_scope_mode {READER_SCOPE, WRITER_SCOPE};
class PGF_INTERNAL_DECL DB_scope { class PGF_INTERNAL_DECL DB_scope {
public: public:
DB_scope(DB *db, DB_scope_mode type); DB_scope(PgfDB *db, DB_scope_mode type);
~DB_scope(); ~DB_scope();
private: private:
DB* save_db; PgfDB* save_db;
DB_scope* next_scope; DB_scope* next_scope;
}; };

View File

@@ -111,7 +111,7 @@ PgfType PgfDBMarshaller::match_type(PgfUnmarshaller *u, PgfType ty)
PgfExpr PgfDBUnmarshaller::eabs(PgfBindType bind_type, PgfText *name, PgfExpr body) PgfExpr PgfDBUnmarshaller::eabs(PgfBindType bind_type, PgfText *name, PgfExpr body)
{ {
ref<PgfExprAbs> eabs = ref<PgfExprAbs> eabs =
DB::malloc<PgfExprAbs>(sizeof(PgfExprAbs)+name->size+1); PgfDB::malloc<PgfExprAbs>(sizeof(PgfExprAbs)+name->size+1);
eabs->bind_type = bind_type; eabs->bind_type = bind_type;
eabs->body = m->match_expr(this, body); eabs->body = m->match_expr(this, body);
memcpy(&eabs->name, name, sizeof(PgfText)+name->size+1); memcpy(&eabs->name, name, sizeof(PgfText)+name->size+1);
@@ -120,7 +120,7 @@ PgfExpr PgfDBUnmarshaller::eabs(PgfBindType bind_type, PgfText *name, PgfExpr bo
PgfExpr PgfDBUnmarshaller::eapp(PgfExpr fun, PgfExpr arg) PgfExpr PgfDBUnmarshaller::eapp(PgfExpr fun, PgfExpr arg)
{ {
ref<PgfExprApp> eapp = DB::malloc<PgfExprApp>(); ref<PgfExprApp> eapp = PgfDB::malloc<PgfExprApp>();
eapp->fun = m->match_expr(this, fun); eapp->fun = m->match_expr(this, fun);
eapp->arg = m->match_expr(this, arg); eapp->arg = m->match_expr(this, arg);
return ref<PgfExprApp>::tagged(eapp); return ref<PgfExprApp>::tagged(eapp);
@@ -128,14 +128,14 @@ PgfExpr PgfDBUnmarshaller::eapp(PgfExpr fun, PgfExpr arg)
PgfExpr PgfDBUnmarshaller::elit(PgfLiteral lit) PgfExpr PgfDBUnmarshaller::elit(PgfLiteral lit)
{ {
ref<PgfExprLit> elit = DB::malloc<PgfExprLit>(); ref<PgfExprLit> elit = PgfDB::malloc<PgfExprLit>();
elit->lit = m->match_lit(this, lit); elit->lit = m->match_lit(this, lit);
return ref<PgfExprLit>::tagged(elit); return ref<PgfExprLit>::tagged(elit);
} }
PgfExpr PgfDBUnmarshaller::emeta(PgfMetaId meta_id) PgfExpr PgfDBUnmarshaller::emeta(PgfMetaId meta_id)
{ {
ref<PgfExprMeta> emeta = DB::malloc<PgfExprMeta>(); ref<PgfExprMeta> emeta = PgfDB::malloc<PgfExprMeta>();
emeta->id = meta_id; emeta->id = meta_id;
return ref<PgfExprMeta>::tagged(emeta); return ref<PgfExprMeta>::tagged(emeta);
} }
@@ -143,21 +143,21 @@ PgfExpr PgfDBUnmarshaller::emeta(PgfMetaId meta_id)
PgfExpr PgfDBUnmarshaller::efun(PgfText *name) PgfExpr PgfDBUnmarshaller::efun(PgfText *name)
{ {
ref<PgfExprFun> efun = ref<PgfExprFun> efun =
DB::malloc<PgfExprFun>(sizeof(PgfExprFun)+name->size+1); PgfDB::malloc<PgfExprFun>(sizeof(PgfExprFun)+name->size+1);
memcpy(&efun->name, name, sizeof(PgfText)+name->size+1); memcpy(&efun->name, name, sizeof(PgfText)+name->size+1);
return ref<PgfExprFun>::tagged(efun); return ref<PgfExprFun>::tagged(efun);
} }
PgfExpr PgfDBUnmarshaller::evar(int index) PgfExpr PgfDBUnmarshaller::evar(int index)
{ {
ref<PgfExprVar> evar = DB::malloc<PgfExprVar>(); ref<PgfExprVar> evar = PgfDB::malloc<PgfExprVar>();
evar->var = index; evar->var = index;
return ref<PgfExprVar>::tagged(evar); return ref<PgfExprVar>::tagged(evar);
} }
PgfExpr PgfDBUnmarshaller::etyped(PgfExpr expr, PgfType ty) PgfExpr PgfDBUnmarshaller::etyped(PgfExpr expr, PgfType ty)
{ {
ref<PgfExprTyped> etyped = DB::malloc<PgfExprTyped>(); ref<PgfExprTyped> etyped = PgfDB::malloc<PgfExprTyped>();
etyped->expr = m->match_expr(this, expr); etyped->expr = m->match_expr(this, expr);
etyped->type = m->match_type(this, ty); etyped->type = m->match_type(this, ty);
return ref<PgfExprTyped>::tagged(etyped); return ref<PgfExprTyped>::tagged(etyped);
@@ -173,7 +173,7 @@ PgfExpr PgfDBUnmarshaller::eimplarg(PgfExpr expr)
PgfLiteral PgfDBUnmarshaller::lint(size_t size, uintmax_t *val) PgfLiteral PgfDBUnmarshaller::lint(size_t size, uintmax_t *val)
{ {
ref<PgfLiteralInt> lit_int = ref<PgfLiteralInt> lit_int =
DB::malloc<PgfLiteralInt>(sizeof(PgfLiteralInt)+size*sizeof(uintmax_t)); PgfDB::malloc<PgfLiteralInt>(sizeof(PgfLiteralInt)+size*sizeof(uintmax_t));
lit_int->size = size; lit_int->size = size;
memcpy(&lit_int->val, val, size*sizeof(uintmax_t)); memcpy(&lit_int->val, val, size*sizeof(uintmax_t));
return ref<PgfLiteralInt>::tagged(lit_int); return ref<PgfLiteralInt>::tagged(lit_int);
@@ -181,7 +181,7 @@ PgfLiteral PgfDBUnmarshaller::lint(size_t size, uintmax_t *val)
PgfLiteral PgfDBUnmarshaller::lflt(double val) PgfLiteral PgfDBUnmarshaller::lflt(double val)
{ {
ref<PgfLiteralFlt> lit_flt = DB::malloc<PgfLiteralFlt>(); ref<PgfLiteralFlt> lit_flt = PgfDB::malloc<PgfLiteralFlt>();
lit_flt->val = val; lit_flt->val = val;
return ref<PgfLiteralFlt>::tagged(lit_flt); return ref<PgfLiteralFlt>::tagged(lit_flt);
} }
@@ -189,7 +189,7 @@ PgfLiteral PgfDBUnmarshaller::lflt(double val)
PgfLiteral PgfDBUnmarshaller::lstr(PgfText *val) PgfLiteral PgfDBUnmarshaller::lstr(PgfText *val)
{ {
ref<PgfLiteralStr> lit_str = ref<PgfLiteralStr> lit_str =
DB::malloc<PgfLiteralStr>(sizeof(PgfLiteralStr)+val->size+1); PgfDB::malloc<PgfLiteralStr>(sizeof(PgfLiteralStr)+val->size+1);
memcpy(&lit_str->val, val, sizeof(PgfText)+val->size+1); memcpy(&lit_str->val, val, sizeof(PgfText)+val->size+1);
return ref<PgfLiteralStr>::tagged(lit_str); return ref<PgfLiteralStr>::tagged(lit_str);
} }
@@ -199,13 +199,13 @@ PgfType PgfDBUnmarshaller::dtyp(int n_hypos, PgfTypeHypo *hypos,
int n_exprs, PgfExpr *exprs) int n_exprs, PgfExpr *exprs)
{ {
ref<PgfDTyp> ty = ref<PgfDTyp> ty =
DB::malloc<PgfDTyp>(sizeof(PgfDTyp)+cat->size+1); PgfDB::malloc<PgfDTyp>(sizeof(PgfDTyp)+cat->size+1);
memcpy(&ty->name, cat, sizeof(PgfText)+cat->size+1); memcpy(&ty->name, cat, sizeof(PgfText)+cat->size+1);
ty->hypos = vector_new<PgfHypo>(n_hypos); ty->hypos = vector_new<PgfHypo>(n_hypos);
for (size_t i = 0; i < n_hypos; i++) { for (size_t i = 0; i < n_hypos; i++) {
ref<PgfHypo> hypo = vector_elem(ty->hypos,i); ref<PgfHypo> hypo = vector_elem(ty->hypos,i);
hypo->bind_type = hypos[i].bind_type; hypo->bind_type = hypos[i].bind_type;
hypo->cid = DB::malloc<PgfText>(sizeof(PgfText)+hypos[i].cid->size+1); hypo->cid = PgfDB::malloc<PgfText>(sizeof(PgfText)+hypos[i].cid->size+1);
memcpy(&hypo->cid->text, hypos[i].cid, sizeof(PgfText)+hypos[i].cid->size+1); memcpy(&hypo->cid->text, hypos[i].cid, sizeof(PgfText)+hypos[i].cid->size+1);
hypo->type = m->match_type(this, hypos[i].type); hypo->type = m->match_type(this, hypos[i].type);
} }
@@ -219,7 +219,7 @@ PgfType PgfDBUnmarshaller::dtyp(int n_hypos, PgfTypeHypo *hypos,
void PgfDBUnmarshaller::free_ref(object x) void PgfDBUnmarshaller::free_ref(object x)
{ {
DB::free(ref<void>::untagged(x)); PgfDB::free(ref<void>::untagged(x));
} }
PgfExprParser::PgfExprParser(PgfText *input, PgfUnmarshaller *unmarshaller) PgfExprParser::PgfExprParser(PgfText *input, PgfUnmarshaller *unmarshaller)

View File

@@ -339,7 +339,7 @@ void namespace_release(Namespace<V> node)
if (!(--node->ref_count)) { if (!(--node->ref_count)) {
namespace_release(node->left); namespace_release(node->left);
namespace_release(node->right); namespace_release(node->right);
DB::free(node); PgfDB::free(node);
} }
} }

View File

@@ -13,15 +13,16 @@ pgf_exn_clear(PgfExn* err)
} }
PGF_API PGF_API
PgfPGF *pgf_read_pgf(const char* fpath, PgfDB *pgf_read_pgf(const char* fpath,
PgfExn* err) PgfRevision *revision,
PgfExn* err)
{ {
PgfPGF *pgf = NULL; PgfDB *db = NULL;
pgf_exn_clear(err); pgf_exn_clear(err);
try { try {
pgf = new PgfPGF(NULL, 0, 0); db = new PgfDB(NULL, 0, 0);
std::ifstream in(fpath, std::ios::binary); std::ifstream in(fpath, std::ios::binary);
if (in.fail()) { if (in.fail()) {
@@ -29,15 +30,16 @@ PgfPGF *pgf_read_pgf(const char* fpath,
} }
{ {
DB_scope scope(pgf, WRITER_SCOPE); DB_scope scope(db, WRITER_SCOPE);
PgfReader rdr(&in); PgfReader rdr(&in);
ref<PgfPGFRoot> pgf_root = rdr.read_pgf(); ref<PgfPGF> pgf = rdr.read_pgf();
pgf->set_root(pgf_root); PgfDB::set_root(pgf);
*revision = pgf.as_object();
} }
return pgf; return db;
} catch (std::system_error& e) { } catch (std::system_error& e) {
err->type = PGF_EXN_SYSTEM_ERROR; err->type = PGF_EXN_SYSTEM_ERROR;
err->code = e.code().value(); err->code = e.code().value();
@@ -46,22 +48,23 @@ PgfPGF *pgf_read_pgf(const char* fpath,
err->msg = strdup(e.what()); err->msg = strdup(e.what());
} }
if (pgf != NULL) if (db != NULL)
delete pgf; delete db;
return NULL; return NULL;
} }
PGF_API PGF_API
PgfPGF *pgf_boot_ngf(const char* pgf_path, const char* ngf_path, PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
PgfExn* err) PgfRevision *revision,
PgfExn* err)
{ {
PgfPGF *pgf = NULL; PgfDB *db = NULL;
pgf_exn_clear(err); pgf_exn_clear(err);
try { try {
pgf = new PgfPGF(ngf_path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); db = new PgfDB(ngf_path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
std::ifstream in(pgf_path, std::ios::binary); std::ifstream in(pgf_path, std::ios::binary);
if (in.fail()) { if (in.fail()) {
@@ -69,17 +72,18 @@ PgfPGF *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
} }
{ {
DB_scope scope(pgf, WRITER_SCOPE); DB_scope scope(db, WRITER_SCOPE);
PgfReader rdr(&in); PgfReader rdr(&in);
ref<PgfPGFRoot> pgf_root = rdr.read_pgf(); ref<PgfPGF> pgf = rdr.read_pgf();
pgf->set_root(pgf_root); db->set_root<PgfPGF>(pgf);
*revision = pgf.as_object();
DB::sync(); PgfDB::sync();
} }
return pgf; return db;
} catch (std::system_error& e) { } catch (std::system_error& e) {
err->type = PGF_EXN_SYSTEM_ERROR; err->type = PGF_EXN_SYSTEM_ERROR;
err->code = e.code().value(); err->code = e.code().value();
@@ -88,8 +92,8 @@ PgfPGF *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
err->msg = strdup(e.what()); err->msg = strdup(e.what());
} }
if (pgf != NULL) { if (db != NULL) {
delete pgf; delete db;
remove(ngf_path); remove(ngf_path);
} }
@@ -97,36 +101,40 @@ PgfPGF *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
} }
PGF_API PGF_API
PgfPGF *pgf_read_ngf(const char *fpath, PgfDB *pgf_read_ngf(const char *fpath,
PgfRevision *revision,
PgfExn* err) PgfExn* err)
{ {
PgfPGF *pgf = NULL; PgfDB *db = NULL;
pgf_exn_clear(err); pgf_exn_clear(err);
bool is_new = false; bool is_new = false;
try { try {
pgf = new PgfPGF(fpath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); db = new PgfDB(fpath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
{ {
DB_scope scope(pgf, WRITER_SCOPE); DB_scope scope(db, WRITER_SCOPE);
if (DB::get_root<PgfPGFRoot>() == 0) { if (PgfDB::get_root<PgfPGF>() == 0) {
is_new = true; is_new = true;
ref<PgfPGFRoot> root = DB::malloc<PgfPGFRoot>(); ref<PgfPGF> pgf = PgfDB::malloc<PgfPGF>();
root->major_version = 2; pgf->major_version = 2;
root->minor_version = 0; pgf->minor_version = 0;
root->gflags = 0; pgf->gflags = 0;
root->abstract.name = DB::malloc<PgfText>(); pgf->abstract.name = PgfDB::malloc<PgfText>();
root->abstract.name->size = 0; pgf->abstract.name->size = 0;
root->abstract.aflags = 0; pgf->abstract.aflags = 0;
root->abstract.funs = 0; pgf->abstract.funs = 0;
root->abstract.cats = 0; pgf->abstract.cats = 0;
DB::set_root<PgfPGFRoot>(root); PgfDB::set_root<PgfPGF>(pgf);
*revision = pgf.as_object();
} else {
*revision = PgfDB::get_root<PgfPGF>().as_object();
} }
} }
return pgf; return db;
} catch (std::system_error& e) { } catch (std::system_error& e) {
err->type = PGF_EXN_SYSTEM_ERROR; err->type = PGF_EXN_SYSTEM_ERROR;
err->code = e.code().value(); err->code = e.code().value();
@@ -135,8 +143,8 @@ PgfPGF *pgf_read_ngf(const char *fpath,
err->msg = strdup(e.what()); err->msg = strdup(e.what());
} }
if (pgf != NULL) { if (db != NULL) {
delete pgf; delete db;
if (is_new) if (is_new)
remove(fpath); remove(fpath);
} }
@@ -145,32 +153,42 @@ PgfPGF *pgf_read_ngf(const char *fpath,
} }
PGF_API PGF_API
void pgf_free(PgfPGF *pgf) void pgf_free(PgfDB *db)
{
delete db;
}
PGF_API_DECL
void pgf_free_revision(PgfDB *pgf, PgfRevision revision)
{ {
delete pgf;
} }
PGF_API PGF_API
PgfText *pgf_abstract_name(PgfPGF* pgf) PgfText *pgf_abstract_name(PgfDB *db, PgfRevision revision)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
return textdup(&(*pgf->get_root<PgfPGFRoot>()->abstract.name)); return textdup(&(*pgf->abstract.name));
} }
PGF_API PGF_API
void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor, PgfExn *err) void pgf_iter_categories(PgfDB *db, PgfRevision revision,
PgfItor *itor, PgfExn *err)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
err->type = PGF_EXN_NONE; err->type = PGF_EXN_NONE;
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.cats, itor, err); namespace_iter(pgf->abstract.cats, itor, err);
} }
PGF_API PGF_API
PgfType pgf_start_cat(PgfPGF *pgf, PgfUnmarshaller *u) PgfType pgf_start_cat(PgfDB *db, PgfRevision revision,
PgfUnmarshaller *u)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
PgfText *startcat = (PgfText *) PgfText *startcat = (PgfText *)
alloca(sizeof(PgfText)+9); alloca(sizeof(PgfText)+9);
@@ -178,7 +196,7 @@ PgfType pgf_start_cat(PgfPGF *pgf, PgfUnmarshaller *u)
strcpy(startcat->text, "startcat"); strcpy(startcat->text, "startcat");
ref<PgfFlag> flag = ref<PgfFlag> flag =
namespace_lookup(pgf->get_root<PgfPGFRoot>()->abstract.aflags, startcat); namespace_lookup(pgf->abstract.aflags, startcat);
if (flag != 0) { if (flag != 0) {
switch (ref<PgfLiteral>::get_tag(flag->value)) { switch (ref<PgfLiteral>::get_tag(flag->value)) {
@@ -202,12 +220,14 @@ PgfType pgf_start_cat(PgfPGF *pgf, PgfUnmarshaller *u)
} }
PGF_API PGF_API
PgfTypeHypo *pgf_category_context(PgfPGF *pgf, PgfText *catname, size_t *n_hypos, PgfUnmarshaller *u) PgfTypeHypo *pgf_category_context(PgfDB *db, PgfRevision revision,
PgfText *catname, size_t *n_hypos, PgfUnmarshaller *u)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
ref<PgfAbsCat> abscat = ref<PgfAbsCat> abscat =
namespace_lookup(pgf->get_root<PgfPGFRoot>()->abstract.cats, catname); namespace_lookup(pgf->abstract.cats, catname);
if (abscat == 0) { if (abscat == 0) {
*n_hypos = 0; *n_hypos = 0;
return NULL; return NULL;
@@ -228,12 +248,14 @@ PgfTypeHypo *pgf_category_context(PgfPGF *pgf, PgfText *catname, size_t *n_hypos
} }
PGF_API PGF_API
prob_t pgf_category_prob(PgfPGF *pgf, PgfText *catname) prob_t pgf_category_prob(PgfDB *db, PgfRevision revision,
PgfText *catname)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
ref<PgfAbsCat> abscat = ref<PgfAbsCat> abscat =
namespace_lookup(pgf->get_root<PgfPGFRoot>()->abstract.cats, catname); namespace_lookup(pgf->abstract.cats, catname);
if (abscat == 0) { if (abscat == 0) {
return 0; return 0;
} }
@@ -242,12 +264,14 @@ prob_t pgf_category_prob(PgfPGF *pgf, PgfText *catname)
} }
PGF_API PGF_API
void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor, PgfExn *err) void pgf_iter_functions(PgfDB *db, PgfRevision revision,
PgfItor *itor, PgfExn *err)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
err->type = PGF_EXN_NONE; err->type = PGF_EXN_NONE;
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.funs, itor, err); namespace_iter(pgf->abstract.funs, itor, err);
} }
struct PgfItorHelper : PgfItor struct PgfItorHelper : PgfItor
@@ -267,9 +291,11 @@ void iter_by_cat_helper(PgfItor *itor, PgfText *key, void *value,
} }
PGF_API PGF_API
void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor, PgfExn *err) void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
PgfText *cat, PgfItor *itor, PgfExn *err)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
PgfItorHelper helper; PgfItorHelper helper;
helper.fn = iter_by_cat_helper; helper.fn = iter_by_cat_helper;
@@ -277,16 +303,18 @@ void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor, PgfExn
helper.itor = itor; helper.itor = itor;
err->type = PGF_EXN_NONE; err->type = PGF_EXN_NONE;
namespace_iter(pgf->get_root<PgfPGFRoot>()->abstract.funs, &helper, err); namespace_iter(pgf->abstract.funs, &helper, err);
} }
PGF_API PGF_API
PgfType pgf_function_type(PgfPGF *pgf, PgfText *funname, PgfUnmarshaller *u) PgfType pgf_function_type(PgfDB *db, PgfRevision revision,
PgfText *funname, PgfUnmarshaller *u)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
ref<PgfAbsFun> absfun = ref<PgfAbsFun> absfun =
namespace_lookup(pgf->get_root<PgfPGFRoot>()->abstract.funs, funname); namespace_lookup(pgf->abstract.funs, funname);
if (absfun == 0) if (absfun == 0)
return 0; return 0;
@@ -294,12 +322,14 @@ PgfType pgf_function_type(PgfPGF *pgf, PgfText *funname, PgfUnmarshaller *u)
} }
PGF_API PGF_API
int pgf_function_is_constructor(PgfPGF *pgf, PgfText *funname) int pgf_function_is_constructor(PgfDB *db, PgfRevision revision,
PgfText *funname)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
ref<PgfAbsFun> absfun = ref<PgfAbsFun> absfun =
namespace_lookup(pgf->get_root<PgfPGFRoot>()->abstract.funs, funname); namespace_lookup(pgf->abstract.funs, funname);
if (absfun == 0) if (absfun == 0)
return false; return false;
@@ -307,12 +337,14 @@ int pgf_function_is_constructor(PgfPGF *pgf, PgfText *funname)
} }
PGF_API PGF_API
prob_t pgf_function_prob(PgfPGF *pgf, PgfText *funname) prob_t pgf_function_prob(PgfDB *db, PgfRevision revision,
PgfText *funname)
{ {
DB_scope scope(pgf, READER_SCOPE); DB_scope scope(db, READER_SCOPE);
ref<PgfPGF> pgf = revision;
ref<PgfAbsFun> absfun = ref<PgfAbsFun> absfun =
namespace_lookup(pgf->get_root<PgfPGFRoot>()->abstract.funs, funname); namespace_lookup(pgf->abstract.funs, funname);
if (absfun == 0) if (absfun == 0)
return INFINITY; return INFINITY;
@@ -364,16 +396,18 @@ PgfType pgf_read_type(PgfText *input, PgfUnmarshaller *u)
} }
PGF_API PGF_API
void pgf_create_function(PgfPGF *pgf, PgfText *name, void pgf_create_function(PgfDB *db, PgfRevision revision,
PgfText *name,
PgfType ty, prob_t prob, PgfType ty, prob_t prob,
PgfMarshaller *m) PgfMarshaller *m,
PgfExn *err)
{ {
DB_scope scope(pgf, WRITER_SCOPE); DB_scope scope(db, WRITER_SCOPE);
PgfDBUnmarshaller u(m); PgfDBUnmarshaller u(m);
ref<PgfPGFRoot> root = pgf->get_root<PgfPGFRoot>(); ref<PgfPGF> pgf = revision;
ref<PgfAbsFun> absfun = DB::malloc<PgfAbsFun>(sizeof(PgfAbsFun)+name->size+1); ref<PgfAbsFun> absfun = PgfDB::malloc<PgfAbsFun>(sizeof(PgfAbsFun)+name->size+1);
absfun->type = m->match_type(&u, ty); absfun->type = m->match_type(&u, ty);
absfun->arity = 0; absfun->arity = 0;
absfun->defns = 0; absfun->defns = 0;
@@ -384,7 +418,7 @@ void pgf_create_function(PgfPGF *pgf, PgfText *name,
memcpy(&absfun->name, name, sizeof(PgfText)+name->size+1); memcpy(&absfun->name, name, sizeof(PgfText)+name->size+1);
Namespace<PgfAbsFun> nmsp = Namespace<PgfAbsFun> nmsp =
namespace_insert(root->abstract.funs, absfun); namespace_insert(pgf->abstract.funs, absfun);
namespace_release(root->abstract.funs); namespace_release(pgf->abstract.funs);
root->abstract.funs = nmsp; pgf->abstract.funs = nmsp;
} }

View File

@@ -210,62 +210,80 @@ struct PgfMarshaller {
typedef float prob_t; typedef float prob_t;
typedef struct PgfPGF PgfPGF; typedef struct PgfDB PgfDB;
typedef object PgfRevision;
/* Reads a PGF file and keeps it in memory. */ /* Reads a PGF file and builds the database in memory.
* If successful, *revision will contain the initial revision of
* the grammar. */
PGF_API_DECL PGF_API_DECL
PgfPGF *pgf_read_pgf(const char* fpath, PgfDB *pgf_read_pgf(const char* fpath, PgfRevision *revision,
PgfExn* err); PgfExn* err);
/* Reads a PGF file and stores the unpacked data in an NGF file /* Reads a PGF file and stores the unpacked data in an NGF file
* ready to be shared with other process, or used for quick startup. * ready to be shared with other process, or used for quick re-start.
* The NGF file is platform dependent and should not be copied * The NGF file is platform dependent and should not be copied
* between machines. */ * between machines. */
PGF_API_DECL PGF_API_DECL
PgfPGF *pgf_boot_ngf(const char* pgf_path, const char* ngf_path, PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path,
PgfExn* err); PgfRevision *revision,
PgfExn* err);
/* Tries to read the grammar from an already booted NGF file. /* Tries to read the grammar from an already booted NGF file.
* If the file does not exist then a new one is created, and the * If the file does not exist then a new one is created, and the
* grammar is set to be empty. It can later be populated with * grammar is set to be empty. It can later be populated with
* rules dynamically. */ * rules dynamically. The default grammar revision is stored
* in *revision. */
PGF_API_DECL PGF_API_DECL
PgfPGF *pgf_read_ngf(const char* fpath, PgfDB *pgf_read_ngf(const char* fpath,
PgfExn* err); PgfRevision *revision,
PgfExn* err);
/* Release the grammar when it is no longer needed. */ /* Release the database when it is no longer needed. */
PGF_API_DECL PGF_API_DECL
void pgf_free(PgfPGF *pgf); void pgf_free(PgfDB *pgf);
PGF_API_DECL PGF_API_DECL
PgfText *pgf_abstract_name(PgfPGF *pgf); void pgf_free_revision(PgfDB *pgf, PgfRevision revision);
PGF_API_DECL PGF_API_DECL
void pgf_iter_categories(PgfPGF *pgf, PgfItor *itor, PgfExn *err); PgfText *pgf_abstract_name(PgfDB *db, PgfRevision revision);
PGF_API_DECL PGF_API_DECL
PgfType pgf_start_cat(PgfPGF *pgf, PgfUnmarshaller *u); void pgf_iter_categories(PgfDB *db, PgfRevision revision,
PgfItor *itor, PgfExn *err);
PGF_API_DECL PGF_API_DECL
PgfTypeHypo *pgf_category_context(PgfPGF *pgf, PgfText *catname, size_t *n_hypos, PgfUnmarshaller *u); PgfType pgf_start_cat(PgfDB *db, PgfRevision revision,
PgfUnmarshaller *u);
PGF_API_DECL PGF_API_DECL
prob_t pgf_category_prob(PgfPGF* pgf, PgfText *catname); PgfTypeHypo *pgf_category_context(PgfDB *db, PgfRevision revision,
PgfText *catname, size_t *n_hypos, PgfUnmarshaller *u);
PGF_API_DECL PGF_API_DECL
void pgf_iter_functions(PgfPGF *pgf, PgfItor *itor, PgfExn *err); prob_t pgf_category_prob(PgfDB *db, PgfRevision revision,
PgfText *catname);
PGF_API_DECL PGF_API_DECL
void pgf_iter_functions_by_cat(PgfPGF *pgf, PgfText *cat, PgfItor *itor, PgfExn *err); void pgf_iter_functions(PgfDB *db, PgfRevision revision,
PgfItor *itor, PgfExn *err);
PGF_API_DECL PGF_API_DECL
PgfType pgf_function_type(PgfPGF *pgf, PgfText *funname, PgfUnmarshaller *u); void pgf_iter_functions_by_cat(PgfDB *db, PgfRevision revision,
PgfText *cat, PgfItor *itor, PgfExn *err);
PGF_API_DECL PGF_API_DECL
int pgf_function_is_constructor(PgfPGF *pgf, PgfText *funname); PgfType pgf_function_type(PgfDB *db, PgfRevision revision,
PgfText *funname, PgfUnmarshaller *u);
PGF_API_DECL PGF_API_DECL
prob_t pgf_function_prob(PgfPGF *pgf, PgfText *funname); int pgf_function_is_constructor(PgfDB *db, PgfRevision revision,
PgfText *funname);
PGF_API_DECL
prob_t pgf_function_prob(PgfDB *db, PgfRevision revision,
PgfText *funname);
typedef struct PgfPrintContext PgfPrintContext; typedef struct PgfPrintContext PgfPrintContext;
@@ -291,8 +309,10 @@ PGF_API_DECL
PgfType pgf_read_type(PgfText *input, PgfUnmarshaller *u); PgfType pgf_read_type(PgfText *input, PgfUnmarshaller *u);
PGF_API_DECL PGF_API_DECL
void pgf_create_function(PgfPGF *pgf, PgfText *name, void pgf_create_function(PgfDB *db, PgfRevision revision,
PgfText *name,
PgfType ty, prob_t prob, PgfType ty, prob_t prob,
PgfMarshaller *m); PgfMarshaller *m,
PgfExn *err);
#endif // PGF_H_ #endif // PGF_H_

View File

@@ -204,7 +204,7 @@ PgfLiteral PgfReader::read_literal()
} }
case PgfLiteralInt::tag: { case PgfLiteralInt::tag: {
ref<PgfLiteralInt> lit_int = ref<PgfLiteralInt> lit_int =
DB::malloc<PgfLiteralInt>(sizeof(PgfLiteralInt)+sizeof(uintmax_t)); PgfDB::malloc<PgfLiteralInt>(sizeof(PgfLiteralInt)+sizeof(uintmax_t));
lit_int->size = 1; lit_int->size = 1;
lit_int->val[0] = read_int(); lit_int->val[0] = read_int();
lit = ref<PgfLiteralInt>::tagged(lit_int); lit = ref<PgfLiteralInt>::tagged(lit_int);
@@ -245,20 +245,20 @@ PgfExpr PgfReader::read_expr()
break; break;
} }
case PgfExprApp::tag: { case PgfExprApp::tag: {
ref<PgfExprApp> eapp = DB::malloc<PgfExprApp>(); ref<PgfExprApp> eapp = PgfDB::malloc<PgfExprApp>();
eapp->fun = read_expr(); eapp->fun = read_expr();
eapp->arg = read_expr(); eapp->arg = read_expr();
expr = ref<PgfExprApp>::tagged(eapp); expr = ref<PgfExprApp>::tagged(eapp);
break; break;
} }
case PgfExprLit::tag: { case PgfExprLit::tag: {
ref<PgfExprLit> elit = DB::malloc<PgfExprLit>(); ref<PgfExprLit> elit = PgfDB::malloc<PgfExprLit>();
elit->lit = read_literal(); elit->lit = read_literal();
expr = ref<PgfExprLit>::tagged(elit); expr = ref<PgfExprLit>::tagged(elit);
break; break;
} }
case PgfExprMeta::tag: { case PgfExprMeta::tag: {
ref<PgfExprMeta> emeta = DB::malloc<PgfExprMeta>(); ref<PgfExprMeta> emeta = PgfDB::malloc<PgfExprMeta>();
emeta->id = read_int(); emeta->id = read_int();
expr = ref<PgfExprMeta>::tagged(emeta); expr = ref<PgfExprMeta>::tagged(emeta);
break; break;
@@ -269,13 +269,13 @@ PgfExpr PgfReader::read_expr()
break; break;
} }
case PgfExprVar::tag: { case PgfExprVar::tag: {
ref<PgfExprVar> evar = DB::malloc<PgfExprVar>(); ref<PgfExprVar> evar = PgfDB::malloc<PgfExprVar>();
evar->var = read_int(); evar->var = read_int();
expr = ref<PgfExprVar>::tagged(evar); expr = ref<PgfExprVar>::tagged(evar);
break; break;
} }
case PgfExprTyped::tag: { case PgfExprTyped::tag: {
ref<PgfExprTyped> etyped = DB::malloc<PgfExprTyped>(); ref<PgfExprTyped> etyped = PgfDB::malloc<PgfExprTyped>();
etyped->expr = read_expr(); etyped->expr = read_expr();
etyped->type = read_type(); etyped->type = read_type();
expr = ref<PgfExprTyped>::tagged(etyped); expr = ref<PgfExprTyped>::tagged(etyped);
@@ -339,24 +339,24 @@ PgfPatt PgfReader::read_patt()
break; break;
} }
case PgfPattWild::tag: { case PgfPattWild::tag: {
ref<PgfPattWild> pwild = DB::malloc<PgfPattWild>(); ref<PgfPattWild> pwild = PgfDB::malloc<PgfPattWild>();
patt = ref<PgfPattWild>::tagged(pwild); patt = ref<PgfPattWild>::tagged(pwild);
break; break;
} }
case PgfPattLit::tag: { case PgfPattLit::tag: {
ref<PgfPattLit> plit = DB::malloc<PgfPattLit>(); ref<PgfPattLit> plit = PgfDB::malloc<PgfPattLit>();
plit->lit = read_literal(); plit->lit = read_literal();
patt = ref<PgfPattLit>::tagged(plit); patt = ref<PgfPattLit>::tagged(plit);
break; break;
} }
case PgfPattImplArg::tag: { case PgfPattImplArg::tag: {
ref<PgfPattImplArg> pimpl = DB::malloc<PgfPattImplArg>(); ref<PgfPattImplArg> pimpl = PgfDB::malloc<PgfPattImplArg>();
pimpl->patt = read_patt(); pimpl->patt = read_patt();
patt = ref<PgfPattImplArg>::tagged(pimpl); patt = ref<PgfPattImplArg>::tagged(pimpl);
break; break;
} }
case PgfPattTilde::tag: { case PgfPattTilde::tag: {
ref<PgfPattTilde> ptilde = DB::malloc<PgfPattTilde>(); ref<PgfPattTilde> ptilde = PgfDB::malloc<PgfPattTilde>();
ptilde->expr = read_expr(); ptilde->expr = read_expr();
patt = ref<PgfPattTilde>::tagged(ptilde); patt = ref<PgfPattTilde>::tagged(ptilde);
break; break;
@@ -425,9 +425,9 @@ void PgfReader::read_abstract(ref<PgfAbstr> abstract)
abstract->cats = read_namespace<PgfAbsCat>(&PgfReader::read_abscat); abstract->cats = read_namespace<PgfAbsCat>(&PgfReader::read_abscat);
} }
ref<PgfPGFRoot> PgfReader::read_pgf() ref<PgfPGF> PgfReader::read_pgf()
{ {
ref<PgfPGFRoot> pgf = DB::malloc<PgfPGFRoot>(); ref<PgfPGF> pgf = PgfDB::malloc<PgfPGF>();
pgf->major_version = read_u16be(); pgf->major_version = read_u16be();
pgf->minor_version = read_u16be(); pgf->minor_version = read_u16be();

View File

@@ -70,7 +70,7 @@ public:
ref<PgfAbsCat> read_abscat(); ref<PgfAbsCat> read_abscat();
void read_abstract(ref<PgfAbstr> abstract); void read_abstract(ref<PgfAbstr> abstract);
ref<PgfPGFRoot> read_pgf(); ref<PgfPGF> read_pgf();
private: private:
std::istream *in; std::istream *in;

View File

@@ -10,7 +10,7 @@ struct PgfVector {
template <class A> inline template <class A> inline
ref<PgfVector<A>> vector_new(size_t len) ref<PgfVector<A>> vector_new(size_t len)
{ {
ref<PgfVector<A>> res = DB::malloc<PgfVector<A>>(sizeof(PgfVector<A>)+len*sizeof(A)); ref<PgfVector<A>> res = PgfDB::malloc<PgfVector<A>>(sizeof(PgfVector<A>)+len*sizeof(A));
res->len = len; res->len = len;
return res; return res;
} }
@@ -18,7 +18,7 @@ ref<PgfVector<A>> vector_new(size_t len)
template <class C, class A> inline template <class C, class A> inline
ref<C> vector_new(PgfVector<A> C::* field, size_t len) ref<C> vector_new(PgfVector<A> C::* field, size_t len)
{ {
ref<C> res = DB::malloc<C>(((size_t) &(((C*) NULL)->*field))+sizeof(PgfVector<A>)+len*sizeof(A)); ref<C> res = PgfDB::malloc<C>(((size_t) &(((C*) NULL)->*field))+sizeof(PgfVector<A>)+len*sizeof(A));
(res->*field).len = len; (res->*field).len = len;
return res; return res;
} }

View File

@@ -56,6 +56,7 @@ import PGF2.FFI
import Foreign import Foreign
import Foreign.C import Foreign.C
import qualified Foreign.Concurrent as C
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.IORef import Data.IORef
@@ -68,10 +69,13 @@ type ConcName = String -- ^ Name of concrete syntax
readPGF :: FilePath -> IO PGF readPGF :: FilePath -> IO PGF
readPGF fpath = readPGF fpath =
withCString fpath $ \c_fpath -> withCString fpath $ \c_fpath ->
alloca $ \p_revision ->
mask_ $ do mask_ $ do
c_pgf <- withPgfExn fpath (pgf_read_pgf c_fpath) c_pgf <- withPgfExn fpath (pgf_read_pgf c_fpath p_revision)
fptr <- newForeignPtr pgf_free_fptr c_pgf c_revision <- peek p_revision
return (PGF fptr Map.empty) fptr1 <- newForeignPtr pgf_free_fptr c_pgf
fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision))
return (PGF fptr1 fptr2 Map.empty)
-- | Reads a PGF file and stores the unpacked data in an NGF file -- | Reads a PGF file and stores the unpacked data in an NGF file
-- ready to be shared with other process, or used for quick startup. -- ready to be shared with other process, or used for quick startup.
@@ -81,10 +85,13 @@ bootNGF :: FilePath -> FilePath -> IO PGF
bootNGF pgf_path ngf_path = bootNGF pgf_path ngf_path =
withCString pgf_path $ \c_pgf_path -> withCString pgf_path $ \c_pgf_path ->
withCString ngf_path $ \c_ngf_path -> withCString ngf_path $ \c_ngf_path ->
alloca $ \p_revision ->
mask_ $ do mask_ $ do
c_pgf <- withPgfExn pgf_path (pgf_boot_ngf c_pgf_path c_ngf_path) c_pgf <- withPgfExn pgf_path (pgf_boot_ngf c_pgf_path c_ngf_path p_revision)
fptr <- newForeignPtr pgf_free_fptr c_pgf c_revision <- peek p_revision
return (PGF fptr Map.empty) fptr1 <- newForeignPtr pgf_free_fptr c_pgf
fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision))
return (PGF fptr1 fptr2 Map.empty)
-- | Tries to read the grammar from an already booted NGF file. -- | Tries to read the grammar from an already booted NGF file.
-- If the file does not exist then a new one is created, and the -- If the file does not exist then a new one is created, and the
@@ -93,18 +100,22 @@ bootNGF pgf_path ngf_path =
readNGF :: FilePath -> IO PGF readNGF :: FilePath -> IO PGF
readNGF fpath = readNGF fpath =
withCString fpath $ \c_fpath -> withCString fpath $ \c_fpath ->
alloca $ \p_revision ->
mask_ $ do mask_ $ do
c_pgf <- withPgfExn fpath (pgf_read_ngf c_fpath) c_db <- withPgfExn fpath (pgf_read_ngf c_fpath p_revision)
fptr <- newForeignPtr pgf_free_fptr c_pgf c_revision <- peek p_revision
return (PGF fptr Map.empty) fptr1 <- newForeignPtr pgf_free_fptr c_db
fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision))
return (PGF fptr1 fptr2 Map.empty)
-- | The abstract language name is the name of the top-level -- | The abstract language name is the name of the top-level
-- abstract module -- abstract module
abstractName :: PGF -> AbsName abstractName :: PGF -> AbsName
abstractName p = abstractName p =
unsafePerformIO $ unsafePerformIO $
withForeignPtr (a_pgf p) $ \p_pgf -> withForeignPtr (a_db p) $ \c_db ->
bracket (pgf_abstract_name p_pgf) free $ \c_text -> withForeignPtr (revision p) $ \c_revision ->
bracket (pgf_abstract_name c_db c_revision) free $ \c_text ->
peekText c_text peekText c_text
-- | The start category is defined in the grammar with -- | The start category is defined in the grammar with
@@ -116,8 +127,9 @@ startCat :: PGF -> Type
startCat p = startCat p =
unsafePerformIO $ unsafePerformIO $
withForeignPtr unmarshaller $ \u -> withForeignPtr unmarshaller $ \u ->
withForeignPtr (a_pgf p) $ \c_pgf -> do withForeignPtr (a_db p) $ \c_db ->
c_typ <- pgf_start_cat c_pgf u withForeignPtr (revision p) $ \c_revision -> do
c_typ <- pgf_start_cat c_db c_revision u
typ <- deRefStablePtr c_typ typ <- deRefStablePtr c_typ
freeStablePtr c_typ freeStablePtr c_typ
return typ return typ
@@ -127,9 +139,10 @@ functionType :: PGF -> Fun -> Maybe Type
functionType p fn = functionType p fn =
unsafePerformIO $ unsafePerformIO $
withForeignPtr unmarshaller $ \u -> withForeignPtr unmarshaller $ \u ->
withForeignPtr (a_pgf p) $ \p_pgf -> withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision ->
withText fn $ \c_fn -> do withText fn $ \c_fn -> do
c_typ <- pgf_function_type p_pgf c_fn u c_typ <- pgf_function_type c_db c_revision c_fn u
if c_typ == castPtrToStablePtr nullPtr if c_typ == castPtrToStablePtr nullPtr
then return Nothing then return Nothing
else do typ <- deRefStablePtr c_typ else do typ <- deRefStablePtr c_typ
@@ -140,16 +153,18 @@ functionIsConstructor :: PGF -> Fun -> Bool
functionIsConstructor p fun = functionIsConstructor p fun =
unsafePerformIO $ unsafePerformIO $
withText fun $ \c_fun -> withText fun $ \c_fun ->
withForeignPtr (a_pgf p) $ \c_pgf -> withForeignPtr (a_db p) $ \c_db ->
do res <- pgf_function_is_constructor c_pgf c_fun withForeignPtr (revision p) $ \c_revision ->
do res <- pgf_function_is_constructor c_db c_revision c_fun
return (res /= 0) return (res /= 0)
functionProb :: PGF -> Fun -> Float functionProb :: PGF -> Fun -> Float
functionProb p fun = functionProb p fun =
unsafePerformIO $ unsafePerformIO $
withText fun $ \c_fun -> withText fun $ \c_fun ->
withForeignPtr (a_pgf p) $ \c_pgf -> withForeignPtr (a_db p) $ \c_db ->
do c_prob <- pgf_function_prob c_pgf c_fun withForeignPtr (revision p) $ \c_revision ->
do c_prob <- pgf_function_prob c_db c_revision c_fun
return (realToFrac c_prob) return (realToFrac c_prob)
-- | List of all functions defined in the abstract syntax -- | List of all functions defined in the abstract syntax
@@ -159,9 +174,10 @@ categories p =
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getCategories ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
withPgfExn "" (pgf_iter_categories p_pgf itor) withPgfExn "" (pgf_iter_categories c_db c_revision itor)
cs <- readIORef ref cs <- readIORef ref
return (reverse cs)) return (reverse cs))
where where
@@ -177,9 +193,10 @@ categoryContext p cat =
withText cat $ \c_cat -> withText cat $ \c_cat ->
alloca $ \p_n_hypos -> alloca $ \p_n_hypos ->
withForeignPtr unmarshaller $ \u -> withForeignPtr unmarshaller $ \u ->
withForeignPtr (a_pgf p) $ \c_pgf -> withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision ->
mask_ $ do mask_ $ do
c_hypos <- pgf_category_context c_pgf c_cat p_n_hypos u c_hypos <- pgf_category_context c_db c_revision c_cat p_n_hypos u
if c_hypos == nullPtr if c_hypos == nullPtr
then return [] then return []
else do n_hypos <- peek p_n_hypos else do n_hypos <- peek p_n_hypos
@@ -204,8 +221,9 @@ categoryProb :: PGF -> Cat -> Float
categoryProb p cat = categoryProb p cat =
unsafePerformIO $ unsafePerformIO $
withText cat $ \c_cat -> withText cat $ \c_cat ->
withForeignPtr (a_pgf p) $ \c_pgf -> withForeignPtr (a_db p) $ \c_db ->
do c_prob <- pgf_category_prob c_pgf c_cat withForeignPtr (revision p) $ \c_revision ->
do c_prob <- pgf_category_prob c_db c_revision c_cat
return (realToFrac c_prob) return (realToFrac c_prob)
-- | List of all functions defined in the abstract syntax -- | List of all functions defined in the abstract syntax
@@ -215,9 +233,10 @@ functions p =
ref <- newIORef [] ref <- newIORef []
(allocaBytes (#size PgfItor) $ \itor -> (allocaBytes (#size PgfItor) $ \itor ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
withPgfExn "" (pgf_iter_functions p_pgf itor) withPgfExn "" (pgf_iter_functions c_db c_revision itor)
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
@@ -235,9 +254,10 @@ functionsByCat p cat =
(withText cat $ \c_cat -> (withText cat $ \c_cat ->
allocaBytes (#size PgfItor) $ \itor -> allocaBytes (#size PgfItor) $ \itor ->
bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr -> bracket (wrapItorCallback (getFunctions ref)) freeHaskellFunPtr $ \fptr ->
withForeignPtr (a_pgf p) $ \p_pgf -> do withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision -> do
(#poke PgfItor, fn) itor fptr (#poke PgfItor, fn) itor fptr
withPgfExn "" (pgf_iter_functions_by_cat p_pgf c_cat itor) withPgfExn "" (pgf_iter_functions_by_cat c_db c_revision c_cat itor)
fs <- readIORef ref fs <- readIORef ref
return (reverse fs)) return (reverse fs))
where where
@@ -319,8 +339,9 @@ readType str =
createFunction :: PGF -> Fun -> Type -> Float -> IO () createFunction :: PGF -> Fun -> Type -> Float -> IO ()
createFunction p name ty prob = createFunction p name ty prob =
withForeignPtr (a_pgf p) $ \p_pgf -> withForeignPtr (a_db p) $ \c_db ->
withForeignPtr (revision p) $ \c_revision ->
withText name $ \c_name -> withText name $ \c_name ->
bracket (newStablePtr ty) freeStablePtr $ \c_ty -> bracket (newStablePtr ty) freeStablePtr $ \c_ty ->
withForeignPtr marshaller $ \m -> do withForeignPtr marshaller $ \m -> do
pgf_create_function p_pgf c_name c_ty prob m pgf_create_function c_db c_revision c_name c_ty prob m

View File

@@ -20,8 +20,11 @@ import PGF2.Expr
-- | An abstract data type representing multilingual grammar -- | An abstract data type representing multilingual grammar
-- in Portable Grammar Format. -- in Portable Grammar Format.
data PGF = PGF {a_pgf :: ForeignPtr PgfPGF, langs :: Map.Map String Concr} data PGF = PGF { a_db :: ForeignPtr PgfDB
data Concr = Concr {c_pgf :: ForeignPtr PgfPGF, concr :: Ptr PgfConcr} , revision :: ForeignPtr PgfRevision
, langs :: Map.Map String Concr
}
data Concr = Concr {c_pgf :: ForeignPtr PgfDB, concr :: Ptr PgfConcr}
------------------------------------------------------------------ ------------------------------------------------------------------
-- libpgf API -- libpgf API
@@ -29,7 +32,8 @@ data Concr = Concr {c_pgf :: ForeignPtr PgfPGF, concr :: Ptr PgfConcr}
data PgfExn data PgfExn
data PgfText data PgfText
data PgfItor data PgfItor
data PgfPGF data PgfDB
data PgfRevision
data PgfPrintContext data PgfPrintContext
data PgfConcr data PgfConcr
data PgfTypeHypo data PgfTypeHypo
@@ -43,19 +47,22 @@ foreign import ccall unsafe "pgf_utf8_encode"
pgf_utf8_encode :: Word32 -> Ptr CString -> IO () pgf_utf8_encode :: Word32 -> Ptr CString -> IO ()
foreign import ccall "pgf_read_pgf" foreign import ccall "pgf_read_pgf"
pgf_read_pgf :: CString -> Ptr PgfExn -> IO (Ptr PgfPGF) pgf_read_pgf :: CString -> Ptr (Ptr PgfRevision) -> Ptr PgfExn -> IO (Ptr PgfDB)
foreign import ccall "pgf_boot_ngf" foreign import ccall "pgf_boot_ngf"
pgf_boot_ngf :: CString -> CString -> Ptr PgfExn -> IO (Ptr PgfPGF) pgf_boot_ngf :: CString -> CString -> Ptr (Ptr PgfRevision) -> Ptr PgfExn -> IO (Ptr PgfDB)
foreign import ccall "pgf_read_ngf" foreign import ccall "pgf_read_ngf"
pgf_read_ngf :: CString -> Ptr PgfExn -> IO (Ptr PgfPGF) pgf_read_ngf :: CString -> Ptr (Ptr PgfRevision) -> Ptr PgfExn -> IO (Ptr PgfDB)
foreign import ccall "&pgf_free" foreign import ccall "&pgf_free"
pgf_free_fptr :: FinalizerPtr PgfPGF pgf_free_fptr :: FinalizerPtr PgfDB
foreign import ccall "pgf_free_revision"
pgf_free_revision :: Ptr PgfDB -> Ptr PgfRevision -> IO ()
foreign import ccall "pgf_abstract_name" foreign import ccall "pgf_abstract_name"
pgf_abstract_name :: Ptr PgfPGF -> IO (Ptr PgfText) pgf_abstract_name :: Ptr PgfDB -> Ptr PgfRevision -> IO (Ptr PgfText)
foreign import ccall "pgf_print_expr" foreign import ccall "pgf_print_expr"
pgf_print_expr :: StablePtr Expr -> Ptr PgfPrintContext -> CInt -> Ptr PgfMarshaller -> IO (Ptr PgfText) pgf_print_expr :: StablePtr Expr -> Ptr PgfPrintContext -> CInt -> Ptr PgfMarshaller -> IO (Ptr PgfText)
@@ -75,34 +82,34 @@ foreign import ccall "wrapper"
wrapItorCallback :: ItorCallback -> IO (FunPtr ItorCallback) wrapItorCallback :: ItorCallback -> IO (FunPtr ItorCallback)
foreign import ccall "pgf_iter_categories" foreign import ccall "pgf_iter_categories"
pgf_iter_categories :: Ptr PgfPGF -> Ptr PgfItor -> Ptr PgfExn -> IO () pgf_iter_categories :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall "pgf_start_cat" foreign import ccall "pgf_start_cat"
pgf_start_cat :: Ptr PgfPGF -> Ptr PgfUnmarshaller -> IO (StablePtr Type) pgf_start_cat :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfUnmarshaller -> IO (StablePtr Type)
foreign import ccall "pgf/pgf.h pgf_category_context" foreign import ccall "pgf/pgf.h pgf_category_context"
pgf_category_context :: Ptr PgfPGF -> Ptr PgfText -> Ptr CSize -> Ptr PgfUnmarshaller -> IO (Ptr PgfTypeHypo) pgf_category_context :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfText -> Ptr CSize -> Ptr PgfUnmarshaller -> IO (Ptr PgfTypeHypo)
foreign import ccall "pgf/pgf.h pgf_category_prob" foreign import ccall "pgf/pgf.h pgf_category_prob"
pgf_category_prob :: Ptr PgfPGF -> Ptr PgfText -> IO (#type prob_t) pgf_category_prob :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfText -> IO (#type prob_t)
foreign import ccall "pgf_iter_functions" foreign import ccall "pgf_iter_functions"
pgf_iter_functions :: Ptr PgfPGF -> Ptr PgfItor -> Ptr PgfExn -> IO () pgf_iter_functions :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall "pgf_iter_functions_by_cat" foreign import ccall "pgf_iter_functions_by_cat"
pgf_iter_functions_by_cat :: Ptr PgfPGF -> Ptr PgfText -> Ptr PgfItor -> Ptr PgfExn -> IO () pgf_iter_functions_by_cat :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfText -> Ptr PgfItor -> Ptr PgfExn -> IO ()
foreign import ccall "pgf/pgf.h pgf_function_type" foreign import ccall "pgf/pgf.h pgf_function_type"
pgf_function_type :: Ptr PgfPGF -> Ptr PgfText -> Ptr PgfUnmarshaller -> IO (StablePtr Type) pgf_function_type :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfText -> Ptr PgfUnmarshaller -> IO (StablePtr Type)
foreign import ccall "pgf/expr.h pgf_function_is_constructor" foreign import ccall "pgf/expr.h pgf_function_is_constructor"
pgf_function_is_constructor :: Ptr PgfPGF -> Ptr PgfText -> IO (#type int) pgf_function_is_constructor :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfText -> IO (#type int)
foreign import ccall "pgf/expr.h pgf_function_is_constructor" foreign import ccall "pgf/expr.h pgf_function_is_constructor"
pgf_function_prob :: Ptr PgfPGF -> Ptr PgfText -> IO (#type prob_t) pgf_function_prob :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfText -> IO (#type prob_t)
foreign import ccall "pgf_create_function" foreign import ccall "pgf_create_function"
pgf_create_function :: Ptr PgfPGF -> Ptr PgfText -> StablePtr Type -> (#type prob_t) -> Ptr PgfMarshaller -> IO () pgf_create_function :: Ptr PgfDB -> Ptr PgfRevision -> Ptr PgfText -> StablePtr Type -> (#type prob_t) -> Ptr PgfMarshaller -> IO ()
----------------------------------------------------------------------- -----------------------------------------------------------------------

View File

@@ -74,8 +74,11 @@ main = do
print (e :: SomeException) print (e :: SomeException)
gr1 <- readPGF "tests/basic.pgf" gr1 <- readPGF "tests/basic.pgf"
print (abstractName gr1)
gr2 <- bootNGF "tests/basic.pgf" "tests/basic.ngf" gr2 <- bootNGF "tests/basic.pgf" "tests/basic.ngf"
print (abstractName gr2)
gr3 <- readNGF "tests/basic.ngf" gr3 <- readNGF "tests/basic.ngf"
print (abstractName gr3)
rp1 <- testLoadFailure (readPGF "non-existing.pgf") rp1 <- testLoadFailure (readPGF "non-existing.pgf")
rp2 <- testLoadFailure (readPGF "tests/basic.gf") rp2 <- testLoadFailure (readPGF "tests/basic.gf")

View File

@@ -15,7 +15,8 @@ static PyObject *PGFError;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
PgfPGF *pgf; PgfDB *db;
PgfRevision revision;
} PGFObject; } PGFObject;
// typedef struct IterObject { // typedef struct IterObject {
@@ -1719,7 +1720,7 @@ typedef struct {
static void static void
PGF_dealloc(PGFObject* self) PGF_dealloc(PGFObject* self)
{ {
pgf_free(self->pgf); pgf_free(self->db);
Py_TYPE(self)->tp_free((PyObject*)self); Py_TYPE(self)->tp_free((PyObject*)self);
} }
@@ -1767,7 +1768,7 @@ PGF_repr(PGFObject *self)
static PyObject* static PyObject*
PGF_getAbstractName(PGFObject *self, void *closure) PGF_getAbstractName(PGFObject *self, void *closure)
{ {
PgfText* txt = pgf_abstract_name(self->pgf); PgfText* txt = pgf_abstract_name(self->db, self->revision);
PyObject *name = PyString_FromStringAndSize(txt->text, txt->size); PyObject *name = PyString_FromStringAndSize(txt->text, txt->size);
free(txt); free(txt);
return name; return name;
@@ -1866,7 +1867,7 @@ PGF_getCategories(PGFObject *self, void *closure)
PgfExn err; PgfExn err;
PyPGFClosure clo = { { pgf_collect_cats }, self, categories }; PyPGFClosure clo = { { pgf_collect_cats }, self, categories };
pgf_iter_categories(self->pgf, &clo.fn, &err); pgf_iter_categories(self->db, self->revision, &clo.fn, &err);
if (err.type != PGF_EXN_NONE) { if (err.type != PGF_EXN_NONE) {
Py_DECREF(categories); Py_DECREF(categories);
return NULL; return NULL;
@@ -1878,7 +1879,7 @@ PGF_getCategories(PGFObject *self, void *closure)
static TypeObject * static TypeObject *
PGF_getStartCat(PGFObject *self, void *closure) PGF_getStartCat(PGFObject *self, void *closure)
{ {
PgfType type = pgf_start_cat(self->pgf, &unmarshaller); PgfType type = pgf_start_cat(self->db, self->revision, &unmarshaller);
if (type == 0) { if (type == 0) {
PyErr_SetString(PGFError, "The start category cannot be found"); PyErr_SetString(PGFError, "The start category cannot be found");
return NULL; return NULL;
@@ -1915,7 +1916,7 @@ PGF_getFunctions(PGFObject *self, void *closure)
PgfExn err; PgfExn err;
PyPGFClosure clo = { { pgf_collect_funs }, self, functions }; PyPGFClosure clo = { { pgf_collect_funs }, self, functions };
pgf_iter_functions(self->pgf, &clo.fn, &err); pgf_iter_functions(self->db, self->revision, &clo.fn, &err);
if (err.type != PGF_EXN_NONE) { if (err.type != PGF_EXN_NONE) {
Py_DECREF(functions); Py_DECREF(functions);
return NULL; return NULL;
@@ -1943,7 +1944,7 @@ PGF_functionsByCat(PGFObject* self, PyObject *args)
PgfExn err; PgfExn err;
PyPGFClosure clo = { { pgf_collect_funs }, self, functions }; PyPGFClosure clo = { { pgf_collect_funs }, self, functions };
pgf_iter_functions_by_cat(self->pgf, catname, &clo.fn, &err); pgf_iter_functions_by_cat(self->db, self->revision, catname, &clo.fn, &err);
if (err.type != PGF_EXN_NONE) { if (err.type != PGF_EXN_NONE) {
Py_DECREF(functions); Py_DECREF(functions);
return NULL; return NULL;
@@ -1964,7 +1965,7 @@ PGF_functionType(PGFObject *self, PyObject *args)
memcpy(funname->text, s, size+1); memcpy(funname->text, s, size+1);
funname->size = size; funname->size = size;
PgfType type = pgf_function_type(self->pgf, funname, &unmarshaller); PgfType type = pgf_function_type(self->db, self->revision, funname, &unmarshaller);
if (type == 0) { if (type == 0) {
PyErr_Format(PyExc_KeyError, "Function '%s' is not defined", funname->text); PyErr_Format(PyExc_KeyError, "Function '%s' is not defined", funname->text);
return NULL; return NULL;
@@ -2385,7 +2386,7 @@ pgf_readPGF(PyObject *self, PyObject *args)
// Read the PGF grammar. // Read the PGF grammar.
PgfExn err; PgfExn err;
py_pgf->pgf = pgf_read_pgf(fpath, &err); py_pgf->db = pgf_read_pgf(fpath, &py_pgf->revision, &err);
if (err.type == PGF_EXN_SYSTEM_ERROR) { if (err.type == PGF_EXN_SYSTEM_ERROR) {
errno = err.code; errno = err.code;
PyErr_SetFromErrnoWithFilename(PyExc_IOError, fpath); PyErr_SetFromErrnoWithFilename(PyExc_IOError, fpath);
@@ -2413,7 +2414,7 @@ pgf_bootNGF(PyObject *self, PyObject *args)
// Read the PGF grammar. // Read the PGF grammar.
PgfExn err; PgfExn err;
py_pgf->pgf = pgf_boot_ngf(fpath, npath, &err); py_pgf->db = pgf_boot_ngf(fpath, npath, &py_pgf->revision, &err);
if (err.type == PGF_EXN_SYSTEM_ERROR) { if (err.type == PGF_EXN_SYSTEM_ERROR) {
errno = err.code; errno = err.code;
PyErr_SetFromErrnoWithFilename(PyExc_IOError, npath); PyErr_SetFromErrnoWithFilename(PyExc_IOError, npath);
@@ -2440,7 +2441,7 @@ pgf_readNGF(PyObject *self, PyObject *args)
// Read the NGF grammar. // Read the NGF grammar.
PgfExn err; PgfExn err;
py_pgf->pgf = pgf_read_ngf(fpath, &err); py_pgf->db = pgf_read_ngf(fpath, &py_pgf->revision, &err);
if (err.type == PGF_EXN_SYSTEM_ERROR) { if (err.type == PGF_EXN_SYSTEM_ERROR) {
errno = err.code; errno = err.code;
PyErr_SetFromErrnoWithFilename(PyExc_IOError, fpath); PyErr_SetFromErrnoWithFilename(PyExc_IOError, fpath);