initial commit

This commit is contained in:
AF 2021-07-24 02:34:37 +03:00
commit ecdda4f059
72 changed files with 1755 additions and 0 deletions

221
.gitignore vendored Normal file
View File

@ -0,0 +1,221 @@
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

10
.idea/builtup4.iml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,51 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="DuplicatedCode" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="HtmlUnknownTag" enabled="true" level="WARNING" enabled_by_default="true">
<option name="myValues">
<value>
<list size="11">
<item index="0" class="java.lang.String" itemvalue="nobr" />
<item index="1" class="java.lang.String" itemvalue="noembed" />
<item index="2" class="java.lang.String" itemvalue="comment" />
<item index="3" class="java.lang.String" itemvalue="noscript" />
<item index="4" class="java.lang.String" itemvalue="embed" />
<item index="5" class="java.lang.String" itemvalue="script" />
<item index="6" class="java.lang.String" itemvalue="markdown" />
<item index="7" class="java.lang.String" itemvalue="sv3i" />
<item index="8" class="java.lang.String" itemvalue="sv3o" />
<item index="9" class="java.lang.String" itemvalue="sv3a" />
<item index="10" class="java.lang.String" itemvalue="sv3c" />
</list>
</value>
</option>
<option name="myCustomValuesEnabled" value="true" />
</inspection_tool>
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="nacl" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="PySide2.QtWidgets.clicked.connect" />
<option value="PySide2.QtWidgets.valueChanged.connect" />
<option value="PySide2.QtWidgets.textChanged.connect" />
<option value="PySide2.QtCore.Signal.emit" />
<option value="PySide2.QtCore.Signal.connect" />
</list>
</option>
</inspection_tool>
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

4
.idea/misc.xml Normal file
View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (builtup4)" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/builtup4.iml" filepath="$PROJECT_DIR$/.idea/builtup4.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

8
bu4/codes.py Normal file
View File

@ -0,0 +1,8 @@
CODE_NULL = 0
CODE_CALL = 1
CODE_MAKE = 2
CODE_NAME = 3
CODE_SKIP = 4
CODE_QUOT = 5
CODE_QOPN = 6
CODE_QCLS = 7

View File

@ -0,0 +1,50 @@
import abc
from typing import Mapping
from bu4.evaluation.evaluable import Evaluable
try:
from typing import TypeAlias
except ImportError:
TypeAlias = type
envtype: TypeAlias = Mapping[bytes, 'AfterValue']
class AVTarget:
def given(self, value: 'EValue') -> Evaluable:
raise NotImplementedError
class AfterValue(Evaluable):
def __init__(self, evaluable: Evaluable, target: AVTarget):
self.evaluable = evaluable
self.target = target
def next(self) -> 'Evaluable':
if isinstance(self.evaluable, EValue):
if isinstance(self.target, AVAV):
self.evaluable, self.target = self.target.target.given(self.evaluable), self.target.aftertarget
return self
return self.target.given(self.evaluable)
if isinstance(self.evaluable, AfterValue):
self.evaluable, self.target = self.evaluable.evaluable, AVAV(self.evaluable.target, self.target)
self.evaluable = self.evaluable.next()
return self
class AVAV(AVTarget):
def __init__(self, target: AVTarget, aftertarget: AVTarget):
self.target = target
self.aftertarget = aftertarget
def given(self, value: 'EValue') -> Evaluable:
return AfterValue(self.target.given(value), self.aftertarget)
class EValue(Evaluable, abc.ABC):
def next(self) -> 'EValue':
return self
def call(self, argument: Evaluable) -> Evaluable:
raise NotImplementedError

14
bu4/evaluation/avcall.py Normal file
View File

@ -0,0 +1,14 @@
from bu4.evaluation.elinked import ELinked
from bu4.parsing.linked import Linked
from bu4.evaluation.aftervalue import Evaluable, EValue, AVTarget, envtype
__all__ = ('AVCall',)
class AVCall(AVTarget):
def __init__(self, env: envtype, argument: Linked):
self.env = env
self.argument = argument
def given(self, value: EValue) -> Evaluable:
return value.call(ELinked(self.env, self.argument))

View File

@ -0,0 +1,10 @@
from bu4.evaluation.aftervalue import EValue, AfterValue, Evaluable, AVTarget
class AVContainer(AVTarget):
def __init__(self, evaluable: Evaluable):
self.after_value = AfterValue(evaluable, self)
def given(self, value: EValue) -> Evaluable:
self.after_value.evaluable = value
return value

22
bu4/evaluation/elambda.py Normal file
View File

@ -0,0 +1,22 @@
from bu4.evaluation.elinked import ELinked
from bu4.evaluation.lambdaenv import LambdaEnv
from bu4.parsing.linked import Linked
from bu4.evaluation.aftervalue import EValue, envtype, Evaluable
__all__ = ('ELambda',)
class ELambda(EValue):
def __init__(self, env: envtype, name: bytes, value: Linked):
self.env = env
self.name = name
self.value = value
def call(self, argument: Evaluable) -> Evaluable:
return ELinked(
LambdaEnv(self.env, self.name, argument),
self.value
)
def __str__(self):
return f'({self.name.decode()}){self.value}'

