tracing + smarter memoization + better __str__
This commit is contained in:
parent
874fb84957
commit
1f1700e9a8
@ -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}'
|
||||||
|
@ -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]
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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})'
|
||||||
|
@ -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()}]'
|
||||||
|
@ -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))
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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]
|
||||||
|
@ -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
49
bu4/tracing/probe.py
Normal 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
27
docs/extensions.md
Normal 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
28
main.py
@ -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()
|
||||||
|
@ -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
5
src/sys5.bu4
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@@
|
||||||
|
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
[b3]
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
17
src/sys6.bu4
Normal file
17
src/sys6.bu4
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@@
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
/(g)
|
||||||
|
(x)
|
||||||
|
/
|
||||||
|
[x]
|
||||||
|
[g]
|
||||||
|
[YC]
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
(_)
|
||||||
|
/
|
||||||
|
[ID]
|
||||||
|
[YC]
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
(_)
|
||||||
|
/ < (x) /[x][SC] > [SC]
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
Loading…
Reference in New Issue
Block a user