tracing + smarter memoization + better __str__

This commit is contained in:
AF 2021-09-06 14:20:24 +03:00
parent 874fb84957
commit 1f1700e9a8
20 changed files with 173 additions and 40 deletions

View File

@ -23,6 +23,9 @@ class AfterValue(Evaluable):
self.evaluable = self.evaluable.next() self.evaluable = self.evaluable.next()
return self return self
def __str__(self):
return f'{self.evaluable}->{self.target}'
class AVChain(AVTarget): class AVChain(AVTarget):
def __init__(self, target: AVTarget, aftertarget: AVTarget): def __init__(self, target: AVTarget, aftertarget: AVTarget):
@ -31,3 +34,6 @@ class AVChain(AVTarget):
def given(self, value: EValue) -> Evaluable: def given(self, value: EValue) -> Evaluable:
return AfterValue(self.target.given(value), self.aftertarget) return AfterValue(self.target.given(value), self.aftertarget)
def __str__(self):
return f'{self.target}->{self.aftertarget}'

View File

@ -2,13 +2,13 @@
from typing import Mapping from typing import Mapping
from bu4.evaluation.av.aftervalue import AfterValue
__all__ = ('envtype',) __all__ = ('envtype',)
from bu4.evaluation.constructs.evaluable import Evaluable
try: try:
from typing import TypeAlias from typing import TypeAlias
except ImportError: except ImportError:
TypeAlias = type TypeAlias = type
envtype: TypeAlias = Mapping[bytes, AfterValue] envtype: TypeAlias = Mapping[bytes, Evaluable]

View File

@ -2,7 +2,6 @@
from typing import Mapping, Iterator from typing import Mapping, Iterator
from bu4.evaluation.av.aftervalue import AfterValue
from bu4.evaluation.av.envtype import envtype from bu4.evaluation.av.envtype import envtype
from bu4.evaluation.constructs.evaluable import Evaluable from bu4.evaluation.constructs.evaluable import Evaluable
from bu4.evaluation.targets.avcontainer import AVContainer from bu4.evaluation.targets.avcontainer import AVContainer
@ -10,8 +9,8 @@ from bu4.evaluation.targets.avcontainer import AVContainer
__all__ = ('LambdaEnv',) __all__ = ('LambdaEnv',)
class LambdaEnv(Mapping): class LambdaEnv(Mapping[bytes, Evaluable]):
def __getitem__(self, k: bytes) -> AfterValue: def __getitem__(self, k: bytes) -> Evaluable:
if k == self.name: if k == self.name:
return self.container return self.container
else: else:
@ -20,11 +19,18 @@ class LambdaEnv(Mapping):
def __len__(self) -> int: def __len__(self) -> int:
return len(self.env) + 1 return len(self.env) + 1
def __iter__(self) -> Iterator[AfterValue]: def __iter__(self) -> Iterator[Evaluable]:
yield self.name yield self.name
yield from self.env yield from self.env
def __init__(self, env: envtype, name: bytes, evaluable: Evaluable): def __init__(self, env: envtype, name: bytes, evaluable: Evaluable, *, memoize):
self.env = env self.env = env
self.name = name self.name = name
self.container = AVContainer(evaluable).after_value self.container = AVContainer(evaluable, name).after_value if memoize else evaluable
@staticmethod
def strfy(self):
return ''.join(f'\x7b{evaluable}|{name.decode()}\x7d' for name, evaluable in self.items())
def __str__(self):
return self.strfy(self)

View File

@ -15,10 +15,12 @@ class ELambda(EValue):
self.env = env self.env = env
self.name = name self.name = name
self.value = value self.value = value
self.used = name in value.future
self.memoize = name in value.multifuture
def call(self, argument: Evaluable) -> Evaluable: def call(self, argument: Evaluable) -> Evaluable:
return ELinked( return ELinked(
LambdaEnv(self.env, self.name, argument), LambdaEnv(self.env, self.name, argument, memoize=self.memoize) if self.used else self.env,
self.value self.value
) )

View File

@ -41,6 +41,9 @@ class AntiProxy:
def __call__(self, value): def __call__(self, value):
return antiproxy(sync(self.evaluable.call(eproxy(value)))) return antiproxy(sync(self.evaluable.call(eproxy(value))))
def __str__(self):
return str(self.evaluable)
def eproxy(value: Any) -> Evaluable: def eproxy(value: Any) -> Evaluable:
if isinstance(value, Evaluable): if isinstance(value, Evaluable):

View File

