🐐 DORMI
This commit is contained in:
@@ -314,6 +314,11 @@ Returns VERITAS if a strict majority of the arguments are VERITAS, FALSITAS othe
|
||||
|
||||
Returns the type of `value` as a string: `NVMERVS` (integer), `LITTERA` (string), `VERAX` (boolean), `CATALOGVS` (list), `FRACTIO` (fraction), `TABVLA` (dict), `FVNCTIO` (function), or `NVLLVS` (null).
|
||||
|
||||
### DORMI
|
||||
`DORMI(n)`
|
||||
|
||||
Sleeps for `n` seconds, where `n` is an integer, fraction, or NVLLVS (treated as 0). Returns nothing meaningful.
|
||||
|
||||
## Modules
|
||||
Modules are additions to the base `CENTVRION` syntax. They add or change certain features. Modules are included in your code by having
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import re
|
||||
import random
|
||||
import time
|
||||
from fractions import Fraction
|
||||
|
||||
from rply.token import BaseBox
|
||||
@@ -1128,6 +1129,18 @@ class BuiltIn(Node):
|
||||
ValFunc: "FVNCTIO", ValNul: "NVLLVS",
|
||||
}
|
||||
return vtable, ValStr(type_map[type(params[0])])
|
||||
case "DORMI":
|
||||
v = params[0]
|
||||
if isinstance(v, ValNul):
|
||||
seconds = 0
|
||||
elif isinstance(v, ValInt):
|
||||
seconds = v.value()
|
||||
elif isinstance(v, ValFrac):
|
||||
seconds = float(v.value())
|
||||
else:
|
||||
raise CentvrionError("DORMI requires a number or NVLLVS")
|
||||
time.sleep(seconds)
|
||||
return vtable, ValNul()
|
||||
case _:
|
||||
raise NotImplementedError(self.builtin)
|
||||
|
||||
|
||||
@@ -258,6 +258,10 @@ def _emit_builtin(node, ctx):
|
||||
case "TYPVS":
|
||||
lines.append(f"CentValue {tmp} = cent_typvs({param_vars[0]});")
|
||||
|
||||
case "DORMI":
|
||||
lines.append(f"cent_dormi({param_vars[0]});")
|
||||
lines.append(f"CentValue {tmp} = cent_null();")
|
||||
|
||||
case _:
|
||||
raise NotImplementedError(node.builtin)
|
||||
|
||||
|
||||
@@ -559,6 +559,23 @@ CentValue cent_typvs(CentValue v) {
|
||||
return cent_str("IGNOTA"); /* unreachable */
|
||||
}
|
||||
|
||||
void cent_dormi(CentValue n) {
|
||||
struct timespec ts;
|
||||
if (n.type == CENT_NULL) {
|
||||
ts.tv_sec = 0; ts.tv_nsec = 0;
|
||||
} else if (n.type == CENT_INT) {
|
||||
ts.tv_sec = n.ival; ts.tv_nsec = 0;
|
||||
} else if (n.type == CENT_FRAC) {
|
||||
long sec = n.fval.num / n.fval.den;
|
||||
long rem = n.fval.num % n.fval.den;
|
||||
ts.tv_sec = sec;
|
||||
ts.tv_nsec = rem * 1000000000L / n.fval.den;
|
||||
} else {
|
||||
cent_type_error("'DORMI' requires a number or NVLLVS");
|
||||
}
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
CentValue cent_fortis_numerus(CentValue lo, CentValue hi) {
|
||||
if (lo.type != CENT_INT || hi.type != CENT_INT)
|
||||
cent_type_error("'FORTIS_NVMERVS' requires two integers");
|
||||
|
||||
@@ -221,6 +221,7 @@ void cent_semen(CentValue seed); /* SEMEN */
|
||||
void cent_everro(void); /* EVERRO */
|
||||
CentValue cent_senatus(CentValue *args, int n); /* SENATVS */
|
||||
CentValue cent_typvs(CentValue v); /* TYPVS */
|
||||
void cent_dormi(CentValue n); /* DORMI */
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Array helpers */
|
||||
|
||||
@@ -44,6 +44,7 @@ builtin_tokens = [("BUILTIN", i) for i in [
|
||||
"CLAVES",
|
||||
"DECIMATIO",
|
||||
"DICE",
|
||||
"DORMI",
|
||||
"EVERRO",
|
||||
"FORTIS_NVMERVS",
|
||||
"FORTIS_ELECTIONIS",
|
||||
|
||||
89
tests.py
89
tests.py
@@ -2,6 +2,7 @@ import os
|
||||
import random
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
from io import StringIO
|
||||
from unittest.mock import patch
|
||||
@@ -2217,5 +2218,93 @@ class TestFvnctio(unittest.TestCase):
|
||||
run_test(self, source, nodes, value, output)
|
||||
|
||||
|
||||
# --- DORMI ---
|
||||
|
||||
dormi_tests = [
|
||||
("DORMI(NVLLVS)",
|
||||
Program([], [ExpressionStatement(BuiltIn("DORMI", [Nullus()]))]),
|
||||
ValNul()),
|
||||
]
|
||||
|
||||
class TestDormi(unittest.TestCase):
|
||||
@parameterized.expand(dormi_tests)
|
||||
def test_dormi(self, source, nodes, value, output=""):
|
||||
run_test(self, source, nodes, value, output)
|
||||
|
||||
def test_dormi_timing_int(self):
|
||||
source = "DORMI(I)\n"
|
||||
lexer = Lexer().get_lexer()
|
||||
tokens = lexer.lex(source)
|
||||
program = Parser().parse(tokens)
|
||||
|
||||
start = time.time()
|
||||
program.eval()
|
||||
elapsed = time.time() - start
|
||||
self.assertAlmostEqual(elapsed, 1.0, delta=0.5)
|
||||
|
||||
def test_dormi_timing_int_compiled(self):
|
||||
source = "DORMI(I)\n"
|
||||
lexer = Lexer().get_lexer()
|
||||
tokens = lexer.lex(source)
|
||||
program = Parser().parse(tokens)
|
||||
|
||||
c_source = compile_program(program)
|
||||
with tempfile.NamedTemporaryFile(suffix=".c", delete=False, mode="w") as tmp_c:
|
||||
tmp_c.write(c_source)
|
||||
tmp_c_path = tmp_c.name
|
||||
with tempfile.NamedTemporaryFile(suffix="", delete=False) as tmp_bin:
|
||||
tmp_bin_path = tmp_bin.name
|
||||
try:
|
||||
subprocess.run(
|
||||
["gcc", "-O2", tmp_c_path, _RUNTIME_C, "-o", tmp_bin_path],
|
||||
check=True, capture_output=True,
|
||||
)
|
||||
start = time.time()
|
||||
proc = subprocess.run([tmp_bin_path], capture_output=True, text=True)
|
||||
elapsed = time.time() - start
|
||||
self.assertEqual(proc.returncode, 0)
|
||||
self.assertAlmostEqual(elapsed, 1.0, delta=0.5)
|
||||
finally:
|
||||
os.unlink(tmp_c_path)
|
||||
os.unlink(tmp_bin_path)
|
||||
|
||||
def test_dormi_timing_frac(self):
|
||||
source = "CVM FRACTIO\nDORMI(S)\n"
|
||||
lexer = Lexer().get_lexer()
|
||||
tokens = lexer.lex(source)
|
||||
program = Parser().parse(tokens)
|
||||
|
||||
start = time.time()
|
||||
program.eval()
|
||||
elapsed = time.time() - start
|
||||
self.assertAlmostEqual(elapsed, 0.5, delta=0.5)
|
||||
|
||||
def test_dormi_timing_frac_compiled(self):
|
||||
source = "CVM FRACTIO\nDORMI(S)\n"
|
||||
lexer = Lexer().get_lexer()
|
||||
tokens = lexer.lex(source)
|
||||
program = Parser().parse(tokens)
|
||||
|
||||
c_source = compile_program(program)
|
||||
with tempfile.NamedTemporaryFile(suffix=".c", delete=False, mode="w") as tmp_c:
|
||||
tmp_c.write(c_source)
|
||||
tmp_c_path = tmp_c.name
|
||||
with tempfile.NamedTemporaryFile(suffix="", delete=False) as tmp_bin:
|
||||
tmp_bin_path = tmp_bin.name
|
||||
try:
|
||||
subprocess.run(
|
||||
["gcc", "-O2", tmp_c_path, _RUNTIME_C, "-o", tmp_bin_path],
|
||||
check=True, capture_output=True,
|
||||
)
|
||||
start = time.time()
|
||||
proc = subprocess.run([tmp_bin_path], capture_output=True, text=True)
|
||||
elapsed = time.time() - start
|
||||
self.assertEqual(proc.returncode, 0)
|
||||
self.assertAlmostEqual(elapsed, 0.5, delta=0.5)
|
||||
finally:
|
||||
os.unlink(tmp_c_path)
|
||||
os.unlink(tmp_bin_path)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user