From d87b3ce166cef067240614aaeb0565dd3838451a Mon Sep 17 00:00:00 2001 From: Krasimir Angelov Date: Mon, 10 Jan 2022 10:27:09 +0100 Subject: [PATCH] get rid of the destructive updates for seq_ids --- src/runtime/c/pgf/data.h | 1 - src/runtime/c/pgf/pgf.cxx | 40 +++++++++------ src/runtime/c/pgf/pgf.h | 19 ++++--- src/runtime/c/pgf/phrasetable.cxx | 83 +++++++++++++++++++++++++++++-- src/runtime/c/pgf/phrasetable.h | 38 +++++++++++++- src/runtime/c/pgf/printer.cxx | 4 +- src/runtime/c/pgf/printer.h | 2 +- src/runtime/c/pgf/reader.cxx | 1 - src/runtime/c/pgf/writer.cxx | 6 ++- src/runtime/c/pgf/writer.h | 6 +-- src/runtime/haskell/PGF2.hsc | 38 +++++++------- src/runtime/haskell/PGF2/FFI.hsc | 15 +++--- 12 files changed, 191 insertions(+), 62 deletions(-) diff --git a/src/runtime/c/pgf/data.h b/src/runtime/c/pgf/data.h index dbd65e5c5..ad47f8774 100644 --- a/src/runtime/c/pgf/data.h +++ b/src/runtime/c/pgf/data.h @@ -130,7 +130,6 @@ struct PGF_INTERNAL_DECL PgfPResult { typedef object PgfSymbol; struct PGF_INTERNAL_DECL PgfSequence { - size_t seq_id; size_t ref_count; Vector syms; diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index d9daf335f..7f5b5b70e 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -827,16 +827,22 @@ void pgf_iter_lins(PgfDB *db, PgfConcrRevision cnc_revision, } PGF_API -void pgf_iter_sequences(PgfDB *db, PgfConcrRevision cnc_revision, - PgfSequenceItor *itor, PgfExn *err) +PgfPhrasetableIds *pgf_iter_sequences(PgfDB *db, PgfConcrRevision cnc_revision, + PgfSequenceItor *itor, PgfExn *err) { PGF_API_BEGIN { DB_scope scope(db, READER_SCOPE); ref concr = PgfDB::revision2concr(cnc_revision); - size_t next_id = 0; - phrasetable_iter(concr->phrasetable, itor, &next_id, err); + PgfPhrasetableIds *seq_ids = new PgfPhrasetableIds(); + seq_ids->start(concr); + + phrasetable_iter(concr->phrasetable, itor, seq_ids, err); + + return seq_ids; } PGF_API_END + + return NULL; } PGF_API @@ -863,7 +869,7 @@ size_t pgf_get_lin_get_prod_count(object o) } PGF_API -PgfText *pgf_print_lindef_internal(object o, size_t i) +PgfText *pgf_print_lindef_internal(PgfPhrasetableIds *seq_ids, object o, size_t i) { ref lincat = o; @@ -893,7 +899,7 @@ PgfText *pgf_print_lindef_internal(object o, size_t i) printer.puts(","); ref seq = *vector_elem(lincat->seqs, i*n_seqs + j); - printer.seq_id(seq->seq_id); + printer.seq_id(seq_ids, seq); } printer.puts("]"); @@ -902,7 +908,7 @@ PgfText *pgf_print_lindef_internal(object o, size_t i) } PGF_API -PgfText *pgf_print_linref_internal(object o, size_t i) +PgfText *pgf_print_linref_internal(PgfPhrasetableIds *seq_ids, object o, size_t i) { ref lincat = o; @@ -926,7 +932,7 @@ PgfText *pgf_print_linref_internal(object o, size_t i) size_t n_seqs = lincat->fields->len; ref seq = *vector_elem(lincat->seqs, lincat->n_lindefs*n_seqs+i); - printer.seq_id(seq->seq_id); + printer.seq_id(seq_ids, seq); printer.puts("]"); @@ -934,7 +940,7 @@ PgfText *pgf_print_linref_internal(object o, size_t i) } PGF_API -PgfText *pgf_print_lin_internal(object o, size_t i) +PgfText *pgf_print_lin_internal(PgfPhrasetableIds *seq_ids, object o, size_t i) { ref lin = o; ref ty = lin->absfun->type; @@ -975,7 +981,7 @@ PgfText *pgf_print_lin_internal(object o, size_t i) printer.puts(","); ref seq = *vector_elem(lin->seqs, i*n_seqs + j); - printer.seq_id(seq->seq_id); + printer.seq_id(seq_ids, seq); } printer.puts("]"); @@ -984,20 +990,25 @@ PgfText *pgf_print_lin_internal(object o, size_t i) } PGF_API -PgfText *pgf_print_sequence_internal(object o) +PgfText *pgf_print_sequence_internal(size_t seq_id, object o) { ref seq = o; PgfInternalMarshaller m; PgfPrinter printer(NULL,0,&m); - printer.seq_id(seq->seq_id); - printer.puts(" = "); + printer.nprintf(10,"S%zu = ", seq_id); printer.sequence(seq); return printer.get_text(); } +PGF_API_DECL +void pgf_release_phrasetable_ids(PgfPhrasetableIds *seq_ids) +{ + delete seq_ids; +} + PGF_API void pgf_check_expr(PgfDB *db, PgfRevision revision, PgfExpr* pe, PgfType ty, @@ -1578,7 +1589,6 @@ public: throw pgf_error(builder_error_msg); seq = PgfDB::malloc(n_syms*sizeof(PgfSymbol)); - seq->seq_id = 0; seq->ref_count = 1; seq->syms.len = n_syms; @@ -1680,7 +1690,6 @@ public: throw pgf_error(builder_error_msg); ref def = PgfDB::malloc(n_syms*sizeof(PgfSymbol)); - def->seq_id = 0; def->ref_count = 1; def->syms.len = n_syms; @@ -1707,7 +1716,6 @@ public: throw pgf_error(builder_error_msg); ref form = PgfDB::malloc(n_syms*sizeof(PgfSymbol)); - form->seq_id = 0; form->ref_count = 1; form->syms.len = n_syms; diff --git a/src/runtime/c/pgf/pgf.h b/src/runtime/c/pgf/pgf.h index e2275b553..098600dd2 100644 --- a/src/runtime/c/pgf/pgf.h +++ b/src/runtime/c/pgf/pgf.h @@ -396,14 +396,16 @@ PGF_API_DECL void pgf_iter_lins(PgfDB *db, PgfConcrRevision cnc_revision, PgfItor *itor, PgfExn *err); +typedef struct PgfPhrasetableIds PgfPhrasetableIds; + typedef struct PgfSequenceItor PgfSequenceItor; struct PgfSequenceItor { - void (*fn)(PgfSequenceItor* self, object value, PgfExn *err); + void (*fn)(PgfSequenceItor* self, size_t seq_id, object value, PgfExn *err); }; PGF_API -void pgf_iter_sequences(PgfDB *db, PgfConcrRevision cnc_revision, - PgfSequenceItor *itor, PgfExn *err); +PgfPhrasetableIds *pgf_iter_sequences(PgfDB *db, PgfConcrRevision cnc_revision, + PgfSequenceItor *itor, PgfExn *err); PGF_API_DECL void pgf_get_lincat_counts_internal(object o, size_t *counts); @@ -415,16 +417,19 @@ PGF_API_DECL size_t pgf_get_lin_get_prod_count(object o); PGF_API_DECL -PgfText *pgf_print_lindef_internal(object o, size_t i); +PgfText *pgf_print_lindef_internal(PgfPhrasetableIds *seq_ids, object o, size_t i); PGF_API_DECL -PgfText *pgf_print_linref_internal(object o, size_t i); +PgfText *pgf_print_linref_internal(PgfPhrasetableIds *seq_ids, object o, size_t i); PGF_API_DECL -PgfText *pgf_print_lin_internal(object o, size_t i); +PgfText *pgf_print_lin_internal(PgfPhrasetableIds *seq_ids, object o, size_t i); PGF_API_DECL -PgfText *pgf_print_sequence_internal(object o); +PgfText *pgf_print_sequence_internal(size_t seq_id, object o); + +PGF_API_DECL +void pgf_release_phrasetable_ids(PgfPhrasetableIds *seq_ids); PGF_API_DECL void pgf_check_expr(PgfDB *db, PgfRevision revision, diff --git a/src/runtime/c/pgf/phrasetable.cxx b/src/runtime/c/pgf/phrasetable.cxx index 15dcec72f..71f540680 100644 --- a/src/runtime/c/pgf/phrasetable.cxx +++ b/src/runtime/c/pgf/phrasetable.cxx @@ -1,5 +1,77 @@ #include "data.h" +PgfPhrasetableIds::PgfPhrasetableIds() +{ + next_id = 0; + n_pairs = 0; + pairs = NULL; + chains = NULL; +} + +void PgfPhrasetableIds::start(ref concr) +{ + next_id = 0; + n_pairs = namespace_size(concr->phrasetable); + size_t mem_size = sizeof(SeqIdPair)*n_pairs; + pairs = (SeqIdPair*) malloc(mem_size); + if (pairs == NULL) + throw pgf_systemerror(ENOMEM); + memset(pairs, 0, mem_size); +} + +size_t PgfPhrasetableIds::add(ref seq) +{ + size_t index = (seq.as_object() >> 4) % n_pairs; + if (pairs[index].seq == 0) { + pairs[index].seq = seq; + pairs[index].seq_id = next_id++; + return pairs[index].seq_id; + } else { + SeqIdChain *chain = + (SeqIdChain*) malloc(sizeof(SeqIdChain)); + if (chain == NULL) + throw pgf_systemerror(ENOMEM); + chain->next = chains; + chain->chain = pairs[index].chain; + chain->seq = seq; + chain->seq_id = next_id++; + pairs[index].chain = chain; + chains = chain; + return chain->seq_id; + } +} + +size_t PgfPhrasetableIds::get(ref seq) +{ + size_t index = (seq.as_object() >> 4) % n_pairs; + if (pairs[index].seq == seq) { + return pairs[index].seq_id; + } else { + SeqIdChain *chain = pairs[index].chain; + while (chain != NULL) { + if (chain->seq == seq) + return chain->seq_id; + chain = chain->chain; + } + throw pgf_error("Can't find sequence id"); + } +} + +void PgfPhrasetableIds::end() +{ + next_id = 0; + n_pairs = 0; + + while (chains != NULL) { + SeqIdChain *next = chains->next; + free(chains); + chains = next; + } + + free(pairs); + pairs = NULL; +} + static int lparam_cmp(PgfLParam *p1, PgfLParam *p2) { @@ -213,21 +285,22 @@ ref phrasetable_get(PgfPhrasetable table, size_t seq_id) } PGF_INTERNAL -void phrasetable_iter(PgfPhrasetable table, PgfSequenceItor* itor, size_t *p_next_id, PgfExn *err) +void phrasetable_iter(PgfPhrasetable table, PgfSequenceItor* itor, + PgfPhrasetableIds *seq_ids, PgfExn *err) { if (table == 0) return; - phrasetable_iter(table->left, itor, p_next_id, err); + phrasetable_iter(table->left, itor, seq_ids, err); if (err->type != PGF_EXN_NONE) return; - table->value->seq_id = (*p_next_id)++; - itor->fn(itor, table->value.as_object(), err); + size_t seq_id = seq_ids->add(table->value); + itor->fn(itor, seq_id, table->value.as_object(), err); if (err->type != PGF_EXN_NONE) return; - phrasetable_iter(table->right, itor, p_next_id, err); + phrasetable_iter(table->right, itor, seq_ids, err); if (err->type != PGF_EXN_NONE) return; } diff --git a/src/runtime/c/pgf/phrasetable.h b/src/runtime/c/pgf/phrasetable.h index b67182118..bbfd7116b 100644 --- a/src/runtime/c/pgf/phrasetable.h +++ b/src/runtime/c/pgf/phrasetable.h @@ -5,6 +5,41 @@ class PgfSequence; class PgfSequenceItor; typedef ref> PgfPhrasetable; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattributes" + +struct PgfPhrasetableIds { +public: + PGF_INTERNAL_DECL PgfPhrasetableIds(); + PGF_INTERNAL_DECL ~PgfPhrasetableIds() { end(); } + + PGF_INTERNAL_DECL void start(ref concr); + PGF_INTERNAL_DECL size_t add(ref seq); + PGF_INTERNAL_DECL size_t get(ref seq); + PGF_INTERNAL_DECL void end(); + +private: + size_t next_id; + + struct PGF_INTERNAL_DECL SeqIdChain; + + struct PGF_INTERNAL_DECL SeqIdPair { + SeqIdChain *chain; + ref seq; + size_t seq_id; + }; + + struct PGF_INTERNAL_DECL SeqIdChain : public SeqIdPair { + SeqIdChain *next; + }; + + size_t n_pairs; + SeqIdPair *pairs; + SeqIdChain *chains; +}; + +#pragma GCC diagnostic pop + PGF_INTERNAL_DECL PgfPhrasetable phrasetable_internalize(PgfPhrasetable table, ref *seq); @@ -12,7 +47,8 @@ PGF_INTERNAL_DECL ref phrasetable_get(PgfPhrasetable table, size_t seq_id); PGF_INTERNAL_DECL -void phrasetable_iter(PgfPhrasetable table, PgfSequenceItor* itor, size_t *p_next_id, PgfExn *err); +void phrasetable_iter(PgfPhrasetable table, PgfSequenceItor* itor, + PgfPhrasetableIds *seq_ids, PgfExn *err); PGF_INTERNAL_DECL void phrasetable_release(PgfPhrasetable table); diff --git a/src/runtime/c/pgf/printer.cxx b/src/runtime/c/pgf/printer.cxx index 7c7aba94d..eb35acfb3 100644 --- a/src/runtime/c/pgf/printer.cxx +++ b/src/runtime/c/pgf/printer.cxx @@ -575,9 +575,9 @@ void PgfPrinter::sequence(ref seq) } } -void PgfPrinter::seq_id(size_t seq_id) +void PgfPrinter::seq_id(PgfPhrasetableIds *seq_ids, ref seq) { - nprintf(5, "S%zu", seq_id); + nprintf(5, "S%zu", seq_ids->get(seq)); } void PgfPrinter::free_ref(object x) diff --git a/src/runtime/c/pgf/printer.h b/src/runtime/c/pgf/printer.h index 7207ce6e2..0d9ca0695 100644 --- a/src/runtime/c/pgf/printer.h +++ b/src/runtime/c/pgf/printer.h @@ -56,7 +56,7 @@ public: void lvar(size_t var); void lparam(ref lparam); void lvar_ranges(ref> vars); - void seq_id(size_t seqid); + void seq_id(PgfPhrasetableIds *seq_ids, ref seq); void symbol(PgfSymbol sym); void sequence(ref seq); diff --git a/src/runtime/c/pgf/reader.cxx b/src/runtime/c/pgf/reader.cxx index 611959600..0737888b5 100644 --- a/src/runtime/c/pgf/reader.cxx +++ b/src/runtime/c/pgf/reader.cxx @@ -565,7 +565,6 @@ ref PgfReader::read_seq() size_t n_syms = read_len(); ref seq = PgfDB::malloc(n_syms*sizeof(PgfSymbol)); - seq->seq_id = 0; seq->ref_count = 1; seq->syms.len = n_syms; diff --git a/src/runtime/c/pgf/writer.cxx b/src/runtime/c/pgf/writer.cxx index 23077ed3a..f1293bd18 100644 --- a/src/runtime/c/pgf/writer.cxx +++ b/src/runtime/c/pgf/writer.cxx @@ -414,7 +414,7 @@ void PgfWriter::write_symbol(PgfSymbol sym) void PgfWriter::write_seq(ref seq) { - seq->seq_id = next_seq_id++; + seq_ids.add(seq); write_vector(ref>::from_ptr(&seq->syms), &PgfWriter::write_symbol); } @@ -444,7 +444,7 @@ void PgfWriter::write_printname(ref printname) void PgfWriter::write_concrete(ref concr) { - next_seq_id = 0; + seq_ids.start(concr); write_name(&concr->name); write_namespace(concr->cflags, &PgfWriter::write_flag); @@ -452,6 +452,8 @@ void PgfWriter::write_concrete(ref concr) write_namespace(concr->lincats, &PgfWriter::write_lincat); write_namespace(concr->lins, &PgfWriter::write_lin); write_namespace(concr->printnames, &PgfWriter::write_printname); + + seq_ids.end(); } void PgfWriter::write_pgf(ref pgf) diff --git a/src/runtime/c/pgf/writer.h b/src/runtime/c/pgf/writer.h index 807330f66..4ee415fdd 100644 --- a/src/runtime/c/pgf/writer.h +++ b/src/runtime/c/pgf/writer.h @@ -45,7 +45,7 @@ public: void write_presult(ref linres); void write_symbol(PgfSymbol sym); void write_seq(ref seq); - void write_seq_id(ref> r) { write_len((*r)->seq_id); }; + void write_seq_id(ref> r) { write_len(seq_ids.get(*r)); }; void write_lin(ref lin); void write_printname(ref printname); @@ -62,10 +62,10 @@ private: void write_symbol(ref r) { write_symbol(*r); }; void write_presult(ref> r) { write_presult(*r); }; - size_t next_seq_id; - FILE *out; + ref abstract; + PgfPhrasetableIds seq_ids; }; #endif diff --git a/src/runtime/haskell/PGF2.hsc b/src/runtime/haskell/PGF2.hsc index b07772129..48d750b38 100644 --- a/src/runtime/haskell/PGF2.hsc +++ b/src/runtime/haskell/PGF2.hsc @@ -223,16 +223,19 @@ showPGF p = modifyIORef ref (\doc -> doc $$ text def) ppConcr name c = unsafePerformIO $ do - doc <- prepareSequences c -- run first to update all seq_id + (seq_ids,doc3) <- prepareSequences c -- run first to update all seq_id + doc1 <- ppLincats seq_ids c + doc2 <- ppLins seq_ids c + pgf_release_phrasetable_ids seq_ids return (text "concrete" <+> text name <+> char '{' $$ - nest 2 (ppLincats c $$ - ppLins c $$ + nest 2 (doc1 $$ + doc2 $$ (text "sequences" <+> char '{' $$ - nest 2 doc $$ + nest 2 doc3 $$ char '}')) $$ char '}') - ppLincats c = unsafePerformIO $ do + ppLincats seq_ids c = do ref <- newIORef empty (allocaBytes (#size PgfItor) $ \itor -> bracket (wrapItorCallback (getLincats ref)) freeHaskellFunPtr $ \fptr -> @@ -259,15 +262,15 @@ showPGF p = char ']') modifyIORef ref $ (\doc -> doc $$ def) forM_ (init [0..n_lindefs]) $ \i -> do - def <- bracket (pgf_print_lindef_internal val i) free $ \c_text -> do + def <- bracket (pgf_print_lindef_internal seq_ids val i) free $ \c_text -> do fmap text (peekText c_text) modifyIORef ref (\doc -> doc $$ text "lindef" <+> def) forM_ (init [0..n_linrefs]) $ \i -> do - def <- bracket (pgf_print_linref_internal val i) free $ \c_text -> do + def <- bracket (pgf_print_linref_internal seq_ids val i) free $ \c_text -> do fmap text (peekText c_text) modifyIORef ref $ (\doc -> doc $$ text "linref" <+> def) - ppLins c = unsafePerformIO $ do + ppLins seq_ids c = do ref <- newIORef empty (allocaBytes (#size PgfItor) $ \itor -> bracket (wrapItorCallback (getLins ref)) freeHaskellFunPtr $ \fptr -> @@ -280,23 +283,24 @@ showPGF p = getLins ref itor key val exn = do n_prods <- pgf_get_lin_get_prod_count val forM_ (init [0..n_prods]) $ \i -> do - def <- bracket (pgf_print_lin_internal val i) free $ \c_text -> do + def <- bracket (pgf_print_lin_internal seq_ids val i) free $ \c_text -> do fmap text (peekText c_text) modifyIORef ref (\doc -> doc $$ text "lin" <+> def) return () prepareSequences c = do ref <- newIORef empty - (allocaBytes (#size PgfSequenceItor) $ \itor -> - bracket (wrapSequenceItorCallback (getSequences ref)) freeHaskellFunPtr $ \fptr -> - withForeignPtr (c_revision c) $ \c_revision -> do - (#poke PgfSequenceItor, fn) itor fptr - withPgfExn "showPGF" (pgf_iter_sequences (a_db p) c_revision itor)) - readIORef ref + seq_ids <- (allocaBytes (#size PgfSequenceItor) $ \itor -> + bracket (wrapSequenceItorCallback (getSequences ref)) freeHaskellFunPtr $ \fptr -> + withForeignPtr (c_revision c) $ \c_revision -> do + (#poke PgfSequenceItor, fn) itor fptr + withPgfExn "showPGF" (pgf_iter_sequences (a_db p) c_revision itor)) + doc <- readIORef ref + return (seq_ids, doc) where getSequences :: IORef Doc -> SequenceItorCallback - getSequences ref itor val exn = do - def <- bracket (pgf_print_sequence_internal val) free $ \c_text -> do + getSequences ref itor seq_id val exn = do + def <- bracket (pgf_print_sequence_internal seq_id val) free $ \c_text -> do fmap text (peekText c_text) modifyIORef ref $ (\doc -> doc $$ def) diff --git a/src/runtime/haskell/PGF2/FFI.hsc b/src/runtime/haskell/PGF2/FFI.hsc index 58e10b821..502078095 100644 --- a/src/runtime/haskell/PGF2/FFI.hsc +++ b/src/runtime/haskell/PGF2/FFI.hsc @@ -46,6 +46,7 @@ data PgfLinBuilderIface data PgfLinearizationOutputIface data PgfGraphvizOptions data PgfSequenceItor +data PgfPhrasetableIds type Wrapper a = a -> IO (FunPtr a) type Dynamic a = FunPtr a -> a @@ -111,25 +112,27 @@ foreign import ccall pgf_iter_lincats :: Ptr PgfDB -> Ptr Concr -> Ptr PgfItor - foreign import ccall pgf_iter_lins :: Ptr PgfDB -> Ptr Concr -> Ptr PgfItor -> Ptr PgfExn -> IO () -type SequenceItorCallback = Ptr PgfSequenceItor -> Ptr () -> Ptr PgfExn -> IO () +type SequenceItorCallback = Ptr PgfSequenceItor -> CSize -> Ptr () -> Ptr PgfExn -> IO () foreign import ccall "wrapper" wrapSequenceItorCallback :: Wrapper SequenceItorCallback -foreign import ccall pgf_iter_sequences :: Ptr PgfDB -> Ptr Concr -> Ptr PgfSequenceItor -> Ptr PgfExn -> IO () +foreign import ccall pgf_iter_sequences :: Ptr PgfDB -> Ptr Concr -> Ptr PgfSequenceItor -> Ptr PgfExn -> IO (Ptr PgfPhrasetableIds) foreign import ccall pgf_get_lincat_counts_internal :: Ptr () -> Ptr CSize -> IO () foreign import ccall pgf_get_lincat_field_internal :: Ptr () -> CSize -> IO (Ptr PgfText) -foreign import ccall pgf_print_lindef_internal :: Ptr () -> CSize -> IO (Ptr PgfText) +foreign import ccall pgf_print_lindef_internal :: Ptr PgfPhrasetableIds -> Ptr () -> CSize -> IO (Ptr PgfText) -foreign import ccall pgf_print_linref_internal :: Ptr () -> CSize -> IO (Ptr PgfText) +foreign import ccall pgf_print_linref_internal :: Ptr PgfPhrasetableIds -> Ptr () -> CSize -> IO (Ptr PgfText) foreign import ccall pgf_get_lin_get_prod_count :: Ptr () -> IO CSize -foreign import ccall pgf_print_lin_internal :: Ptr () -> CSize -> IO (Ptr PgfText) +foreign import ccall pgf_print_lin_internal :: Ptr PgfPhrasetableIds -> Ptr () -> CSize -> IO (Ptr PgfText) -foreign import ccall pgf_print_sequence_internal :: Ptr () -> IO (Ptr PgfText) +foreign import ccall pgf_print_sequence_internal :: CSize -> Ptr () -> IO (Ptr PgfText) + +foreign import ccall pgf_release_phrasetable_ids :: Ptr PgfPhrasetableIds -> IO () type ItorCallback = Ptr PgfItor -> Ptr PgfText -> Ptr () -> Ptr PgfExn -> IO ()