14
bu4/evaluation/elinked.py Normal file
View File

@ -0,0 +1,14 @@
from bu4.parsing.linked import Linked
from bu4.evaluation.aftervalue import Evaluable, envtype
class ELinked(Evaluable):
def __init__(self, env: envtype, linked: Linked):
self.env = env
self.linked = linked
def next(self) -> Evaluable:
return self.linked.evaluable(self.env)
def __str__(self):
return f'{self.linked}'

11
bu4/evaluation/enull.py Normal file
View File

@ -0,0 +1,11 @@
from bu4.evaluation.aftervalue import EValue, Evaluable
__all__ = ('ENull',)
class ENull(EValue):
def call(self, argument: Evaluable) -> Evaluable:
return self
def __str__(self):
return f'?'

View File

@ -0,0 +1,3 @@
class Evaluable:
def next(self) -> 'Evaluable':
raise NotImplementedError

View File

@ -0,0 +1,24 @@
from typing import Mapping, Iterator
from bu4.evaluation.avcontainer import AVContainer
from bu4.evaluation.aftervalue import AfterValue, envtype, Evaluable
class LambdaEnv(Mapping):
def __getitem__(self, k: bytes) -> AfterValue:
if k == self.name:
return self.container
else:
return self.env[k]
def __len__(self) -> int:
return len(self.env) + 1
def __iter__(self) -> Iterator[AfterValue]:
yield self.name
yield from self.env
def __init__(self, env: envtype, name: bytes, evaluable: Evaluable):
self.env = env
self.name = name
self.container = AVContainer(evaluable).after_value

51
bu4/evaluation/proxy.py Normal file
View File

@ -0,0 +1,51 @@
from typing import Any
from bu4.evaluation.aftervalue import AVTarget, EValue, Evaluable, AfterValue
from bu4.toolchain.sync import sync
class AVProxyCall(AVTarget):
def __init__(self, value: Any):
self.value = value
def given(self, value: EValue) -> Evaluable:
if isinstance(value, EProxy):
return eproxy(self.value(value.value))
else:
return eproxy(self.value(antiproxy(value)))
class EProxy(EValue):
def __init__(self, value: Any):
super().__init__()
self.value = value
def call(self, value: Evaluable) -> Evaluable:
return AfterValue(value, AVProxyCall(self.value))
def __str__(self):
return str(self.value)
class AntiProxy:
def __init__(self, evaluable: EValue):
self.evaluable = evaluable
def __call__(self, value):
return antiproxy(sync(self.evaluable.call(eproxy(value))))
def eproxy(value: Any) -> Evaluable:
if isinstance(value, Evaluable):
return value
elif isinstance(value, AntiProxy):
return value.evaluable
else:
return EProxy(value)
def antiproxy(evaluable: EValue):
if isinstance(evaluable, EProxy):
return evaluable.value
else:
return AntiProxy(evaluable)

View File

@ -0,0 +1,8 @@
from bu4.linking.altarget import ALTarget
from bu4.parsing.linked import LinkingState
class AfterLinking(LinkingState):
def __init__(self, state: LinkingState, target: ALTarget):
self.state = state
self.target = target

12
bu4/linking/alal.py Normal file
View File

@ -0,0 +1,12 @@
from bu4.linking.afterlinking import AfterLinking
from bu4.linking.altarget import ALTarget
from bu4.parsing.linked import Linked, LinkingState
class ALAL(ALTarget):
def __init__(self, target: ALTarget, aftertarget: ALTarget):
self.target = target
self.aftertarget = aftertarget
def given(self, linked: Linked) -> LinkingState:
return AfterLinking(self.target.given(linked), self.aftertarget)

12
bu4/linking/allambda.py Normal file
View File

@ -0,0 +1,12 @@
from typing import Callable
from bu4.linking.altarget import ALTarget
from bu4.parsing.linked import Linked, LinkingState
class ALLambda(ALTarget):
def __init__(self, lambda_: Callable[[Linked], LinkingState]):
self.lambda_ = lambda_
def given(self, linked: Linked) -> LinkingState:
return self.lambda_(linked)

6
bu4/linking/altarget.py Normal file
View File

@ -0,0 +1,6 @@
from bu4.parsing.linked import Linked, LinkingState
class ALTarget:
def given(self, linked: Linked) -> LinkingState:
raise NotImplementedError

View File

@ -0,0 +1,6 @@
from bu4.parsing.linked import LinkingState, Linked
class LinkingFinished(LinkingState):
def __init__(self, linked: Linked):
self.linked = linked

View File

@ -0,0 +1,7 @@
from bu4.parsing.linked import LinkingState, Parsed
class LinkingParsed(LinkingState):
def __init__(self, promise: set[bytes], parsed: Parsed):
self.promise = promise
self.parsed = parsed

60
bu4/parsing/lcall.py Normal file
View File

@ -0,0 +1,60 @@
from bu4.codes import CODE_CALL
from bu4.evaluation.avcall import AVCall
from bu4.evaluation.elinked import ELinked
from bu4.linking.afterlinking import AfterLinking
from bu4.linking.allambda import ALLambda
from bu4.parsing.linked import Linked, Parsed, LinkingState
from bu4.linking.linkingfinished import LinkingFinished
from bu4.linking.linkingparsed import LinkingParsed
from bu4.evaluation.aftervalue import envtype, Evaluable, AfterValue
__all__ = ('LCall', 'PCall',)
class LCall(Linked):
argument: Linked
lambda_: Linked
def __init__(self, promise: set[bytes], argument: Parsed, lambda_: Parsed):
self.promise = promise
self._argument = argument
self._lambda = lambda_
def link(self) -> LinkingState:
return AfterLinking(
LinkingParsed(self.promise, self._argument),
ALLambda(self._given_argument)
)
def _given_argument(self, argument: Linked) -> LinkingState:
self.argument = argument
return AfterLinking(
LinkingParsed(self.promise, self._lambda),
ALLambda(self._given_lambda)
)
def _given_lambda(self, lambda_) -> LinkingState:
self.lambda_ = lambda_
self.future = self.argument.future | self.lambda_.future
return LinkingFinished(self)
def evaluable(self, env: envtype) -> Evaluable:
return AfterValue(ELinked(env, self.lambda_), AVCall(env, self.argument))
def __str__(self):
return f'/{self.argument}{self.lambda_}'
def unlink(self) -> Parsed:
return PCall(self._argument, self._lambda)
class PCall(Parsed):
def __init__(self, value: Parsed, lambda_: Parsed):
self.value = value
self.lambda_ = lambda_
def link(self, promise: set[bytes]) -> Linked:
return LCall(promise, self.value, self.lambda_)
def __bytes__(self):
return bytes([CODE_CALL, *bytes(self.value), *bytes(self.lambda_)])

29
bu4/parsing/linked.py Normal file
View File

@ -0,0 +1,29 @@
from bu4.evaluation.aftervalue import envtype, Evaluable
class LinkingState:
pass
class Linked:
future: set[bytes]
def link(self) -> LinkingState:
raise NotImplementedError
def evaluable(self, env: envtype) -> Evaluable:
raise NotImplementedError
def unlink(self) -> 'Parsed':
raise NotImplementedError
def __bytes__(self):
return bytes(self.unlink())
class Parsed:
def link(self, promise: set[bytes]) -> Linked:
raise NotImplementedError
def __bytes__(self):
raise NotImplementedError

53
bu4/parsing/llambda.py Normal file
View File

@ -0,0 +1,53 @@
from bu4.codes import CODE_MAKE, CODE_NULL
from bu4.evaluation.elambda import ELambda
from bu4.linking.afterlinking import AfterLinking
from bu4.linking.allambda import ALLambda
from bu4.parsing.linked import Linked, Parsed, LinkingState
from bu4.linking.linkingfinished import LinkingFinished
from bu4.linking.linkingparsed import LinkingParsed
from bu4.evaluation.aftervalue import envtype, Evaluable
__all__ = ('LLambda', 'PLambda',)
class LLambda(Linked):
value: Linked
def __init__(self, promise: set[bytes], name: bytes, value: Parsed):
assert name not in promise, f'overloaded: {name}'
self.promise = promise
self.name = name
self._value = value
def link(self) -> LinkingState:
return AfterLinking(LinkingParsed(self.promise | {self.name}, self._value), ALLambda(self._given_value))
def _given_value(self, value: Linked) -> LinkingState:
self.value = value
self.future = self.value.future - {self.name}
return LinkingFinished(self)
def evaluable(self, env: envtype) -> Evaluable:
return ELambda(
{name: container for name, container in env.items() if name in self.future},
self.name,
self.value
)
def __str__(self):
return f'({self.name.decode()}){self.value}'
def unlink(self) -> Parsed:
return PLambda(self.name, self._value)
class PLambda(Parsed):
def __init__(self, name: bytes, value: Parsed):
self.name = name
self.value = value
def link(self, promise: set[bytes]) -> Linked:
return LLambda(promise, self.name, self.value)
def __bytes__(self):
return bytes([CODE_MAKE, *self.name, CODE_NULL, *bytes(self.value)])

37
bu4/parsing/lname.py Normal file
View File

@ -0,0 +1,37 @@
from bu4.codes import CODE_NAME, CODE_NULL
from bu4.parsing.linked import Linked, LinkingState, Parsed
from bu4.linking.linkingfinished import LinkingFinished
from bu4.evaluation.aftervalue import envtype, Evaluable
__all__ = ('LName', 'PName',)
class LName(Linked):
def __init__(self, promise: set[bytes], name: bytes):
assert name in promise, f'undefined: {name}'
self.name = name
self.future = {name}
def link(self) -> LinkingState:
return LinkingFinished(self)
def evaluable(self, env: envtype) -> Evaluable:
return env[self.name]
def __str__(self):
return f'[{self.name.decode()}]'
def unlink(self) -> Parsed:
return PName(self.name)
class PName(Parsed):
def __init__(self, name: bytes):
self.name = name
def link(self, promise: set[bytes]) -> Linked:
return LName(promise, self.name)
def __bytes__(self):
return bytes([CODE_NAME, *self.name, CODE_NULL])

