diff --git a/src/runtime/c/Makefile.am b/src/runtime/c/Makefile.am index c0c96b46b..d46287d3b 100644 --- a/src/runtime/c/Makefile.am +++ b/src/runtime/c/Makefile.am @@ -28,7 +28,7 @@ libpgf_la_SOURCES = \ pgf/namespace.h libpgf_la_LDFLAGS = -no-undefined -libpgf_la_LIBADD = -lrt +# libpgf_la_LIBADD = -lrt libpgf_la_CXXFLAGS = -fno-rtti -std=c++11 bin_PROGRAMS = diff --git a/src/runtime/c/pgf/data.h b/src/runtime/c/pgf/data.h index 054a2bce7..02b98a390 100644 --- a/src/runtime/c/pgf/data.h +++ b/src/runtime/c/pgf/data.h @@ -123,7 +123,7 @@ struct PGF_INTERNAL_DECL PgfPGF { static void release(ref pgf); }; -extern PGF_INTERNAL_DECL -PgfText master; +extern PGF_INTERNAL_DECL size_t master_size; +extern PGF_INTERNAL_DECL char master_text[]; #endif diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index 50020df83..4ebb39d03 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -883,8 +883,16 @@ object PgfDB::malloc_internal(size_t bytes) throw pgf_systemerror(errno, filepath); } +// OSX mman and mman-win32 do not implement mremap or MREMAP_MAYMOVE +#ifndef MREMAP_MAYMOVE + if (munmap(ms, old_size) == -1) + throw pgf_systemerror(errno); + malloc_state* new_ms = + (malloc_state*) mmap(0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); +#else malloc_state* new_ms = (malloc_state*) mremap(ms, old_size, new_size, MREMAP_MAYMOVE); +#endif if (new_ms == MAP_FAILED) throw pgf_systemerror(errno); diff --git a/src/runtime/c/pgf/expr.cxx b/src/runtime/c/pgf/expr.cxx index dc8f4b316..dafe8db6b 100644 --- a/src/runtime/c/pgf/expr.cxx +++ b/src/runtime/c/pgf/expr.cxx @@ -239,13 +239,15 @@ PgfExprParser::~PgfExprParser() free(token_value); } -uint32_t PgfExprParser::getc() +bool PgfExprParser::getc() { - uint32_t ch = pgf_utf8_decode((const uint8_t **) &pos); - if (pos - ((const char*) &inp->text) > inp->size) { - ch = EOF; - } - return ch; + if (pos - ((const char*) &inp->text) >= inp->size) { + ch = ' '; + return false; + } + + ch = pgf_utf8_decode((const uint8_t **) &pos); + return true; } void PgfExprParser::putc(uint32_t ucs) @@ -256,7 +258,7 @@ void PgfExprParser::putc(uint32_t ucs) ucs < 0x10000 ? 3 : ucs < 0x200000 ? 4 : ucs < 0x4000000 ? 5 : - 6 + 6 ); size_t len = token_value ? token_value->size : 0; @@ -313,10 +315,12 @@ pgf_is_normal_ident(PgfText *id) return true; } -void PgfExprParser::str_char() +bool PgfExprParser::str_char() { if (ch == '\\') { - ch = getc(); + if (!getc()) + return false; + switch (ch) { case '\\': putc('\\'); @@ -340,14 +344,14 @@ void PgfExprParser::str_char() putc('\t'); break; case '0': - puts("\0"); + putc('\0'); default: - return; + return false; } } else { putc(ch); } - ch = getc(); + return getc(); } void PgfExprParser::token() @@ -361,86 +365,91 @@ void PgfExprParser::token() while (isspace(ch)) { token_pos = pos; - ch = getc(); + if (!getc()) { + token_tag = PGF_TOKEN_EOF; + return; + } } switch (ch) { - case EOF: - token_tag = PGF_TOKEN_EOF; - break; case '(': - ch = getc(); + getc(); token_tag = PGF_TOKEN_LPAR; break; case ')': - ch = getc(); + getc(); token_tag = PGF_TOKEN_RPAR; break; case '{': - ch = getc(); + getc(); token_tag = PGF_TOKEN_LCURLY; break; case '}': - ch = getc(); + getc(); token_tag = PGF_TOKEN_RCURLY; break; case '<': - ch = getc(); + getc(); token_tag = PGF_TOKEN_LTRIANGLE; break; case '>': - ch = getc(); + getc(); token_tag = PGF_TOKEN_RTRIANGLE; break; case '?': - ch = getc(); + getc(); token_tag = PGF_TOKEN_QUESTION; break; case '\\': - ch = getc(); + getc(); token_tag = PGF_TOKEN_LAMBDA; break; case '-': - ch = getc(); - if (ch == '>') { - ch = getc(); - token_tag = PGF_TOKEN_RARROW; - } else if (isdigit(ch)) { - putc('-'); - goto digit; + if (getc()) { + if (ch == '>') { + getc(); + token_tag = PGF_TOKEN_RARROW; + } else if (isdigit(ch)) { + putc('-'); + goto digit; + } } break; case ',': - ch = getc(); + getc(); token_tag = PGF_TOKEN_COMMA; break; case ':': - ch = getc(); + getc(); token_tag = PGF_TOKEN_COLON; break; case ';': - ch = getc(); + getc(); token_tag = PGF_TOKEN_SEMI; break; case '\'': { - ch = getc(); - while (ch != '\'' && ch != EOF) { - str_char(); - } - if (ch == '\'') { - ch = getc(); - token_tag = PGF_TOKEN_IDENT; - } + if (getc()) { + while (ch != '\'') { + if (!str_char()) + break; + } + if (ch == '\'') { + getc(); + token_tag = PGF_TOKEN_IDENT; + } + } break; } case '"': { - ch = getc(); - while (ch != '"' && ch != EOF) { - str_char(); - } - if (ch == '"') { - ch = getc(); - token_tag = PGF_TOKEN_STR; + if (getc()) { + while (ch != '"') { + if (!str_char()) + break; + } + if (ch == '"') { + getc(); + token_tag = PGF_TOKEN_STR; + } } break; } @@ -448,28 +457,34 @@ void PgfExprParser::token() if (pgf_is_ident_first(ch)) { do { putc(ch); - ch = getc(); + if (!getc()) + break; } while (pgf_is_ident_rest(ch)); - token_tag = PGF_TOKEN_IDENT; + if (token_value->size == 1 && strcmp(token_value->text,"_")==0) + token_tag = PGF_TOKEN_WILD; + else + token_tag = PGF_TOKEN_IDENT; } else if (isdigit(ch)) { digit: do { putc(ch); - ch = getc(); + if (!getc()) + break; } while (isdigit(ch)); - if (ch == '.') { - putc(ch); - ch = getc(); - - while (isdigit(ch)) { - putc(ch); - ch = getc(); - } + if (ch == '.') { + putc(ch); + if (getc()) { + while (isdigit(ch)) { + putc(ch); + if (!getc()) + break; + } + } token_tag = PGF_TOKEN_FLT; - } else { - token_tag = PGF_TOKEN_INT; - } + } else { + token_tag = PGF_TOKEN_INT; + } } break; } @@ -479,7 +494,8 @@ digit: bool PgfExprParser::lookahead(int ch) { while (isspace(this->ch)) { - this->ch = getc(); + if (!getc()) + break; } return (this->ch == ch); @@ -615,8 +631,6 @@ PgfExpr PgfExprParser::parse_arg() return arg; } -PGF_INTERNAL PgfText wildcard = {size: 1, text: {'_',0}}; - PgfBind *PgfExprParser::parse_bind(PgfBind *next) { PgfBind *last = next; @@ -629,10 +643,8 @@ PgfBind *PgfExprParser::parse_bind(PgfBind *next) for (;;) { PgfText *var; - if (token_tag == PGF_TOKEN_IDENT) { + if (token_tag == PGF_TOKEN_IDENT || token_tag == PGF_TOKEN_WILD) { var = token_value; - } else if (token_tag == PGF_TOKEN_WILD) { - var = &wildcard; } else { goto error; } @@ -771,10 +783,8 @@ bool PgfExprParser::parse_hypos(size_t *n_hypos, PgfTypeHypo **hypos) } PgfText *var; - if (token_tag == PGF_TOKEN_IDENT) { + if (token_tag == PGF_TOKEN_IDENT || token_tag == PGF_TOKEN_WILD) { var = token_value; - } else if (token_tag == PGF_TOKEN_WILD) { - var = &wildcard; } else { return false; } @@ -807,6 +817,18 @@ bool PgfExprParser::parse_hypos(size_t *n_hypos, PgfTypeHypo **hypos) return true; } +static +PgfText *mk_wildcard() +{ + PgfText *t = (PgfText *) malloc(sizeof(PgfText)+2); + if (t != NULL) { + t->size = 1; + t->text[0] = '_'; + t->text[1] = 0; + } + return t; +} + PgfType PgfExprParser::parse_type() { PgfType type = 0; @@ -826,7 +848,7 @@ PgfType PgfExprParser::parse_type() size_t n_start = n_hypos; if ((token_tag == PGF_TOKEN_IDENT && - (lookahead(',') || + (lookahead(',') || lookahead(':'))) || (token_tag == PGF_TOKEN_LCURLY) || (token_tag == PGF_TOKEN_WILD)) { @@ -842,7 +864,7 @@ PgfType PgfExprParser::parse_type() hypos = (PgfTypeHypo*) realloc(hypos, sizeof(PgfTypeHypo)*(n_hypos+1)); PgfTypeHypo *bt = &hypos[n_hypos]; bt->bind_type = PGF_BIND_TYPE_EXPLICIT; - bt->cid = textdup(&wildcard); + bt->cid = mk_wildcard(); bt->type = 0; n_hypos++; } @@ -889,7 +911,7 @@ PgfType PgfExprParser::parse_type() hypos = (PgfTypeHypo*) realloc(hypos, sizeof(PgfTypeHypo)*(n_hypos+1)); PgfTypeHypo *bt = &hypos[n_hypos]; bt->bind_type = PGF_BIND_TYPE_EXPLICIT; - bt->cid = textdup(&wildcard); + bt->cid = mk_wildcard(); bt->type = u->dtyp(0,NULL,cat,n_args,args); n_hypos++; diff --git a/src/runtime/c/pgf/expr.h b/src/runtime/c/pgf/expr.h index e645b61fa..bb1c62b3c 100644 --- a/src/runtime/c/pgf/expr.h +++ b/src/runtime/c/pgf/expr.h @@ -210,14 +210,14 @@ class PGF_INTERNAL_DECL PgfExprParser { const char *token_pos, *pos; uint32_t ch; - uint32_t getc(); + bool getc(); void putc(uint32_t ch); public: PgfExprParser(PgfText* input, PgfUnmarshaller *unmarshaller); ~PgfExprParser(); - void str_char(); + bool str_char(); void token(); bool lookahead(int ch); @@ -267,8 +267,6 @@ public: prob_t get_prob() { return prob; }; }; -PGF_INTERNAL_DECL extern PgfText wildcard; - /* The following functions release the memory in the database, * allocated for values of the corresponding types. */ diff --git a/src/runtime/c/pgf/ipc.cxx b/src/runtime/c/pgf/ipc.cxx index c84c9e7a2..c56d4f489 100644 --- a/src/runtime/c/pgf/ipc.cxx +++ b/src/runtime/c/pgf/ipc.cxx @@ -2,6 +2,9 @@ #include #include #include +#include +#include + #include "pgf/data.h" typedef struct { diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index 9d3230dff..b2f44c7b5 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -1,5 +1,7 @@ #include #include +#include + #include "data.h" #include "reader.h" #include "writer.h" @@ -28,8 +30,8 @@ pgf_exn_clear(PgfExn* err) err->msg = strdup(e.what()); \ } -PGF_INTERNAL -PgfText master = {size: 6, text: {'m','a','s','t','e','r',0}}; +PGF_INTERNAL size_t master_size = 6; +PGF_INTERNAL char master_text[] = {'m','a','s','t','e','r',0}; PGF_API PgfDB *pgf_read_pgf(const char* fpath, @@ -124,10 +126,14 @@ PgfDB *pgf_read_ngf(const char *fpath, PGF_API_BEGIN { db = new PgfDB(fpath, O_RDWR, 0); + PgfText *master = (PgfText *)alloca(sizeof(PgfText)+master_size+1); + master->size = master_size; + memcpy(&master->text, master_text, master_size+1); + { DB_scope scope(db, WRITER_SCOPE); - ref pgf = PgfDB::get_revision(&master); + ref pgf = PgfDB::get_revision(master); Node::add_value_ref(pgf); *revision = pgf.as_object(); } @@ -159,7 +165,7 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name, { DB_scope scope(db, WRITER_SCOPE); - ref pgf = PgfDB::malloc(master.size+1); + ref pgf = PgfDB::malloc(master_size+1); pgf->ref_count = 1; pgf->major_version = PGF_MAJOR_VERSION; pgf->minor_version = PGF_MINOR_VERSION; @@ -171,7 +177,8 @@ PgfDB *pgf_new_ngf(PgfText *abstract_name, pgf->abstract.cats = 0; pgf->prev = 0; pgf->next = 0; - memcpy(&pgf->name, &master, sizeof(PgfText)+master.size+1); + pgf->name.size = master_size; + memcpy(&pgf->name.text, master_text, master_size+1); PgfDB::set_revision(pgf); *revision = pgf.as_object(); @@ -269,7 +276,7 @@ void pgf_iter_categories(PgfDB *db, PgfRevision revision, PGF_API_BEGIN { DB_scope scope(db, READER_SCOPE); ref pgf = PgfDB::revision2pgf(revision); - + namespace_iter(pgf->abstract.cats, itor, err); } PGF_API_END } @@ -671,7 +678,7 @@ void pgf_create_function(PgfDB *db, PgfRevision revision, ref::from_ptr((PgfExprFun*) &absfun->name); absfun->ep.expr = ref::tagged(efun); memcpy(&absfun->name, name, sizeof(PgfText)+name->size+1); - + Namespace funs = namespace_insert(pgf->abstract.funs, absfun); namespace_release(pgf->abstract.funs); diff --git a/src/runtime/c/pgf/printer.cxx b/src/runtime/c/pgf/printer.cxx index fefee4717..2643724db 100644 --- a/src/runtime/c/pgf/printer.cxx +++ b/src/runtime/c/pgf/printer.cxx @@ -382,7 +382,7 @@ PgfLiteral PgfPrinter::lstr(PgfText *v) void PgfPrinter::hypo(PgfTypeHypo *hypo, int prio) { - if (textcmp(hypo->cid, &wildcard) == 0) { + if (hypo->cid->size == 1 && strcmp(hypo->cid->text, "_") == 0) { this->prio = prio; m->match_type(this, hypo->type); } else { diff --git a/src/runtime/c/pgf/reader.cxx b/src/runtime/c/pgf/reader.cxx index cb0e7098a..5e090c154 100644 --- a/src/runtime/c/pgf/reader.cxx +++ b/src/runtime/c/pgf/reader.cxx @@ -430,7 +430,7 @@ void PgfReader::read_abstract(ref abstract) ref PgfReader::read_pgf() { - ref pgf = PgfDB::malloc(master.size+1); + ref pgf = PgfDB::malloc(master_size+1); pgf->ref_count = 1; pgf->major_version = read_u16be(); @@ -448,7 +448,8 @@ ref PgfReader::read_pgf() pgf->prev = 0; pgf->next = 0; - memcpy(&pgf->name, &master, sizeof(PgfText)+master.size+1); + pgf->name.size = master_size; + memcpy(&pgf->name.text, master_text, master_size+1); return pgf; } diff --git a/src/runtime/haskell/pgf2.cabal b/src/runtime/haskell/pgf2.cabal index beb137b03..77dc779e0 100644 --- a/src/runtime/haskell/pgf2.cabal +++ b/src/runtime/haskell/pgf2.cabal @@ -50,7 +50,7 @@ test-suite basic default-language: Haskell2010 build-depends: base, - HUnit, + HUnit >= 1.6.1.0, random, directory, pgf2 @@ -61,5 +61,5 @@ test-suite transactions default-language: Haskell2010 build-depends: base, - HUnit, + HUnit >= 1.6.1.0, pgf2 diff --git a/src/runtime/haskell/stack.yaml b/src/runtime/haskell/stack.yaml index 3b1a3092b..f7a9f5cbb 100644 --- a/src/runtime/haskell/stack.yaml +++ b/src/runtime/haskell/stack.yaml @@ -1,3 +1,5 @@ -# This is mainly here so that I can run `stack sdist` for uploading to Hackage - resolver: lts-12.26 # ghc 8.4.4 + +extra-deps: + - HUnit-1.6.2.0@sha256:1a79174e8af616117ad39464cac9de205ca923da6582825e97c10786fda933a4,1588 + - call-stack-0.4.0@sha256:ac44d2c00931dc20b01750da8c92ec443eb63a7231e8550188cb2ac2385f7feb,1200 diff --git a/src/runtime/javascript/expr.ts b/src/runtime/javascript/expr.ts index e598b55c5..a3f5bc881 100644 --- a/src/runtime/javascript/expr.ts +++ b/src/runtime/javascript/expr.ts @@ -10,10 +10,37 @@ export class Type { } } +export function mkType (hypos: Hypo[], name: string, exprs: Expr[]): Type { + return new Type(hypos, name, exprs) +} + +export enum BindType { + Explicit, + Implicit +} + export class Hypo { - bind_type!: boolean - var!: string - type!: Type + bind_type: BindType + var: string + type: Type + + constructor (bt: BindType, v: string, t: Type) { + this.bind_type = bt + this.var = v + this.type = t + } +} + +export function mkHypo (type: Type): Hypo { + return new Hypo(BindType.Explicit, '_', type) +} + +export function mkDepHypo (vr: string, type: Type): Hypo { + return new Hypo(BindType.Explicit, vr, type) +} + +export function mkImplHypo (vr: string, type: Type): Hypo { + return new Hypo(BindType.Implicit, vr, type) } export class Expr { diff --git a/src/runtime/javascript/ffi.ts b/src/runtime/javascript/ffi.ts index 4dd78a416..d83e3b6af 100644 --- a/src/runtime/javascript/ffi.ts +++ b/src/runtime/javascript/ffi.ts @@ -48,15 +48,22 @@ export const PgfTextPtr = ref.refType(PgfText) export const PgfItorPtr = ref.refType(ref.types.void) -const PgfType = ref.refType(ref.types.Object) // TODO -// const PgfTypePtr = ref.refType(PgfType) +const PgfType = ref.refType(ref.types.Object) -const PgfTypeHypo = ref.types.void // TODO -const PgfTypeHypoPtr = ref.refType(PgfTypeHypo) +const PgfTypeHypo = Struct({ + bind_type: ref.types.int, + cid: PgfTextPtr, + type: PgfType +}) export const PgfExpr = ref.refType(ref.types.Object) export const PgfLiteral = ref.refType(ref.types.Object) +// export const PgfTypePtr = ref.refType(PgfType) +export const PgfTypeHypoPtr = ref.refType(PgfTypeHypo) +export const PgfExprPtr = ref.refType(PgfExpr) +// export const PgfLiteralPtr = ref.refType(PgfLiteral) + const PgfMetaId = ref.types.int const PgfPrintContext = ref.types.void // TODO @@ -158,7 +165,7 @@ export function PgfText_FromString (str: string): Pointer { // ---------------------------------------------------------------------------- // Un/marshalling -const eabs = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.bool, PgfTextPtr, PgfExpr], +const eabs = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, ref.types.bool, PgfTextPtr, PgfExpr], function (self, btype: boolean, name: Pointer, body: Pointer): Pointer { const jsname = PgfText_AsString(name) const obj = new ExprAbs(btype, jsname, body.deref()) @@ -167,7 +174,7 @@ const eabs = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.bool, PgfTextPtr, return buf }) -const eapp = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfExpr], +const eapp = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, PgfExpr, PgfExpr], function (self, fun: Pointer, arg: Pointer): Pointer { const obj = new ExprApp(fun.deref(), arg.deref()) const buf = ref.alloc(ref.types.Object) as Pointer @@ -175,7 +182,7 @@ const eapp = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfExpr], return buf }) -const elit = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfLiteral], +const elit = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, PgfLiteral], function (self, lit: Pointer): Pointer { const litObj = lit.deref() const obj = new ExprLit(litObj) @@ -184,7 +191,7 @@ const elit = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfLiteral], return buf }) -const emeta = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfMetaId], +const emeta = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, PgfMetaId], function (self, meta: number): Pointer { const obj = new ExprMeta(meta) const buf = ref.alloc(ref.types.Object) as Pointer @@ -192,7 +199,7 @@ const emeta = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfMetaId], return buf }) -const efun = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfTextPtr], +const efun = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, PgfTextPtr], function (self, name: Pointer): Pointer { const jsname = PgfText_AsString(name) const obj = new ExprFun(jsname) @@ -201,7 +208,7 @@ const efun = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfTextPtr], return buf }) -const evar = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.int], +const evar = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, ref.types.int], function (self, index: number): Pointer { const obj = new ExprVar(index) const buf = ref.alloc(ref.types.Object) as Pointer @@ -209,7 +216,7 @@ const evar = ffi.Callback(PgfExpr, [PgfUnmarshaller, ref.types.int], return buf }) -const etyped = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfType], +const etyped = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, PgfExpr, PgfType], function (self, expr: Pointer, type: Pointer): Pointer { const obj = new ExprTyped(expr.deref(), type.deref()) const buf = ref.alloc(ref.types.Object) as Pointer @@ -217,7 +224,7 @@ const etyped = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr, PgfType], return buf }) -const eimplarg = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr], +const eimplarg = ffi.Callback(PgfExpr, [PgfUnmarshallerPtr, PgfExpr], function (self, expr: Pointer): Pointer { const obj = new ExprImplArg(expr.deref()) const buf = ref.alloc(ref.types.Object) as Pointer @@ -225,7 +232,7 @@ const eimplarg = ffi.Callback(PgfExpr, [PgfUnmarshaller, PgfExpr], return buf }) -const lint = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.size_t, ref.refType(ref.types.int)], +const lint = ffi.Callback(PgfLiteral, [PgfUnmarshallerPtr, ref.types.size_t, ref.refType(ref.types.int)], function (self, size: number, val: Pointer): Pointer { let jsval: number | bigint = 0 if (size === 1) { @@ -263,7 +270,7 @@ const lint = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.size_t, ref.re return buf }) -const lflt = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.double], +const lflt = ffi.Callback(PgfLiteral, [PgfUnmarshallerPtr, ref.types.double], function (self, val: number): Pointer { const obj = new Literal(val) const buf = ref.alloc(ref.types.Object) as Pointer @@ -271,7 +278,7 @@ const lflt = ffi.Callback(PgfLiteral, [PgfUnmarshaller, ref.types.double], return buf }) -const lstr = ffi.Callback(PgfLiteral, [PgfUnmarshaller, PgfTextPtr], +const lstr = ffi.Callback(PgfLiteral, [PgfUnmarshallerPtr, PgfTextPtr], function (self, val: Pointer): Pointer { const jsval = PgfText_AsString(val) const obj = new Literal(jsval) @@ -280,19 +287,36 @@ const lstr = ffi.Callback(PgfLiteral, [PgfUnmarshaller, PgfTextPtr], return buf }) -const dtyp = ffi.Callback(PgfType, [PgfUnmarshaller, ref.types.int, PgfTypeHypoPtr, PgfTextPtr, ref.types.int, ref.refType(PgfExpr)], +const dtyp = ffi.Callback(PgfType, [PgfUnmarshallerPtr, ref.types.int, PgfTypeHypoPtr, PgfTextPtr, ref.types.int, PgfExprPtr], function (self, n_hypos: number, hypos: Pointer, cat: Pointer, n_exprs: number, exprs: Pointer): Pointer { - // TODO const jshypos: Hypo[] = [] + if (n_hypos > 0) { + const hyposArr = hypos.reinterpret(PgfTypeHypo.size * n_hypos, 0) + for (let i = 0; i < n_hypos; i++) { + const hypo = ref.get(hyposArr, PgfTypeHypo.size * i, PgfTypeHypo) + const h = new Hypo(hypo.bind_type, PgfText_AsString(hypo.cid), hypo.type.deref() as Type) + jshypos.push(h) + } + } + const jsname = PgfText_AsString(cat) + const jsexprs: Expr[] = [] + if (n_exprs > 0) { + const exprsArr = exprs.reinterpret(PgfExpr.size * n_exprs, 0) + for (let i = 0; i < n_exprs; i++) { + const expr = ref.get(exprsArr, PgfExpr.size * i, PgfExpr) + jsexprs.push(expr.deref() as Expr) + } + } + const obj = new Type(jshypos, jsname, jsexprs) const buf = ref.alloc(ref.types.Object) as Pointer ref.writeObject(buf, 0, obj) return buf }) -const free_ref = ffi.Callback(ref.types.void, [PgfUnmarshaller, ref.refType(ref.types.Object)], +const free_ref = ffi.Callback(ref.types.void, [PgfUnmarshallerPtr, ref.refType(ref.types.Object)], function (self, x: Pointer): void { }) @@ -314,17 +338,17 @@ const un_vtbl = new PgfUnmarshallerVtbl({ export const unmarshaller = new PgfUnmarshaller({ vtbl: un_vtbl.ref() }) -const match_lit = ffi.Callback(ref.types.Object, [PgfMarshaller, PgfUnmarshaller, PgfLiteral], +const match_lit = ffi.Callback(ref.types.Object, [PgfMarshallerPtr, PgfUnmarshallerPtr, PgfLiteral], function (self, u: any, lit: any): Pointer { return 0 as any }) -const match_expr = ffi.Callback(ref.types.Object, [PgfMarshaller, PgfUnmarshaller, PgfExpr], +const match_expr = ffi.Callback(ref.types.Object, [PgfMarshallerPtr, PgfUnmarshallerPtr, PgfExpr], function (self, u: any, expr: any): Pointer { return 0 as any }) -const match_type = ffi.Callback(ref.types.Object, [PgfMarshaller, PgfUnmarshaller, PgfType], +const match_type = ffi.Callback(ref.types.Object, [PgfMarshallerPtr, PgfUnmarshallerPtr, PgfType], function (self, u: any, type: any): Pointer { return 0 as any }) diff --git a/src/runtime/javascript/index.ts b/src/runtime/javascript/index.ts index 753484eeb..6c78db85d 100644 --- a/src/runtime/javascript/index.ts +++ b/src/runtime/javascript/index.ts @@ -2,8 +2,8 @@ import errno from './errno' import { - Type, - Hypo, + Type, mkType, + Hypo, mkHypo, mkDepHypo, mkImplHypo, Expr, ExprAbs, ExprApp, @@ -229,6 +229,10 @@ function readExpr (str: string): Expr { return ref.readObject(expr) as Expr } +function showType (context: string[], type: Type): string { + return 'TODO' +} + // ---------------------------------------------------------------------------- // Exposed library API @@ -242,9 +246,14 @@ export { readType, readExpr, + showType, Type, + mkType, Hypo, + mkHypo, + mkDepHypo, + mkImplHypo, Expr, ExprAbs, ExprApp, @@ -266,9 +275,14 @@ export default { readType, readExpr, + showType, Type, + mkType, Hypo, + mkHypo, + mkDepHypo, + mkImplHypo, Expr, ExprAbs, ExprApp, diff --git a/src/runtime/javascript/tests/basic.test.ts b/src/runtime/javascript/tests/basic.test.ts index a01046fe2..f8164f347 100644 --- a/src/runtime/javascript/tests/basic.test.ts +++ b/src/runtime/javascript/tests/basic.test.ts @@ -2,14 +2,18 @@ import PGF, { PGFError, PGFGrammar, // Type, + mkType, // Hypo, + mkHypo, + mkDepHypo, + mkImplHypo, // Expr, // ExprAbs, ExprApp, ExprLit, ExprMeta, ExprFun, - // ExprVar, + ExprVar, // ExprTyped, ExprImplArg // Literal @@ -225,10 +229,87 @@ describe('abstract syntax', () => { // ---------------------------------------------------------------------------- describe('types', () => { - test('invalid', () => { - expect(() => { - PGF.readType('->') - }).toThrow(PGFError) + describe('read', () => { + test('invalid', () => { + expect(() => { + PGF.readType('->') + }).toThrow(PGFError) + }) + + test('1', () => { + const t1 = PGF.readType('A') + const t2 = PGF.readType('A') + const t3 = PGF.readType('B') + expect(t1).toEqual(t2) + expect(t1).not.toEqual(t3) + }) + + test('2', () => { + const t1 = PGF.readType('A -> B') + const t2 = PGF.readType('A->B') + const t3 = PGF.readType('B->B') + expect(t1).toEqual(t2) + expect(t1).not.toEqual(t3) + }) + + test('3', () => { + const t1 = PGF.readType('A -> B -> C') + const t2 = PGF.readType('A->B -> C') + expect(t1).toEqual(t2) + }) + + test('4', () => { + const t1 = PGF.readType('(x : N) -> P x') + const t2 = mkType([mkDepHypo('x', mkType([], 'N', []))], 'P', [new ExprFun('x')]) + expect(t1).toEqual(t2) + }) + }) + + describe.skip('show', () => { + test('1', () => { + const type = mkType([], 'N', []) + expect(PGF.showType([], type)).toEqual('N') + }) + + test('2', () => { + const type = mkType([mkHypo(mkType([], 'N', []))], 'N', []) + expect(PGF.showType([], type)).toEqual('N -> N') + }) + + test('3', () => { + const type = mkType([mkHypo(mkType([mkHypo(mkType([], 'N', []))], 'N', []))], 'N', []) + expect(PGF.showType([], type)).toEqual('(N -> N) -> N') + }) + + test('4', () => { + const type = mkType([mkDepHypo('x', mkType([], 'N', []))], 'P', [new ExprVar(0)]) + expect(PGF.showType([], type)).toEqual('(x : N) -> P x') + }) + + test('5', () => { + const type = mkType([mkDepHypo('f', mkType([mkHypo(mkType([], 'N', []))], 'N', []))], 'P', [new ExprApp(new ExprVar(0), new ExprFun('z'))]) + expect(PGF.showType([], type)).toEqual('(f : N -> N) -> P (f z)') + }) + + test('6', () => { + const type = mkType([mkDepHypo('f', mkType([mkHypo(mkType([], 'N', []))], 'N', []))], 'P', [new ExprApp(new ExprVar(0), new ExprVar(1))]) + expect(PGF.showType(['n'], type)).toEqual('(f : N -> N) -> P (f n)') + }) + + test('7', () => { + const type = mkType([mkImplHypo('f', mkType([mkHypo(mkType([], 'N', []))], 'N', []))], 'P', [new ExprApp(new ExprVar(0), new ExprVar(1))]) + expect(PGF.showType(['n'], type)).toEqual('({f} : N -> N) -> P (f n)') + }) + + test('8', () => { + const type = mkType([mkDepHypo('x', mkType([], 'N', [])), mkHypo(mkType([], 'P', [new ExprVar(0)]))], 'S', []) + expect(PGF.showType(['n'], type)).toEqual('(x : N) -> P x -> S') + }) + + test('9', () => { + const type = mkType([mkDepHypo('x', mkType([], 'N', [])), mkDepHypo('y', mkType([], 'P', [new ExprVar(0)]))], 'S', []) + expect(PGF.showType(['n'], type)).toEqual('(x : N) -> (y : P x) -> S') + }) }) })