core: fully keep track of parse path

This commit is contained in:
Shiz 2021-07-04 23:35:17 +02:00
parent e71cacb8f7
commit ea61dbf1e3
4 changed files with 84 additions and 32 deletions

View File

@ -25,13 +25,15 @@ class Params:
s.reset()
PathElement = U[str, int]
PathElement = U[None, str, int]
PathEntry = Tuple[PathElement, 'Type']
def format_path(path: Iterable[PathElement]) -> str:
s = ''
first = True
for p in path:
if p is None:
continue
sep = '.'
if isinstance(p, int):
p = '[' + str(p) + ']'

View File

@ -13,19 +13,29 @@ class Wrapper(G[T], Type[T]):
self.child = child
def parse(self, context: Context, stream: Stream) -> T:
return context.parse(to_type(self.child), stream)
child = to_type(self.child)
with context.enter(None, child):
return context.parse(child, stream)
def dump(self, context: Context, stream: Stream, value: O[T]) -> None:
context.dump(to_type(self.child), stream, value)
child = to_type(self.child)
with context.enter(None, child):
context.dump(child, stream, value)
def sizeof(self, context: Context, value: O[T]) -> O[int]:
return context.sizeof(to_type(self.child), value)
child = to_type(self.child)
with context.enter(None, child):
return context.sizeof(child, value)
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[T]) -> O[int]:
return context.offsetof(to_type(self.child), path, value)
child = to_type(self.child)
with context.enter(None, child):
return context.offsetof(child, path, value)
def default(self, context: Context) -> T:
return context.default(to_type(self.child))
child = to_type(self.child)
with context.enter(None, child):
return context.default(child)
def __str__(self) -> str:
return str(to_type(self.child))
@ -64,27 +74,37 @@ class Generic(G[T], Type[T], BaseExpr[T]):
def parse(self, context: Context, stream: Stream) -> T:
if not self.stack:
raise Error(context, 'unresolved generic')
return context.parse(to_type(self.stack[-1]), stream)
child = to_type(self.stack[-1])
with context.enter(None, child):
return context.parse(child, stream)
def dump(self, context: Context, stream: Stream, value: T) -> None:
if not self.stack:
raise Error(context, 'unresolved generic')
context.dump(to_type(self.stack[-1]), stream, value)
child = to_type(self.stack[-1])
with context.enter(None, child):
context.dump(child, stream, value)
def sizeof(self, context: Context, value: O[T]) -> O[int]:
if not self.stack:
return None
return context.sizeof(to_type(self.stack[-1]), value)
child = to_type(self.stack[-1])
with context.enter(None, child):
return context.sizeof(child, value)
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[T]) -> O[int]:
if not self.stack:
return None
return context.offsetof(to_type(self.stack[-1]), path, value)
child = to_type(self.stack[-1])
with context.enter(None, child):
return context.offsetof(child, path, value)
def default(self, context: Context) -> T:
if not self.stack:
raise Error(context, 'unresolved generic')
return context.default(to_type(self.stack[-1]))
child = to_type(self.stack[-1])
with context.enter(None, child):
return context.default(child)
def __str__(self) -> str:
if self.stack:

View File

