Skip to content

Commit

Permalink
Adding CLI for ease of usage
Browse files Browse the repository at this point in the history
  • Loading branch information
ACassimiro committed Aug 23, 2024
1 parent d24de17 commit d44aa43
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 3 deletions.
6 changes: 5 additions & 1 deletion rust-lite/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ pytest-xdist = "*"
pyupgrade = "*"

[tool.poetry.scripts]
rust = "rust_lite.__main__:main"
main = "rust_lite.__main__:main"
empty = "rust_lite.__main__:exec_empty"
erc20 = "rust_lite.__main__:exec_erc20"
lending = "rust_lite.__main__:exec_lending"
staking = "rust_lite.__main__:exec_staking"

[tool.isort]
profile = "black"
Expand Down
62 changes: 60 additions & 2 deletions rust-lite/src/rust_lite/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import sys
from collections.abc import Iterable
from typing import TYPE_CHECKING
from .cli import _create_argument_parser, generate_options, get_argument_type_setter, get_option_string_destination
from pyk.cli.pyk import parse_toml_args
from pathlib import Path


from .manager import RustLiteManager

Expand All @@ -15,6 +19,7 @@
from argparse import Namespace
from collections.abc import Callable, Iterator
from typing import Any, Final, TypeVar
from .cli import RunOptions

T = TypeVar('T')

Expand All @@ -23,19 +28,72 @@


def main() -> None:
sys.setrecursionlimit(15000000)
parser = _create_argument_parser()
args = parser.parse_args()
toml_args = parse_toml_args(args, get_option_string_destination, get_argument_type_setter)
logging.basicConfig(level=_loglevel(args), format=_LOG_FORMAT)

stripped_args = toml_args | {
key: val for (key, val) in vars(args).items() if val is not None and not (isinstance(val, Iterable) and not val)
}
print(stripped_args)
options = generate_options(stripped_args)

executor_name = 'exec_' + args.command.lower().replace('-', '_')
if executor_name not in globals():
raise AssertionError(f'Unimplemented command: {args.command}')

execute = globals()[executor_name]
execute(options)


def exec_run(options: RunOptions) -> None:
contract_path = str(options.input_file.resolve())

print('Instantiating module manager;')

module_manager = RustLiteManager()

print('Module manager initiated; Trying to load program into K cell;')


# contract_path = '../tests/syntax/erc_20_token.rs'
contract_path = '../tests/execution/empty.rs'
# contract_path = '../tests/execution/empty.rs'

module_manager.load_program(contract_path)

print('Program loaded; Trying to fetch the content of the K cell.')

module_manager.fetch_k_cell_content()

def trigger_exec_run(stripped_args):
options = generate_options(stripped_args)
executor_name = 'exec_run'
execute = globals()[executor_name]
execute(options)

def exec_empty() -> None:
stripped_args = {'command': 'run', 'input_file': Path('../tests/execution/empty.rs')}
trigger_exec_run(stripped_args)

def exec_erc20() -> None:
stripped_args = {'command': 'run', 'input_file': Path('../tests/syntax/erc_20_token.rs')}
trigger_exec_run(stripped_args)

def exec_staking() -> None:
stripped_args = {'command': 'run', 'input_file': Path('../tests/syntax/lending.rs')}
trigger_exec_run(stripped_args)

def exec_lending() -> None:
stripped_args = {'command': 'run', 'input_file': Path('../tests/syntax/staking.rs')}
trigger_exec_run(stripped_args)


def _loglevel(args: Namespace) -> int:
if args.debug:
return logging.DEBUG

if args.verbose:
return logging.INFO

return logging.WARNING
202 changes: 202 additions & 0 deletions rust-lite/src/rust_lite/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
from __future__ import annotations

import logging
from argparse import ArgumentParser
from functools import cached_property
from typing import TYPE_CHECKING, Any

from pyk.cli.args import DisplayOptions as PykDisplayOptions
from pyk.cli.args import KCLIArgs, KDefinitionOptions, LoggingOptions, Options, SaveDirOptions
from pyk.cli.utils import file_path
from pyk.kast.inner import KSort
from pyk.kore.tools import PrintOutput
from pyk.ktool.krun import KRunOutput

if TYPE_CHECKING:
from collections.abc import Callable
from pathlib import Path
from typing import Final, TypeVar

