Skip to content

Commit

Permalink
Merge pull request Jaseci-Labs#247 from Jaseci-Labs/jac_cache_stuff
Browse files Browse the repository at this point in the history
feat(cli): creating option to not cache bytecode in cli
  • Loading branch information
marsninja authored Feb 26, 2024
2 parents 04473de + 7b894e3 commit ea40d6b
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 37 deletions.
14 changes: 7 additions & 7 deletions jaclang/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,25 @@ def format_file(filename: str) -> None:


@cmd_registry.register
def run(filename: str, main: bool = True) -> None:
"""Run the specified .jac file.
:param filename: The path to the .jac file.
:param main: If True, use '__main__' as the module name, else use the actual module name.
"""
def run(filename: str, main: bool = True, cache: bool = True) -> None:
"""Run the specified .jac file."""
base, mod = os.path.split(filename)
base = base if base else "./"
mod = mod[:-4]
if filename.endswith(".jac"):
jac_import(
target=mod, base_path=base, override_name="__main__" if main else None
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
)
elif filename.endswith(".jir"):
with open(filename, "rb") as f:
ir = pickle.load(f)
jac_import(
target=mod,
base_path=base,
cachable=cache,
override_name="__main__" if main else None,
mod_bundle=ir,
)
Expand Down
42 changes: 30 additions & 12 deletions jaclang/cli/cmdreg.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def register(self, func: Callable) -> Callable:
name = func.__name__
cmd = Command(func)
self.registry[name] = cmd
cmd_parser = self.sub_parsers.add_parser(name, description=func.__doc__)
cmd_parser: argparse.ArgumentParser = self.sub_parsers.add_parser(
name, description=func.__doc__
)
first = True
for param_name, param in cmd.sig.parameters.items():
arg_msg = f"type: {param.annotation.__name__}"
Expand Down Expand Up @@ -83,17 +85,33 @@ def register(self, func: Callable) -> Callable:
)
else:
arg_msg += f", default: {param.default}"
cmd_parser.add_argument(
f"-{param_name[:1]}",
f"--{param_name}",
default=param.default,
help=arg_msg,
type=(
eval(param.annotation)
if isinstance(param.annotation, str)
else param.annotation
),
)
if param.annotation == bool:
cmd_parser.add_argument(
f"-{param_name[:1]}",
f"--{param_name}",
default=param.default,
action="store_true",
help=arg_msg,
)
cmd_parser.add_argument(
f"-n{param_name[:1]}",
f"--no-{param_name}",
dest=param_name,
action="store_false",
help=f"Compliment of {arg_msg}",
)
else:
cmd_parser.add_argument(
f"-{param_name[:1]}",
f"--{param_name}",
default=param.default,
help=arg_msg,
type=(
eval(param.annotation)
if isinstance(param.annotation, str)
else param.annotation
),
)
return func

def get(self, name: str) -> Optional[Command]:
Expand Down
9 changes: 4 additions & 5 deletions jaclang/compiler/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,19 @@
from jaclang.compiler.passes.main import PyOutPass, pass_schedule
from jaclang.compiler.passes.tool import JacFormatPass
from jaclang.compiler.passes.tool.schedules import format_pass
from jaclang.compiler.passes.transform import Alert


def compile_jac(file_path: str) -> list[Alert]:
def compile_jac(file_path: str, cache_result: bool = False) -> Pass:
"""Start Compile for Jac file and return python code as string."""
code = jac_file_to_pass(
file_path=file_path,
schedule=pass_schedule,
)
if isinstance(code.ir, ast.Module) and not code.errors_had:
if cache_result and isinstance(code.ir, ast.Module) and not code.errors_had:
print_pass = PyOutPass(input_ir=code.ir, prior=code)
return print_pass
else:
return code.errors_had
return print_pass.errors_had
return code


def jac_file_to_pass(
Expand Down
4 changes: 2 additions & 2 deletions jaclang/compiler/passes/main/pyout_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ def enter_module(self, node: ast.Module) -> None:
mods = [node] + self.get_all_sub_nodes(node, ast.Module)
for mod in mods:
mod_path, out_path_py, out_path_pyc = self.get_output_targets(mod)
if os.path.exists(out_path_py) and os.path.getmtime(
out_path_py
if os.path.exists(out_path_pyc) and os.path.getmtime(
out_path_pyc
) > os.path.getmtime(mod_path):
continue
self.gen_python(mod, out_path=out_path_py)
Expand Down
19 changes: 9 additions & 10 deletions jaclang/core/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,24 +46,23 @@ def jac_importer(
codeobj = marshal.loads(codeobj)
else:
gen_dir = path.join(caller_dir, Con.JAC_GEN_DIR)
py_file_path = path.join(gen_dir, module_name + ".py")
pyc_file_path = path.join(gen_dir, module_name + ".jbc")
if (
cachable
and path.exists(py_file_path)
and path.getmtime(py_file_path) > path.getmtime(full_target)
and path.exists(pyc_file_path)
and path.getmtime(pyc_file_path) > path.getmtime(full_target)
):
with open(pyc_file_path, "rb") as f:
codeobj = marshal.load(f)
else:
if error := compile_jac(full_target):
if error:
for e in error:
print(e)
logging.error(e)
result = compile_jac(full_target, cache_result=cachable)
if result.errors_had or not result.ir.gen.py_bytecode:
for e in result.errors_had:
print(e)
logging.error(e)
return None
with open(pyc_file_path, "rb") as f:
codeobj = marshal.load(f)
else:
codeobj = marshal.loads(result.ir.gen.py_bytecode)

module_name = override_name if override_name else module_name
module = types.ModuleType(module_name)
Expand Down
5 changes: 5 additions & 0 deletions jaclang/tests/fixtures/hello_nc.jac
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Hello World!"""

with entry {
"Hello World!" |> print;
}
36 changes: 35 additions & 1 deletion jaclang/tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def test_jac_cli_run(self) -> None:
sys.stdout = captured_output

# Execute the function
cli.run(self.fixture_abs_path("hello.jac")) # type: ignore
cli.run(self.fixture_abs_path("hello.jac"))

sys.stdout = sys.__stdout__
stdout_value = captured_output.getvalue()
Expand Down Expand Up @@ -116,3 +116,37 @@ def test_build_and_run(self) -> None:
stdout_value = captured_output.getvalue()
self.assertIn("Errors: 0, Warnings: 0", stdout_value)
self.assertIn("<module 'pyfunc' from", stdout_value)

def test_cache_no_cache_on_run(self) -> None:
"""Basic test for pass."""
process = subprocess.Popen(
["jac", "run", f"{self.fixture_abs_path('hello_nc.jac')}", "-nc"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, _ = process.communicate()
self.assertFalse(
os.path.exists(
f"{self.fixture_abs_path(os.path.join('__jac_gen__', 'hello_nc.jbc'))}"
)
)
self.assertIn("Hello World!", stdout)
process = subprocess.Popen(
["jac", "run", f"{self.fixture_abs_path('hello_nc.jac')}", "-c"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
stdout, _ = process.communicate()
self.assertIn("Hello World!", stdout)
self.assertTrue(
os.path.exists(
f"{self.fixture_abs_path(os.path.join('__jac_gen__', 'hello_nc.jbc'))}"
)
)
os.remove(
f"{self.fixture_abs_path(os.path.join('__jac_gen__', 'hello_nc.jbc'))}"
)

0 comments on commit ea40d6b

Please sign in to comment.