33
bu4/parsing/lnull.py Normal file
View File

@ -0,0 +1,33 @@
from bu4.evaluation.enull import ENull
from bu4.codes import CODE_NULL
from bu4.parsing.linked import Linked, LinkingState, Parsed
from bu4.linking.linkingfinished import LinkingFinished
from bu4.evaluation.aftervalue import envtype, Evaluable
__all__ = ('LNull', 'PNull',)
class LNull(Linked):
def __init__(self):
self.future = set()
def link(self) -> LinkingState:
return LinkingFinished(self)
def evaluable(self, env: envtype) -> Evaluable:
return ENull()
def __str__(self):
return '?'
def unlink(self) -> Parsed:
return PNull()
class PNull(Parsed):
def link(self, promise: set[bytes]) -> 'Linked':
return LNull()
def __bytes__(self):
return bytes([CODE_NULL])

141
bu4/parsing/parser.py Normal file
View File

@ -0,0 +1,141 @@
from io import BytesIO
from typing import Callable
from bu4.parsing.linked import Parsed
from bu4.parsing.lname import PName
from bu4.codes import CODE_NULL, CODE_CALL, CODE_MAKE, CODE_NAME, CODE_SKIP, CODE_QUOT, CODE_QOPN, CODE_QCLS
from bu4.parsing.lcall import PCall
from bu4.parsing.lnull import PNull
from bu4.parsing.llambda import PLambda
class ParseState:
pass
class PSRead(ParseState):
pass
class PSFinal(ParseState):
def __init__(self, parsed: Parsed):
self.parsed = parsed
class PSATarget:
def given(self, parsed: Parsed) -> ParseState:
raise NotImplementedError
class PSAfter(ParseState):
def __init__(self, state, target: PSATarget):
self.state = state
self.target = target
class PSAA(PSATarget):
def __init__(self, target: PSATarget, aftertarget: PSATarget):
self.target = target
self.aftertarget = aftertarget
def given(self, parsed: Parsed) -> ParseState:
return PSAfter(self.target.given(parsed), self.aftertarget)
class PSALambda(PSATarget):
def __init__(self, lambda_: Callable[[Parsed], ParseState]):
self.lambda_ = lambda_
def given(self, parsed: Parsed) -> ParseState:
return self.lambda_(parsed)
class PSAEndsWith(PSATarget):
def __init__(self, parser: 'Parser', c: int, msg: str):
self.parser = parser
self.c = c
self.msg = msg
def given(self, parsed: Parsed) -> ParseState:
assert self.parser.read() == self.c, self.msg
return PSFinal(parsed)
_apacall = PSAfter(
PSRead(),
PSALambda(
lambda argument: PSAfter(
PSRead(),
PSALambda(
lambda lambda_: PSFinal(
PCall(
argument,
lambda_
)
)
)
)
)
)
class Parser:
def __init__(self, s: bytes):
self.__s = BytesIO(s)
def read(self) -> int:
bytes_ = self.__s.read(1)
return bytes_[0] if bytes_ else 0
def parse_name(self) -> bytes:
s = BytesIO()
while True:
c = self.read()
if not c:
return s.getvalue()
s.write(bytes([c]))
def _state_read(self, state: PSAfter):
c = self.read()
if c == CODE_NULL:
state.state = PSFinal(PNull())
elif c == CODE_CALL:
state.state = _apacall
elif c == CODE_MAKE:
state.state = (lambda name: PSAfter(
PSRead(),
PSALambda(
lambda value: PSFinal(PLambda(name, value))
)
))(self.parse_name())
elif c == CODE_NAME:
state.state = PSFinal(PName(self.parse_name()))
elif c == CODE_SKIP:
pass
elif c == CODE_QUOT:
state.target = PSAA(PSAEndsWith(self, CODE_QUOT, "quot expected"), state.target)
elif c == CODE_QOPN:
state.target = PSAA(PSAEndsWith(self, CODE_QCLS, "qcls expected"), state.target)
else:
raise ValueError(f"unknown control: {hex(c)}")
return state
def _state_next(self, state: PSAfter):
if isinstance(state.state, PSAfter):
state.state, state.target = state.state.state, PSAA(state.state.target, state.target)
elif isinstance(state.state, PSFinal):
state = state.target.given(state.state.parsed)
elif isinstance(state.state, PSRead):
state = self._state_read(state)
return state
def parse(self) -> Parsed:
state = PSAfter(PSRead(), PSALambda(lambda parsed: PSFinal(parsed)))
while True:
if isinstance(state, PSFinal):
return state.parsed
elif isinstance(state, PSAfter):
state = self._state_next(state)
else:
raise TypeError