@ -30,22 +30,32 @@ class Switch(G[T, V], Type[T]):
return to_type(options[selector])
def parse(self, context: Context, stream: Stream) -> T:
return context.parse(self.get_value(context), stream)
child = self.get_value(context)
with context.enter(None, child):
return context.parse(child, stream)
def dump(self, context: Context, stream: Stream, value: T) -> None:
context.dump(self.get_value(context), stream, value)
child = self.get_value(context)
with context.enter(None, child):
context.dump(child, stream, value)
def sizeof(self, context: Context, value: O[T]) -> O[Pos]:
return context.sizeof(self.get_value(context, peek=True), value)
child = self.get_value(context, peek=True)
with context.enter(None, child):
return context.sizeof(child, value)
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[T]) -> O[Pos]:
return context.offsetof(self.get_value(context, peek=True), path, value)
child = self.get_value(context, peek=True)
with context.enter(None, child):
return context.offsetof(child, path, value)
def default(self, context: Context) -> T:
return context.default(self.get_value(context, peek=True))
child = self.get_value(context, peek=True)
with context.enter(None, child):
return context.default(ChildProcessError)
def __str__(self) -> str:
return f'{format_value(self.options)}[{self.selector}]'
return f'{format_value(self.options, str)}[{self.selector}]'
def __repr__(self) -> str:
return f'{__name__}.Switch({self.options!r}, selector={self.selector!r}, default={self.default_key!r}, fallback={self.default_val!r})'
@ -58,33 +68,43 @@ class If(G[T,V], Type[U[T, V]]):
def parse(self, context: Context, stream: Stream) -> U[T, V]:
if context.get(self.cond):
return context.parse(to_type(self.true), stream)
child = to_type(self.true)
else:
return context.parse(to_type(self.false), stream)
child = to_type(self.false)
with context.enter(None, child):
return context.parse(child, stream)
def dump(self, context: Context, stream: Stream, value: U[T, V]) -> None:
if context.get(self.cond):
context.dump(to_type(self.true), stream, value)
child = to_type(self.true)
else:
context.dump(to_type(self.false), stream, value)
child = to_type(self.false)
with context.enter(None, child):
return context.dump(child, stream, value)
def sizeof(self, context: Context, value: O[U[T, V]]) -> O[Pos]:
if context.peek(self.cond):
return context.sizeof(to_type(self.true), value)
child = to_type(self.true)
else:
return context.sizeof(to_type(self.false), value)
child = to_type(self.false)
with context.enter(None, child):
return context.sizeof(child, value)
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[U[T, V]]) -> O[Pos]:
if context.peek(self.cond):
return context.offsetof(to_type(self.true), path, value)
child = to_type(self.true)
else:
return context.offsetof(to_type(self.false), path, value)
child = to_type(self.false)
with context.enter(None, child):
return context.offsetof(child, path, value)
def default(self, context: Context) -> U[T, V]:
if context.peek(self.cond):
return context.default(to_type(self.true))
child = to_type(self.true)
else:
return context.default(to_type(self.false))
child = to_type(self.false)
with context.enter(None, child):
return context.default(self.child)
def __str__(self) -> str:
return f'({self.cond} ? {self.true} : {self.false})'

View File

@ -29,25 +29,35 @@ class Transform(G[T, V], Type[V]):
self.on_repr = repr or str
def parse(self, context: Context, stream: Stream) -> V:
value = context.parse(to_type(self.child), stream)
child = to_type(self.child)
with context.enter(None, child):
value = context.parse(child, stream)
return self.on_parse(value, context) if self.context else self.on_parse(value)
def dump(self, context: Context, stream: Stream, value: V) -> None:
value = self.on_dump(value, context) if self.context else self.on_dump(value)
context.dump(to_type(self.child), stream, value)
child = to_type(self.child)
with context.enter(None, child):
context.dump(child, stream, value)
def sizeof(self, context: Context, value: O[V]) -> O[int]:
if value is not None:
value = self.on_dump(value, context) if self.context else self.on_dump(value)
return context.sizeof(to_type(self.child), value)
child = to_type(self.child)
with context.enter(None, child):
return context.sizeof(child, value)
def offsetof(self, context: Context, path: Sequence[PathElement], value: O[V]) -> O[int]:
if value is not None:
value = self.on_dump(value, context) if self.context else self.on_dump(value)
return context.offsetof(to_type(self.child), path, value)
child = to_type(self.child)
with context.enter(None, child):
return context.offsetof(child, path, value)
def default(self, context: Context) -> V:
value = context.default(to_type(self.child))
child = to_type(self.child)
with context.enter(None, child):
value = context.default(child)
return self.on_parse(value, context) if self.context else self.on_parse(value)
def __str__(self) -> str: