🐐 DECIMATIO
This commit is contained in:
@@ -248,12 +248,14 @@ Vnlike many other programming languages with modules, the modules in `CENTVRION`
|
||||
### FORS
|
||||

|
||||
|
||||
The `FORS` module allows you to add randomness to your `CENTVRION` program. It adds 3 new built-in functions: `FORTIS_NVMERVS int int`, `FORTIS_ELECTIONIS ['a]`, and `SEMEN int`.
|
||||
The `FORS` module allows you to add randomness to your `CENTVRION` program. It adds 4 new built-in functions: `FORTIS_NVMERVS int int`, `FORTIS_ELECTIONIS ['a]`, `DECIMATIO ['a]`, and `SEMEN int`.
|
||||
|
||||
`FORTIS_NVMERVS int int` picks a random int in the (inclusive) range of the two given ints.
|
||||
|
||||
`FORTIS_ELECTIONIS ['a]` picks a random element from the given array. `FORTIS_ELECTIONIS array` is identical to ```array[FORTIS_NVMERVS NVLLVS ((LONGITVDO array)-I)]```.
|
||||
|
||||
`DECIMATIO ['a]` returns a copy of the given array with a random tenth of its elements removed. Arrays with fewer than 10 elements are returned unchanged.
|
||||
|
||||
`SEMEN int` seeds the random number generator for reproducibility.
|
||||
|
||||
### FRACTIO
|
||||
|
||||
@@ -957,6 +957,16 @@ class BuiltIn(Node):
|
||||
raise CentvrionError("SEMEN requires an integer seed")
|
||||
random.seed(seed)
|
||||
return vtable, ValNul()
|
||||
case "DECIMATIO":
|
||||
if "FORS" not in vtable["#modules"]:
|
||||
raise CentvrionError("Cannot use 'DECIMATIO' without module 'FORS'")
|
||||
if not isinstance(params[0], ValList):
|
||||
raise CentvrionError("DECIMATIO requires an array")
|
||||
arr = list(params[0].value())
|
||||
to_remove = len(arr) // 10
|
||||
for _ in range(to_remove):
|
||||
arr.pop(random.randint(0, len(arr) - 1))
|
||||
return vtable, ValList(arr)
|
||||
case "LONGITVDO":
|
||||
if isinstance(params[0], (ValList, ValStr)):
|
||||
return vtable, ValInt(len(params[0].value()))
|
||||
|
||||
@@ -186,6 +186,13 @@ def _emit_builtin(node, ctx):
|
||||
else:
|
||||
lines.append(f"CentValue {tmp} = cent_fortis_electionis({param_vars[0]});")
|
||||
|
||||
case "DECIMATIO":
|
||||
if not ctx.has_module("FORS"):
|
||||
lines.append('cent_runtime_error("FORS module required for DECIMATIO");')
|
||||
lines.append(f"CentValue {tmp} = cent_null();")
|
||||
else:
|
||||
lines.append(f"CentValue {tmp} = cent_decimatio({param_vars[0]});")
|
||||
|
||||
case "SEMEN":
|
||||
if not ctx.has_module("FORS"):
|
||||
lines.append('cent_runtime_error("FORS module required for SEMEN");')
|
||||
|
||||
@@ -533,6 +533,25 @@ CentValue cent_fortis_electionis(CentValue lst) {
|
||||
return lst.lval.items[rand() % lst.lval.len];
|
||||
}
|
||||
|
||||
CentValue cent_decimatio(CentValue lst) {
|
||||
if (lst.type != CENT_LIST)
|
||||
cent_type_error("'DECIMATIO' requires a list");
|
||||
int len = lst.lval.len;
|
||||
/* Copy the list so we can remove in-place */
|
||||
CentValue result = cent_list_new(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
cent_list_push(&result, lst.lval.items[i]);
|
||||
int to_remove = result.lval.len / 10;
|
||||
for (int i = 0; i < to_remove; i++) {
|
||||
int idx = rand() % result.lval.len;
|
||||
/* Shift remaining elements left */
|
||||
for (int j = idx; j < result.lval.len - 1; j++)
|
||||
result.lval.items[j] = result.lval.items[j + 1];
|
||||
result.lval.len--;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void cent_semen(CentValue seed) {
|
||||
if (seed.type != CENT_INT)
|
||||
cent_type_error("'SEMEN' requires an integer seed");
|
||||
|
||||
@@ -177,6 +177,7 @@ CentValue cent_avdi_numerus(void); /* AVDI_NVMERVS */
|
||||
CentValue cent_longitudo(CentValue v); /* LONGITVDO */
|
||||
CentValue cent_fortis_numerus(CentValue lo, CentValue hi); /* FORTIS_NVMERVS */
|
||||
CentValue cent_fortis_electionis(CentValue lst); /* FORTIS_ELECTIONIS */
|
||||
CentValue cent_decimatio(CentValue lst); /* DECIMATIO */
|
||||
void cent_semen(CentValue seed); /* SEMEN */
|
||||
void cent_everro(void); /* EVERRO */
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ keyword_tokens = [("KEYWORD_"+i, i) for i in [
|
||||
builtin_tokens = [("BUILTIN", i) for i in [
|
||||
"AVDI_NVMERVS",
|
||||
"AVDI",
|
||||
"DECIMATIO",
|
||||
"DICE",
|
||||
"EVERRO",
|
||||
"FORTIS_NVMERVS",
|
||||
|
||||
@@ -57,7 +57,7 @@ contexts:
|
||||
scope: constant.language.centvrion
|
||||
|
||||
builtins:
|
||||
- match: '\b(AVDI_NVMERVS|AVDI|DICE|FORTIS_NVMERVS|FORTIS_ELECTIONIS|LONGITVDO|SEMEN)\b'
|
||||
- match: '\b(AVDI_NVMERVS|AVDI|DECIMATIO|DICE|FORTIS_NVMERVS|FORTIS_ELECTIONIS|LONGITVDO|SEMEN)\b'
|
||||
scope: support.function.builtin.centvrion
|
||||
|
||||
modules:
|
||||
|
||||
10
tests.py
10
tests.py
@@ -537,6 +537,14 @@ builtin_tests = [
|
||||
('LONGITVDO("")', Program([], [ExpressionStatement(BuiltIn("LONGITVDO", [String("")]))]), ValInt(0)),
|
||||
("CVM FORS\nFORTIS_ELECTIONIS([I, II, III])", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("FORTIS_ELECTIONIS", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]))]), ValInt(1)),
|
||||
("CVM FORS\nSEMEN(XLII)\nFORTIS_NVMERVS(I, C)", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("XLII")])), ExpressionStatement(BuiltIn("FORTIS_NVMERVS", [Numeral("I"), Numeral("C")]))]), ValInt(82)),
|
||||
# DECIMATIO: seed 42, 10 elements → removes 1 (element II)
|
||||
("CVM FORS\nSEMEN(XLII)\nDECIMATIO([I, II, III, IV, V, VI, VII, VIII, IX, X])", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("XLII")])), ExpressionStatement(BuiltIn("DECIMATIO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V"), Numeral("VI"), Numeral("VII"), Numeral("VIII"), Numeral("IX"), Numeral("X")])]))]), ValList([ValInt(1), ValInt(3), ValInt(4), ValInt(5), ValInt(6), ValInt(7), ValInt(8), ValInt(9), ValInt(10)])),
|
||||
# DECIMATIO: seed 1, 3 elements → 3//10=0, nothing removed
|
||||
("CVM FORS\nSEMEN(I)\nDECIMATIO([I, II, III])", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("I")])), ExpressionStatement(BuiltIn("DECIMATIO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III")])]))]), ValList([ValInt(1), ValInt(2), ValInt(3)])),
|
||||
# DECIMATIO: empty array → empty array
|
||||
("CVM FORS\nDECIMATIO([])", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("DECIMATIO", [DataArray([])]))]), ValList([])),
|
||||
# DECIMATIO: seed 42, 20 elements → removes 2 (elements I and IV)
|
||||
("CVM FORS\nSEMEN(XLII)\nDECIMATIO([I, II, III, IV, V, VI, VII, VIII, IX, X, XI, XII, XIII, XIV, XV, XVI, XVII, XVIII, XIX, XX])", Program([ModuleCall("FORS")], [ExpressionStatement(BuiltIn("SEMEN", [Numeral("XLII")])), ExpressionStatement(BuiltIn("DECIMATIO", [DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V"), Numeral("VI"), Numeral("VII"), Numeral("VIII"), Numeral("IX"), Numeral("X"), Numeral("XI"), Numeral("XII"), Numeral("XIII"), Numeral("XIV"), Numeral("XV"), Numeral("XVI"), Numeral("XVII"), Numeral("XVIII"), Numeral("XIX"), Numeral("XX")])]))]), ValList([ValInt(2), ValInt(3), ValInt(5), ValInt(6), ValInt(7), ValInt(8), ValInt(9), ValInt(10), ValInt(11), ValInt(12), ValInt(13), ValInt(14), ValInt(15), ValInt(16), ValInt(17), ValInt(18), ValInt(19), ValInt(20)])),
|
||||
]
|
||||
|
||||
class TestBuiltins(unittest.TestCase):
|
||||
@@ -577,6 +585,8 @@ error_tests = [
|
||||
("CVM FORS\nFORTIS_ELECTIONIS([])", CentvrionError), # FORTIS_ELECTIONIS on empty array
|
||||
("CVM FORS\nFORTIS_NVMERVS(X, I)", CentvrionError), # FORTIS_NVMERVS a > b
|
||||
("PER i IN I FACE { DICE(i) }", CentvrionError), # PER over non-array
|
||||
("DECIMATIO([I, II, III])", CentvrionError), # FORS required for DECIMATIO
|
||||
("CVM FORS\nDECIMATIO(I)", CentvrionError), # DECIMATIO requires an array
|
||||
("LONGITVDO(I)", CentvrionError), # LONGITVDO on non-array
|
||||
("DESIGNA x VT I\nINVOCA x ()", CentvrionError), # invoking a non-function
|
||||
("SI I TVNC { DESIGNA r VT I }", CentvrionError), # non-bool SI condition: int
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"patterns": [
|
||||
{
|
||||
"name": "support.function.builtin.cent",
|
||||
"match": "\\b(AVDI_NVMERVS|AVDI|DICE|EVERRO|FORTIS_NVMERVS|FORTIS_ELECTIONIS|LONGITVDO)\\b"
|
||||
"match": "\\b(AVDI_NVMERVS|AVDI|DECIMATIO|DICE|EVERRO|FORTIS_NVMERVS|FORTIS_ELECTIONIS|LONGITVDO|SEMEN)\\b"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user