10
bu4/toolchain/elinked.py Normal file
View File

@ -0,0 +1,10 @@
from bu4.evaluation.elinked import ELinked
from bu4.parsing.linked import Parsed
from bu4.evaluation.aftervalue import envtype
from bu4.toolchain.prepare import prepare
def elinked(env: envtype, parsed: Parsed):
linked = parsed.link(set(env))
prepare(linked)
return ELinked(env, linked)

6
bu4/toolchain/parse.py Normal file
View File

@ -0,0 +1,6 @@
from bu4.parsing.linked import Parsed
from bu4.parsing.parser import Parser
def parse(source: bytes) -> Parsed:
return Parser(source).parse()

28
bu4/toolchain/prepare.py Normal file
View File

@ -0,0 +1,28 @@
from bu4.linking.afterlinking import AfterLinking
from bu4.linking.alal import ALAL
from bu4.parsing.linked import LinkingState, Linked
from bu4.linking.linkingfinished import LinkingFinished
from bu4.linking.linkingparsed import LinkingParsed
def _afterlinking_iteration(state: AfterLinking) -> LinkingState:
if isinstance(state.state, LinkingFinished):
state = state.target.given(state.state.linked)
elif isinstance(state.state, AfterLinking):
state.state, state.target = state.state.state, ALAL(state.state.target, state.target)
elif isinstance(state.state, LinkingParsed):
state.state = state.state.parsed.link(state.state.promise).link()
else:
raise TypeError
return state
def prepare(linked: Linked) -> Linked:
state = linked.link()
while True:
if isinstance(state, LinkingFinished):
return state.linked
elif isinstance(state, AfterLinking):
state = _afterlinking_iteration(state)
else:
raise TypeError

13
bu4/toolchain/readfile.py Normal file
View File

@ -0,0 +1,13 @@
import os
from io import StringIO
def readfile(path: str) -> str:
srcio = StringIO()
with open(path + '.bu4') as file:
for line in file:
if line.startswith('@'):
srcio.write(readfile(os.path.join(path, '..', line.removeprefix('@').strip())))
else:
srcio.write(line)
return srcio.getvalue()

8
bu4/toolchain/sync.py Normal file
View File

@ -0,0 +1,8 @@
from bu4.evaluation.aftervalue import Evaluable, EValue
def sync(evaluable: Evaluable) -> EValue:
while True:
if isinstance(evaluable, EValue):
return evaluable
evaluable = evaluable.next()

12
bu4/toolchain/synced.py Normal file
View File

@ -0,0 +1,12 @@
from bu4.evaluation.aftervalue import EValue
from bu4.toolchain.elinked import elinked
from bu4.toolchain.parse import parse
from bu4.toolchain.sync import sync
from bu4.toolchain.transply import transply
def synced(source: str) -> EValue:
bsource = transply(source)
parsed = parse(bsource)
evaluable = elinked({}, parsed)
return sync(evaluable)

38
bu4/toolchain/transply.py Normal file
View File

@ -0,0 +1,38 @@
from io import BytesIO
from bu4.codes import CODE_CALL, CODE_QOPN, CODE_MAKE, CODE_QCLS, CODE_NULL, CODE_SKIP, CODE_NAME, CODE_QUOT
def transply(source: str) -> bytes:
b = BytesIO()
for c in source:
if c.isspace():
pass
elif c in '/':
b.write(bytes([CODE_CALL]))
elif c in '{':
b.write(bytes([CODE_CALL, CODE_QOPN]))
elif c in '(':
b.write(bytes([CODE_MAKE]))
elif c in '|':
b.write(bytes([CODE_QCLS, CODE_MAKE]))
elif c in '})':
b.write(bytes([CODE_NULL]))
elif c in '#':
b.write(bytes([CODE_SKIP]))
elif c in '?':
b.write(bytes([CODE_QOPN, CODE_NULL, CODE_QCLS]))
elif c in ']':
b.write(bytes([CODE_NULL, CODE_QCLS]))
elif c in '[':
b.write(bytes([CODE_QOPN, CODE_NAME]))
elif c in '"':
b.write(bytes([CODE_QUOT]))
elif c in '<':
b.write(bytes([CODE_QOPN]))
elif c in '>':
b.write(bytes([CODE_QCLS]))
else:
value = c.encode()
b.write(value if len(value) == 1 else value.hex().encode())
return b.getvalue()

17
bu4/utils.py Normal file
View File

@ -0,0 +1,17 @@
from bu4.evaluation.proxy import eproxy
from bu4.evaluation.aftervalue import EValue
from bu4.toolchain.sync import sync
def to_bool(_01):
return _01(True)(False)
def with_common_interface(value: EValue):
value = sync(value.call(eproxy(0)))
value = sync(value.call(eproxy(1)))
value = sync(value.call(eproxy(lambda a: lambda b: a + b)))
value = sync(value.call(eproxy(lambda n: lambda x: lambda y: x if n == 0 else y)))
value = sync(value.call(eproxy(lambda n: lambda x: lambda y: x if n & 1 else y)))
value = sync(value.call(eproxy(lambda n: n >> 1)))
return value

