🐐 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).
|
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
|
||||||
Modules are additions to the base `CENTVRION` syntax. They add or change certain features. Modules are included in your code by having
|
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 re
|
||||||
import random
|
import random
|
||||||
|
import time
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
|
|
||||||
from rply.token import BaseBox
|
from rply.token import BaseBox
|
||||||
@@ -1128,6 +1129,18 @@ class BuiltIn(Node):
|
|||||||
ValFunc: "FVNCTIO", ValNul: "NVLLVS",
|
ValFunc: "FVNCTIO", ValNul: "NVLLVS",
|
||||||
}
|
}
|
||||||
return vtable, ValStr(type_map[type(params[0])])
|
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 _:
|
case _:
|
||||||
raise NotImplementedError(self.builtin)
|
raise NotImplementedError(self.builtin)
|
||||||
|
|
||||||
|
|||||||
@@ -258,6 +258,10 @@ def _emit_builtin(node, ctx):
|
|||||||
case "TYPVS":
|
case "TYPVS":
|
||||||
lines.append(f"CentValue {tmp} = cent_typvs({param_vars[0]});")
|
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 _:
|
case _:
|
||||||
raise NotImplementedError(node.builtin)
|
raise NotImplementedError(node.builtin)
|
||||||
|
|
||||||
|
|||||||
@@ -559,6 +559,23 @@ CentValue cent_typvs(CentValue v) {
|
|||||||
return cent_str("IGNOTA"); /* unreachable */
|
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) {
|
CentValue cent_fortis_numerus(CentValue lo, CentValue hi) {
|
||||||
if (lo.type != CENT_INT || hi.type != CENT_INT)
|
if (lo.type != CENT_INT || hi.type != CENT_INT)
|
||||||
cent_type_error("'FORTIS_NVMERVS' requires two integers");
|
cent_type_error("'FORTIS_NVMERVS' requires two integers");
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ void cent_semen(CentValue seed); /* SEMEN */
|
|||||||
void cent_everro(void); /* EVERRO */
|
void cent_everro(void); /* EVERRO */
|
||||||
CentValue cent_senatus(CentValue *args, int n); /* SENATVS */
|
CentValue cent_senatus(CentValue *args, int n); /* SENATVS */
|
||||||
CentValue cent_typvs(CentValue v); /* TYPVS */
|
CentValue cent_typvs(CentValue v); /* TYPVS */
|
||||||
|
void cent_dormi(CentValue n); /* DORMI */
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Array helpers */
|
/* Array helpers */
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ builtin_tokens = [("BUILTIN", i) for i in [
|
|||||||
"CLAVES",
|
"CLAVES",
|
||||||
"DECIMATIO",
|
"DECIMATIO",
|
||||||
"DICE",
|
"DICE",
|
||||||
|
"DORMI",
|
||||||
"EVERRO",
|
"EVERRO",
|
||||||
"FORTIS_NVMERVS",
|
"FORTIS_NVMERVS",
|
||||||
"FORTIS_ELECTIONIS",
|
"FORTIS_ELECTIONIS",
|
||||||
|
|||||||
89
tests.py
89
tests.py
@@ -2,6 +2,7 @@ import os
|
|||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
@@ -2217,5 +2218,93 @@ class TestFvnctio(unittest.TestCase):
|
|||||||
run_test(self, source, nodes, value, output)
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user