mirror of
https://github.com/flynx/pWiki.git
synced 2026-08-24 16:26:42 +00:00
cleanup...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
60af0b4e44
commit
327693a768
@ -32,6 +32,13 @@ var pwpath = require('./path')
|
|||||||
// ...this handles the syntax and execution...
|
// ...this handles the syntax and execution...
|
||||||
var BaseParser =
|
var BaseParser =
|
||||||
module.BaseParser = {
|
module.BaseParser = {
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// Passive parsing...
|
||||||
|
//
|
||||||
|
// XXX might be a good idea to rewrite this level as an actual parser.
|
||||||
|
//
|
||||||
|
|
||||||
// patterns...
|
// patterns...
|
||||||
//
|
//
|
||||||
// The way the patterns are organized might seem a bit overcomplicated
|
// The way the patterns are organized might seem a bit overcomplicated
|
||||||
@ -534,6 +541,11 @@ module.BaseParser = {
|
|||||||
ast: function(...args){
|
ast: function(...args){
|
||||||
return [...this.group(...args)] },
|
return [...this.group(...args)] },
|
||||||
|
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
// Active parsing...
|
||||||
|
|
||||||
|
|
||||||
// Expand macros (stage I)...
|
// Expand macros (stage I)...
|
||||||
//
|
//
|
||||||
// .expand(<page>, <ast>[, <state>])
|
// .expand(<page>, <ast>[, <state>])
|
||||||
@ -574,6 +586,20 @@ module.BaseParser = {
|
|||||||
// Macros can synchronize by awaiting on local state.waitNested or
|
// Macros can synchronize by awaiting on local state.waitNested or
|
||||||
// state.waitNested they receive in state.
|
// state.waitNested they receive in state.
|
||||||
//
|
//
|
||||||
|
// If all macros are sync none of .waitAll, .waitNested or .wait are
|
||||||
|
// created.
|
||||||
|
//
|
||||||
|
// Promises:
|
||||||
|
// .waitNested
|
||||||
|
// Waits for the last non-isolated async macro, skipping
|
||||||
|
// waiting for isolated macros.
|
||||||
|
// .waitAll
|
||||||
|
// Waits for the last async macro.
|
||||||
|
// .wait
|
||||||
|
// Waits for the full AST to resolve (i.e. each promise in
|
||||||
|
// the AST is resolved).
|
||||||
|
//
|
||||||
|
//
|
||||||
// NOTE: this is always sync, but some of the items in the returned
|
// NOTE: this is always sync, but some of the items in the returned
|
||||||
// array may be promises.
|
// array may be promises.
|
||||||
// NOTE: each macro call will receive a "local" state cotaining
|
// NOTE: each macro call will receive a "local" state cotaining
|
||||||
@ -587,27 +613,11 @@ module.BaseParser = {
|
|||||||
// NOTE: .waitAll and .waitNested are "live", each updated for every
|
// NOTE: .waitAll and .waitNested are "live", each updated for every
|
||||||
// promise returned while expanding, while .wait is global and
|
// promise returned while expanding, while .wait is global and
|
||||||
// will resolve only when all other promises are resolved.
|
// will resolve only when all other promises are resolved.
|
||||||
|
// NOTE: macro-local state is forgotten as soon as the macro returns,
|
||||||
|
// thus if a macro wants to store state it should either store
|
||||||
|
// it in state.parent or state.root.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// XXX the parser is always sync
|
|
||||||
// - macros always return sync but can be resolved or not resolved
|
|
||||||
// - each level is always sequential
|
|
||||||
// - isolated macros can be resolved in any order
|
|
||||||
// - macros can wait on:
|
|
||||||
// - nested
|
|
||||||
// e.g. a @var needs all the previous @var's to resolve
|
|
||||||
// but does not care about isolated @include's
|
|
||||||
// - full
|
|
||||||
// a full include needs all nesteds to resolve, both
|
|
||||||
// isolated and not
|
|
||||||
// - first nested item in one macro waits for last relevant
|
|
||||||
// nested item in previous macro -> i.e. for previous
|
|
||||||
// macro to resolve in a relevant way...
|
|
||||||
// - everything returns an ast
|
|
||||||
// - callbacks/events/handlers to trigger on specific macro
|
|
||||||
// resolution
|
|
||||||
//
|
|
||||||
// XXX Q: do we need generators?
|
|
||||||
// XXX Handle errors...
|
// XXX Handle errors...
|
||||||
expand: function(page, ast, state={}, nested_handlers={}){
|
expand: function(page, ast, state={}, nested_handlers={}){
|
||||||
var that = this
|
var that = this
|
||||||
@ -617,6 +627,14 @@ module.BaseParser = {
|
|||||||
ast
|
ast
|
||||||
: ast.iter()
|
: ast.iter()
|
||||||
|
|
||||||
|
var cleanup = function(state, wait, val){
|
||||||
|
if(state[wait] === val){
|
||||||
|
if(!('root' in state)
|
||||||
|
|| state.root === state){
|
||||||
|
delete state[wait]
|
||||||
|
} else {
|
||||||
|
state[wait] = undefined } } }
|
||||||
|
|
||||||
var elems = []
|
var elems = []
|
||||||
for(let elem of ast){
|
for(let elem of ast){
|
||||||
|
|
||||||
@ -666,6 +684,8 @@ module.BaseParser = {
|
|||||||
// each macro can wait async for an arbitrary amount of
|
// each macro can wait async for an arbitrary amount of
|
||||||
// time it only should care about what was promised
|
// time it only should care about what was promised
|
||||||
// before it neglecting what came after.
|
// before it neglecting what came after.
|
||||||
|
// NOTE: this also enables nested namespaces but the current
|
||||||
|
// macros do not use this.
|
||||||
var res =
|
var res =
|
||||||
that.callMacro(page, name, args, body, {
|
that.callMacro(page, name, args, body, {
|
||||||
// global/parent state...
|
// global/parent state...
|
||||||
@ -682,36 +702,17 @@ module.BaseParser = {
|
|||||||
elem.resolving = res
|
elem.resolving = res
|
||||||
|
|
||||||
let all, nested
|
let all, nested
|
||||||
// XXX if res is not started yet and it has not yet
|
|
||||||
// started waiting for .waitAll this can be a
|
|
||||||
// condition for a dead lock:
|
|
||||||
// res -> .waitAll -> res
|
|
||||||
all = state.waitAll =
|
all = state.waitAll =
|
||||||
Promise.all([state.waitAll, res])
|
Promise.all([state.waitAll, res])
|
||||||
// XXX do we need to wait till the last .waitNested is
|
|
||||||
// resolved?
|
|
||||||
// ...should it's handlers complete??
|
|
||||||
// XXX can this be controlled by the macro???
|
|
||||||
// ...one way to do in is to ger pass a resolve(..)
|
|
||||||
// func to the macro...
|
|
||||||
// ...do we need this?
|
|
||||||
if(!res.isolated){
|
if(!res.isolated){
|
||||||
nested = state.waitNested =
|
nested = state.waitNested =
|
||||||
Promise.all([state.waitNested, res]) }
|
Promise.all([state.waitNested, res]) }
|
||||||
res.then(
|
res.then(
|
||||||
function(value){
|
function(value){
|
||||||
if(state.waitAll === all){
|
cleanup(state, 'waitAll', all)
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
cleanup(state, 'waitNested', nested)
|
||||||
state.waitAll = undefined }
|
|
||||||
//delete state.waitAll }
|
|
||||||
if(state.waitNested === nested){
|
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
|
||||||
state.waitNested = undefined }
|
|
||||||
//delete state.waitNested }
|
|
||||||
delete elem.resolving
|
delete elem.resolving
|
||||||
elem.value = value
|
elem.value = value
|
||||||
// XXX should we resolve to value or elem???
|
|
||||||
// ...elem seems more consistent...
|
|
||||||
return value },
|
return value },
|
||||||
function(err){
|
function(err){
|
||||||
state.errors ??= []
|
state.errors ??= []
|
||||||
@ -730,27 +731,16 @@ module.BaseParser = {
|
|||||||
state.waitAll
|
state.waitAll
|
||||||
&& state.waitAll
|
&& state.waitAll
|
||||||
.then(function(){
|
.then(function(){
|
||||||
// only cleanup our own mess =)
|
cleanup(state, 'waitAll', waitAll) })
|
||||||
waitAll === state.waitAll
|
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
|
||||||
&& (state.waitAll = undefined) })
|
|
||||||
//&& (delete state.waitAll) })
|
|
||||||
&& (wait = state.wait = waitAll
|
&& (wait = state.wait = waitAll
|
||||||
.then(function(){
|
.then(function(){
|
||||||
wait === state.wait
|
cleanup(state, 'wait', wait)
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
|
||||||
&& (state.wait = null)
|
|
||||||
//&& (delete state.wait)
|
|
||||||
return elems }))
|
return elems }))
|
||||||
var waitNested = state.waitNested
|
var waitNested = state.waitNested
|
||||||
state.waitNested
|
state.waitNested
|
||||||
&& state.waitNested
|
&& state.waitNested
|
||||||
.then(function(){
|
.then(function(){
|
||||||
// only cleanup our own mess =)
|
cleanup(state, 'waitNested', waitNested) })
|
||||||
waitNested === state.waitNested
|
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
|
||||||
&& (state.waitNested = undefined) })
|
|
||||||
//&& (delete state.waitNested) })
|
|
||||||
|
|
||||||
return elems },
|
return elems },
|
||||||
|
|
||||||
@ -767,34 +757,6 @@ module.BaseParser = {
|
|||||||
// NOTE: to fully resolve the ast this may need to be called several
|
// NOTE: to fully resolve the ast this may need to be called several
|
||||||
// times...
|
// times...
|
||||||
//
|
//
|
||||||
//
|
|
||||||
// XXX can we prevent reaces over state.unresolved???
|
|
||||||
// it can be deleted when calling .exec(..) / .execNested(..)
|
|
||||||
// while parsing, for example from within a macro...
|
|
||||||
// XXX this somehow blocks the execution of .expand(..)
|
|
||||||
// This fullly runs:
|
|
||||||
// .expand(.., '@echo(A)@source(/async/echo)@echo(B)@include(/async/echo)@echo(C)', ..)
|
|
||||||
// printing:
|
|
||||||
// ---- A
|
|
||||||
// -- A
|
|
||||||
// ---- B
|
|
||||||
// ---- C
|
|
||||||
// ---- Page
|
|
||||||
// -- Page
|
|
||||||
// ---- Page
|
|
||||||
// -- B
|
|
||||||
// -- Page
|
|
||||||
// -- C
|
|
||||||
// This blocks:
|
|
||||||
// .resolve(.., '@echo(A)@source(/async/echo)@echo(B)@include(/async/echo)@echo(C)', ..)
|
|
||||||
// printing:
|
|
||||||
// ---- A
|
|
||||||
// -- A
|
|
||||||
// ---- B
|
|
||||||
// ---- C
|
|
||||||
// ...looks like we are still getting a deadlock...
|
|
||||||
// -> the issue seems to be in a nested call to .execNested(..) -> .finalize(..)
|
|
||||||
// XXX make this an actual test...
|
|
||||||
resolve: function(page, ast, state={}, nested_handlers={}){
|
resolve: function(page, ast, state={}, nested_handlers={}){
|
||||||
var that = this
|
var that = this
|
||||||
ast = typeof(ast) != 'object' ?
|
ast = typeof(ast) != 'object' ?
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user