51
main.py Normal file
View File

@ -0,0 +1,51 @@
from bu4.evaluation.proxy import antiproxy, eproxy
from bu4.toolchain.readfile import readfile
from bu4.toolchain.sync import sync
from bu4.toolchain.synced import synced
from bu4.utils import with_common_interface
from timesample import TimeSample
with TimeSample(' compilation'):
sys0 = synced(readfile('src/sys0'))
with TimeSample(' first, AP'):
print(
antiproxy(sys0)(0)(1)(
lambda a: lambda b: a + b
)(
lambda n: lambda x: lambda y: x if n == 0 else y
)(
lambda n: lambda x: lambda y: x if n & 1 else y
)(
lambda n: n >> 1
)
)
with TimeSample(' second, AP'):
print(
antiproxy(sys0)(0)(1)(
lambda a: lambda b: a + b
)(
lambda n: lambda x: lambda y: x if n == 0 else y
)(
lambda n: lambda x: lambda y: x if n & 1 else y
)(
lambda n: n >> 1
)
)
with TimeSample(' third, EP'):
sys0 = with_common_interface(sys0)
print(sys0)
with TimeSample(' sys2'):
with TimeSample(' compilation'):
sys2c = synced(readfile('src/sys2'))
with TimeSample(' runtime'):
sys2 = sys2c
sys2 = with_common_interface(sys2)
print(sys2)
with TimeSample(' runtime'):
sys2 = sys2c
sys2 = with_common_interface(sys2)
print(sys2)
with TimeSample(' full'):
sys3 = with_common_interface(synced(readfile('src/sys3')))
sys3 = sync(sys3.call(eproxy(5)))
print(sys3)

6
src/@.bu4 Normal file
View File

@ -0,0 +1,6 @@
@core/@
@church_numerals/@
@binary/@
@convert/@
@io/@
@numbers

2
src/binary/01.bu4 Normal file
View File

@ -0,0 +1,2 @@
{ /<(b0) <(g) /[b0]/[0]/[1][g]> >[YC] | b0 }
{ <(g) /[b0]/[1]/[0][g]> | b1 }

5
src/binary/@.bu4 Normal file
View File

@ -0,0 +1,5 @@
@b!
@01
@add
@mul
@sub

34
src/binary/add.bu4 Normal file
View File

@ -0,0 +1,34 @@
{ (b) </[b ]/[0][b!]> | b_double }
{
/(b_add)
(bA)(bB)
/(zqA)(lbA)(hb!A)
/
/(zqB)(lbB)(hb!B)
/
/
/
/
[hb!A]
/
[hb!B]
[b_add]
/
/[b0]/[b1] </[lbB]/[lbA][and]>
[b_add]
/
/[lbB]/[lbA][xor]
[b!]
/
[bA]
[zqB]
[bB]
/
[bB]
[zqA]
[bA]
[YC]
|
b_add
}

19
src/binary/b!.bu4 Normal file
View File

@ -0,0 +1,19 @@
{
(lb)(hb!)
(g)
/
[hb!]
/
[lb]
/
/
/(hzq)(hlb)(hhb!)
[hzq]
[hb!]
/
[0]
[lb]
[g]
|
b!
}

40
src/binary/mul.bu4 Normal file
View File

@ -0,0 +1,40 @@
{
/(b_mul)
(bA)(bB)
/(zqA)(lbA)(hb!A)
/
/(zqB)(lbB)(hb!B)
/
/
/
/
/[b0]/[hb!A] <[lbB]>
/
/[b0]/[hb!B] <[lbA]>
[b_add]
/
/
/
[hb!A]
/
[hb!B]
[b_mul]
[b_double]
[b_add]
/
</[lbB]/[lbA][and]>
[b!]
/
[b0]
[zqB]
[bB]
/
[b0]
[zqA]
[bA]
[YC]
|
b_mul
}
{ (b) /[b]/[b][b_mul] | b_square }

98
src/binary/sub.bu4 Normal file
View File

@ -0,0 +1,98 @@
{
/(b_sub)
(bA)(bB)
/(zqA)(lbA)(hb!A)
/
/(zqB)(lbB)(hb!B)
/
/(hsAB)(hsBA)
/
/
/
/[hsBA][b_double]
/
/[hsAB][b_double]
[pair]
/
/(zqhsAB)(lbAB-unused)(hb!AB-unused)
/
/
[b0]
/
/
/
/
[b1]
/
[hsAB]
[b_sub]
[first]
/
[1]
[b!]
[pair]
/
/
/[hsBA]/[1][b!]
/
[b0]
[pair]
[zqhsAB]
[hsAB]
[lbB]
/
/
/(zqhsBA)(lbBA-unused)(hb!BA-unused)
/
/
/
/
/
[hsBA]
/
[b1]
[b_sub]
[second]
/
[1]
[b!]
/
[b0]
[pair]
/
/
[b0]
/
/[hsAB]/[1][b!]
[pair]
[zqhsBA]
[hsBA]
/
/
/[hsBA][b_double]
/
/[hsAB][b_double]
[pair]
[lbB]
[lbA]
/[hb!B]/[hb!A][b_sub]
/
/
[b0]
/
[bA]
[pair]
[zqB]
[bB]
/
/
[bB]
/
[b0]
[pair]
[zqA]
[bA]
[YC]
|
b_sub
}