@ -17,3 +17,6 @@ class AVCall(AVTarget):
def given(self, value: EValue) -> Evaluable: def given(self, value: EValue) -> Evaluable:
return value.call(ELinked(self.env, self.argument)) return value.call(ELinked(self.env, self.argument))
def __str__(self):
return f'({self.argument})'

View File

@ -9,9 +9,13 @@ __all__ = ('AVContainer',)
class AVContainer(AVTarget): class AVContainer(AVTarget):
def __init__(self, evaluable: Evaluable): def __init__(self, evaluable: Evaluable, name: bytes):
self.after_value = AfterValue(evaluable, self) self.after_value = AfterValue(evaluable, self)
self.name = name
def given(self, value: EValue) -> Evaluable: def given(self, value: EValue) -> Evaluable:
self.after_value.evaluable = value self.after_value.evaluable = value
return value return value
def __str__(self):
return f'[{self.name.decode()}]'

View File

@ -18,6 +18,11 @@ class LCall(Linked):
self.argument = argument self.argument = argument
self.lambda_ = lambda_ self.lambda_ = lambda_
self.future = self.argument.future | self.lambda_.future self.future = self.argument.future | self.lambda_.future
self.multifuture = (
self.argument.multifuture |
self.lambda_.multifuture |
(self.argument.future & self.lambda_.future)
)
def evaluable(self, env: envtype) -> Evaluable: def evaluable(self, env: envtype) -> Evaluable:
return AfterValue(ELinked(env, self.lambda_), AVCall(env, self.argument)) return AfterValue(ELinked(env, self.lambda_), AVCall(env, self.argument))

View File

@ -12,6 +12,7 @@ class LException(Linked):
def __init__(self, name: bytes): def __init__(self, name: bytes):
self.name = name self.name = name
self.future = set() self.future = set()
self.multifuture = set()
def evaluable(self, env: envtype) -> Evaluable: def evaluable(self, env: envtype) -> Evaluable:
return EException(self.name) return EException(self.name)

View File

@ -8,6 +8,7 @@ __all__ = ('Linked',)
class Linked: class Linked:
future: set[bytes] future: set[bytes]
multifuture: set[bytes]
def evaluable(self, env: envtype) -> Evaluable: def evaluable(self, env: envtype) -> Evaluable:
raise NotImplementedError raise NotImplementedError

View File

@ -14,11 +14,13 @@ class LLambda(Linked):
def __init__(self, name: bytes, value: Linked): def __init__(self, name: bytes, value: Linked):
self.name = name self.name = name
self.value = value self.value = value
self.future = self.value.future - {self.name} self.future = self.value.future - {name}
self.multifuture = self.future
self.used = name in value.future
def evaluable(self, env: envtype) -> Evaluable: def evaluable(self, env: envtype) -> Evaluable:
return ELambda( return ELambda(
{name: env[name] for name in self.future}, {name: env[name] for name in self.future} if self.used else env,
self.name, self.name,
self.value self.value
) )

View File

@ -11,6 +11,7 @@ class LName(Linked):
def __init__(self, name: bytes): def __init__(self, name: bytes):
self.name = name self.name = name
self.future = {name} self.future = {name}
self.multifuture = set()
def evaluable(self, env: envtype) -> Evaluable: def evaluable(self, env: envtype) -> Evaluable:
return env[self.name] return env[self.name]

View File

@ -11,6 +11,7 @@ __all__ = ('LNull',)
class LNull(Linked): class LNull(Linked):
def __init__(self): def __init__(self):
self.future = set() self.future = set()
self.multifuture = set()
def evaluable(self, env: envtype) -> Evaluable: def evaluable(self, env: envtype) -> Evaluable:
return ENull() return ENull()

49
bu4/tracing/probe.py Normal file
View File

@ -0,0 +1,49 @@
# Copyright (c) PARRRATE T&V 2021. All rights reserved.
from bu4.evaluation.constructs.elambda import ELambda
from bu4.evaluation.constructs.evaluable import Evaluable
from bu4.evaluation.constructs.evalue import EValue
from bu4.evaluation.sync import sync
class Probe(EValue):
def call(self, argument: Evaluable) -> Evaluable:
return ProbeB(self, argument)
def start_and_list(self):
probe = self
list_ = []
while isinstance(probe, ProbeB):
list_.append(probe.argument)
probe = probe.prev
assert isinstance(probe, ProbeA)
return probe.start, reversed(list_)
def __str__(self):
start, list_ = self.start_and_list()
return f'probe {start} [ {" ; ".join(map(str, list_))} ]'
class ProbeA(Probe):
def __init__(self, start):
self.start = start
class ProbeB(Probe):
def __init__(self, prev: Probe, argument):
self.prev = prev
self.argument = argument
_probe_index = 0
def trace(lambda_: EValue):
global _probe_index
size = 0
while True:
if not isinstance(lambda_, ELambda):
return size, lambda_
lambda_ = sync(lambda_.call(ProbeA(_probe_index)))
_probe_index += 1
size += 1