T = TypeVar('T')

_LOGGER: Final = logging.getLogger(__name__)


def generate_options(args: dict[str, Any]) -> LoggingOptions:
command = args['command']
match command:
case 'version':
return VersionOptions(args)
case 'run':
return RunOptions(args)
case _:
raise ValueError(f'Unrecognized command: {command}')


def get_option_string_destination(command: str, option_string: str) -> str:
option_string_destinations = {}
match command:
case 'version':
option_string_destinations = VersionOptions.from_option_string()
case 'parse':
option_string_destinations = RunOptions.from_option_string()

return option_string_destinations.get(option_string, option_string.replace('-', '_'))


def get_argument_type_setter(command: str, option_string: str) -> Callable[[str], Any]:
def func(par: str) -> str:
return par

option_types = {}
match command:
case 'version':
option_types = VersionOptions.get_argument_type()
case 'parse':
option_types = RunOptions.get_argument_type()

return option_types.get(option_string, func)


def _create_argument_parser() -> ArgumentParser:
rust_lite_cli_args = RustLiteCLIArgs()
parser = ArgumentParser(prog='rust-lite')

command_parser = parser.add_subparsers(dest='command', required=True)

# command_parser.add_parser('version', help='Print Rust-Lite version and exit.', parents=[rust_lite_cli_args.logging_args])

run_args = command_parser.add_parser(
'run',
help='Run Rust-Lite program.',
parents=[
rust_lite_cli_args.logging_args,
# rust_lite_cli_args.target_args,
# rust_lite_cli_args.k_args,
],
)
run_args.add_argument('input_file', type=file_path, help='Path to input file.')
# run_args.add_argument(
# '--output',
# type=PrintOutput,
# choices=list(PrintOutput),
# )
# run_args.add_argument(
# '--sort',
# dest='sort',
# default=None,
# type=KSort,
# help='Sort to parse input as.',
# )

return parser


class KOptions(KDefinitionOptions):
definition_dir: Path | None
depth: int | None

@staticmethod
def default() -> dict[str, Any]:
return {
'definition_dir': None,
'depth': None,
}

@staticmethod
def from_option_string() -> dict[str, str]:
return KDefinitionOptions.from_option_string() | {
'definition': 'definition_dir',
}

@staticmethod
def get_argument_type() -> dict[str, Callable]:
return KDefinitionOptions.get_argument_type()


class TargetOptions(Options):
target: str | None

@staticmethod
def default() -> dict[str, Any]:
return {
'target': None,
}


class DisplayOptions(PykDisplayOptions):
sort_collections: bool

@staticmethod
def default() -> dict[str, Any]:
return {
'sort_collections': False,
}

@staticmethod
def from_option_string() -> dict[str, str]:
return PykDisplayOptions.from_option_string()

@staticmethod
def get_argument_type() -> dict[str, Callable]:
return PykDisplayOptions.get_argument_type()


class VersionOptions(LoggingOptions):
@staticmethod
def from_option_string() -> dict[str, str]:
return LoggingOptions.from_option_string()

@staticmethod
def get_argument_type() -> dict[str, Callable]:
return LoggingOptions.get_argument_type()

class RunOptions(
LoggingOptions
):
input_file: Path

@staticmethod
def default() -> dict[str, Any]:
return {
'input_file': None,
}

@staticmethod
def from_option_string() -> dict[str, str]:
return (
LoggingOptions.from_option_string()
)

@staticmethod
def get_argument_type() -> dict[str, Callable]:
return (
{
'input_file': file_path,
}
)

class RustLiteCLIArgs(KCLIArgs):
@cached_property
def target_args(self) -> ArgumentParser:
args = ArgumentParser(add_help=False)
args.add_argument('--target', choices=['llvm', 'haskell', 'haskell-standalone', 'foundry'])
return args

@cached_property
def k_args(self) -> ArgumentParser:
args = super().definition_args
args.add_argument('--depth', type=int, help='Maximum depth to execute to.')
return args

@cached_property
def display_args(self) -> ArgumentParser:
args = super().display_args
args.add_argument(
'--sort-collections',
dest='sort_collections',
default=None,
action='store_true',
help='Sort collections before outputting term.',
)
return args

0 comments on commit d44aa43

Please sign in to comment.