View File

@ -0,0 +1,2 @@
{ (f)(x) [x] | c0 }
{ (f)(x) /[x][f] | c1 }

View File

@ -0,0 +1,2 @@
@01
@add

View File

@ -0,0 +1,2 @@
{ (cA)(cB)(f)(x) //[x]</[f][cA]></[f][cB]> | c_add }
{ (c) /[c]/[c][c_add] | c_double }

3
src/ci.bu4 Normal file
View File

@ -0,0 +1,3 @@
(n0)(n1)(n_add)(n_zq)(n_lb)(n_h)
{ /[n_add]/[n1]/[n0] [b_to_n] | b_to_nx }
{ /[n_h]/[n_lb]/[n_zq][n_to_b] | n_to_bx }

3
src/convert/@.bu4 Normal file
View File

@ -0,0 +1,3 @@
@b_to_c
@b_to_n
@n_to_b

18
src/convert/b_to_c.bu4 Normal file
View File

@ -0,0 +1,18 @@
{
/(b_to_c)
(b)
/(zq)(lb)(hb!)
/
/
/[c0]/[c1][lb]
/
/</[hb!][b_to_c]>[c_double]
[c_add]
/
[c0]
[zq]
[b]
[YC]
|
b_to_c
}

28
src/convert/b_to_n.bu4 Normal file
View File

@ -0,0 +1,28 @@
{
(n0)(n1)(n_add)
/(b_to_nx)
(b)
/(zq)(lb)(hb!)
/
/
{ /[hb!][b_to_nx] | hn }
/
[hn]
/
[hn]
[n_add]
/
/
[n0]
/
[n1]
[lb]
[n_add]
/
[n0]
[zq]
[b]
[YC]
|
b_to_n
}

17
src/convert/n_to_b.bu4 Normal file
View File

@ -0,0 +1,17 @@
{
(n_zq)(n_lb)(n_h)
/(n_to_bx)
(n)
/
/
//[n][n_h][n_to_bx]
/
//[n][n_lb][bool]
[b!]
/
[b0]
/[n][n_zq]
[YC]
|
n_to_b
}

6
src/core/@.bu4 Normal file
View File

@ -0,0 +1,6 @@
@bool
@pair
@yc
@id
@collector
@compose

7
src/core/bool.bu4 Normal file
View File

@ -0,0 +1,7 @@
{ (x)(y) [x] | 1 }
{ (x)(y) [y] | 0 }
{ (x) /[0]/[1][x] | bool }
{ (x) /[1]/[0][x] | not }
{ (x)(y) /[0]/[y][x] | and }
{ (x)(y) /[y]/[1][x] | or }
{ (x)(y) /[y]/</[y][not]>[x] | xor }

19
src/core/collector.bu4 Normal file
View File

@ -0,0 +1,19 @@
{
/(collector)
(x)
(mode)
/
[x]
/
(g)
/
/[x][g]
[collector]
[mode]
[YC]
|
collector
}
{ [1] | collecting }
{ [0] | collect }

1
src/core/compose.bu4 Normal file
View File

@ -0,0 +1 @@
{ (_first)(_second)(x) //[x][_first][_second] | compose }

1
src/core/id.bu4 Normal file
View File

@ -0,0 +1 @@
{ (x)[x] | ID }

6
src/core/pair.bu4 Normal file
View File

@ -0,0 +1,6 @@
{ (x)(y)(g) /[y]/[x][g] | pair }
{ (_pair) /[1][_pair] | first }
{ (_pair) /[0][_pair] | second }
{ (x) /[x]/[x][pair] | double }
{ (x)(y) /[x]/[y][pair] | iswap }
{ (_pair) /[iswap][_pair] | swap }

2
src/core/yc.bu4 Normal file
View File

@ -0,0 +1,2 @@
{ (x) /[x][x] | SC }
{ (g) /<(x)//[x][SC][g]>[SC] | YC }

5
src/io/@.bu4 Normal file
View File

@ -0,0 +1,5 @@
@system
@pipe
@transform
@sysbinary
@decorator

14
src/io/decorator.bu4 Normal file
View File

@ -0,0 +1,14 @@
{
(input)(output)(decorated)
/
/
[output]
/
[decorated]
[pipeline]
/
[input]
[pipeline]
|
sysDecorator
}

37
src/io/pipe.bu4 Normal file
View File

@ -0,0 +1,37 @@
{
/(pipeline)
(input)(output)
/(isInputI)(outI)(outputI)(inputI)
/(isInputO)(outO)(outputO)(inputO)
/
/
(in)
/
[output]
/
/[in][inputI]
[pipeline]
/
/
[outputO]
/
[input]
[pipeline]
/
[outO]
/
[isInputO]
[system]
/
/
/[outI][inputO]
/
[outputI]
[pipeline]
/</[isInputI][not]>/[isInputO][and]
[output]
[input]
[YC]
|
pipeline
}

66
src/io/sysbinary.bu4 Normal file
View File

@ -0,0 +1,66 @@
{
/(sysB2Bits)
/
/(b2sys)
(b)
/(zq)(lb)(hb!)
/
/
/
/
[hb!]
[b2sys]
/
[lb]
[outSystem]
/
[0]
[outSystem]
/
/
[sysB2Bits]
/
[1]
[outSystem]
[zq]
[b]
[YC]
[inSimple]
[YC]
|
sysB2Bits
}
{
/
[ID]
/(sysBits2B)
(callback)
/
(in-zq)
/
/
(in-lb)
/
(b)
/
/
[b]
/
[in-lb]
[b!]
[callback]
[sysBits2B]
[inSimple]
/
/
/[ID][sysBits2B]
/
/[b0][callback]
[outSystem]
[in-zq]
[inSimple]
[YC]
|
sysBits2B
}

92
src/io/system.bu4 Normal file
View File

@ -0,0 +1,92 @@
{
(isInput)(out)(output)(input)
(g)
/[input]/[output]/[out]/[isInput]
[g]
|
system
}
{
(isInput)(out)(output)(input)
[isInput]
|
isSysInput
}
{
(isInput)(out)(output)(input)
[out]
|
outOf
}
{
(isInput)(out)(output)(input)
[output]
|
outputOf
}
{
(isInput)(out)(output)(input)
[input]
|
inputOf
}
{
(value)(sys)
/[value]/[inputOf][sys]
|
writeValue
}
{
(out)(output)
/
/[inputOf][output]
/
[output]
/
[out]
/
[0]
[system]
|
outSystem
}
{
(input)
/(this)
/
[input]
/
?
/
?
/
[1]
[system]
[YC]
|
inSimple
}
{
(out)(output)(input)
/
[input]
/
[output]
/
[out]
/
[1]
[system]
|
inSystem
}

15
src/io/transform.bu4 Normal file
View File

@ -0,0 +1,15 @@
{
(g)
/(this)
/
(in)
/
[this]
/
/[in][g]
[outSystem]
[inSimple]
[YC]
|
sysTransform
}

23
src/numbers.bu4 Normal file
View File

@ -0,0 +1,23 @@
{ /[b1][b_double] | b2 }
{ /[b1]/[1][b!] | b3 }
{ /[b2][b_double] | b4 }
{ /[b2]/[1][b!] | b5 }
{ /[b3][b_double] | b6 }
{ /[b3]/[1][b!] | b7 }
{ /[b4][b_double] | b8 }
{ /[b4]/[1][b!] | b9 }
{ /[b5][b_double] | bxA }
{ /[b5]/[1][b!] | bxB }
{ /[b3][b_square] | ^1 }
{ /[^1][b_square] | ^2 }
{ /[^2][b_square] | ^3 }
{ /[^3][b_square] | ^4 }
{ /[^4][b_square] | ^5 }
{ /[^5][b_square] | ^6 }
{ /[^6][b_square] | ^7 }
{ /[^7][b_square] | ^8 }
{ /[^8][b_square] | ^9 }
{ /[^9][b_square] | ^A }
{ /[^A][b_square] | ^B }
{ /[^B][b_square] | ^C }

7
src/sys0.bu4 Normal file
View File

@ -0,0 +1,7 @@
@@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
@ci
/[^4][b_to_nx]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

12
src/sys2.bu4 Normal file
View File

@ -0,0 +1,12 @@
@@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
@ci
//
/
[^5]
/
[^4]
[b_sub][second][b_to_nx]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

37
src/sys3.bu4 Normal file
View File

@ -0,0 +1,37 @@
@@
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
@ci
(n)
/
[outOf]
/
[n]
/
[inputOf]
/
<
/
/
/[ID][sysTransform]
/
[sysBits2B]
/
[sysB2Bits]
[sysDecorator]
/
/[b_square][sysTransform]
/
/[b_square][sysTransform]
[sysDecorator]
>
/
/[b_to_nx][sysTransform]
/
/[n_to_bx][sysTransform]
[sysDecorator]
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

18
timesample.py Normal file
View File

@ -0,0 +1,18 @@
import time
class TimeSample:
level = 0
def __init__(self, *args):
self.args = args
def __enter__(self):
TimeSample.level += 1
self.__t = time.time()
def __exit__(self, exc_type, exc_val, exc_tb):
TimeSample.level -= 1
print(' ' * 4 * self.level, end='')
print(*self.args, time.time() - self.__t)
print()