27
docs/extensions.md Normal file
View File

@ -0,0 +1,27 @@
Application (essential):
* Call
Abstraction:
* Lambda
* Name
Common:
* Null (=exception/undefined)
* Quot
* Qopn-Qcls
* Skip
Special:
* Namespaces (evaluable imports)
* String literals (exceptions)
* Static literals (constants and platform values)
* Trace/probes
* Classes (named lambda constructs)
* Methods (static types, optionally explicit)
* Factories (static types, optionally explicit)
* Await/after constructs with callbacks (and mutability/io monads)
* Speculative execution (asynchronousity and multithreading)
* Index-based linking (more static)
* Hashes (v13 extension)
* Typing decorators (v13 extension)
* Evaluable to parsed conversion (compilation inversion)

28
main.py
View File

@ -1,12 +1,13 @@
# Copyright (c) PARRRATE T&V 2021. All rights reserved. # Copyright (c) PARRRATE T&V 2021. All rights reserved.
import random import random
from collections import deque
from bu4.common_interface import with_common_interface from bu4.common_interface import with_common_interface
from bu4.evaluation.constructs.proxy import antiproxy, eproxy from bu4.evaluation.constructs.proxy import antiproxy, eproxy
from bu4.evaluation.sync import sync from bu4.evaluation.sync import sync
from bu4.parsing.toolchain.readfile import readfile from bu4.parsing.toolchain.readfile import readfile
from bu4.synced import synced from bu4.synced import synced
from bu4.tracing.probe import trace, Probe
from timesample import TimeSample from timesample import TimeSample
with TimeSample('all'): with TimeSample('all'):
@ -64,3 +65,28 @@ with TimeSample('all'):
TimeSample.print(sys1) TimeSample.print(sys1)
with TimeSample('sys4'): with TimeSample('sys4'):
TimeSample.print(with_common_interface(synced(readfile('src/sys4')))) TimeSample.print(with_common_interface(synced(readfile('src/sys4'))))
with TimeSample('sys5'):
sys5 = synced(readfile('src/sys5'))
queue = deque([(0, 0, sys5)])
for trace_index in range(1, 100 + 1):
if not queue:
break
tab, parent, evaluable = queue.popleft()
for _ in range(10000):
evaluable = evaluable.next()
_probe_index, probe = trace(evaluable)
prefix = ('.', ' ' * tab, parent, trace_index)
if isinstance(probe, Probe):
start, list_ = probe.start_and_list()
TimeSample.print(*prefix, _probe_index, probe)
queue.extend((tab + 1, trace_index, deeper_evaluable) for deeper_evaluable in list_)
else:
TimeSample.print(*prefix, '...')
with TimeSample('sys6'):
sys6 = synced(readfile('src/sys6')).call(synced('?'))
for _ in range(100):
sys6 = sys6.next()
print(sys6)
for _ in range(10000000):
sys6 = sys6.next()

View File

@ -1,26 +0,0 @@
Application (essential):
* Call
Abstraction:
* Lambda
* Name
Common:
* Null (=exception/undefined)
* Quot
* Qopn-Qcls
* Skip
Special:
* Namespaces (E- inputs)
* String literals (=exceptions)
* Trace/probes
* Classes (named lambda constructs)
* Methods (statically typed, optionally explicitly)
* Factories (statically typed, optionally explicitly)
* Await/after constructs with callbacks (and mutability/io quasimonads)
* Speculative execution (anychronousity and multithreading)
* Index-based linking (more static)
* Hashes (v13 extension)
* Bitstring call protocol (v13 extension)
* Evaluable to parsed

5
src/sys5.bu4 Normal file
View File

@ -0,0 +1,5 @@
@@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
[b3]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

17
src/sys6.bu4 Normal file
View File

@ -0,0 +1,17 @@
@@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
/(g)
(x)
/
[x]
[g]
[YC]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
(_)
/
[ID]
[YC]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
(_)
/ < (x) /[x][SC] > [SC]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""