🐐 VSQVE change

This commit is contained in:
2026-04-21 22:35:22 +02:00
parent 5961884219
commit 559b1b100e
9 changed files with 62 additions and 47 deletions

View File

@@ -105,10 +105,14 @@ Arrays are defined using square brackets (`[]`) and commas (`,`):
![Array literal](snippets/array_literal.png)
An array of integers can also be initialized with the `VSQVE` keyword:
An array of integers can also be initialized with the `VSQVE` keyword. The range is inclusive on both ends:
![Array with VSQVE](snippets/array_vsqve.png)
```
> [I, II, III, IV, V, VI, VII, VIII, IX, X]
```
Individual elements can be accessed by index using square brackets. Indexing is 1-based, so `I` refers to the first element:
![Array indexing](snippets/array_index.png)
@@ -178,7 +182,7 @@ The keyword `ET` can be used as a boolean "and". The keyword `AVT` can be used a
![DONICVM loop](snippets/donicvm.png)
```
> XLV
> LV
```
### DVM loops

View File

@@ -280,7 +280,7 @@ class DataRangeArray(Node):
raise CentvrionError("Range bounds must be numbers")
from_int = from_val.value() or 0
to_int = to_val.value() or 0
return vtable, ValList([ValInt(i) for i in range(from_int, to_int)])
return vtable, ValList([ValInt(i) for i in range(from_int, to_int + 1)])
class DataDict(Node):

View File

@@ -135,10 +135,10 @@ def emit_expr(node, ctx):
hi_lines, hi_var = emit_expr(node.to_value, ctx)
tmp = ctx.fresh_tmp()
i_var = ctx.fresh_tmp()
cap = f"({hi_var}.ival > {lo_var}.ival ? (int)({hi_var}.ival - {lo_var}.ival) : 0)"
cap = f"({hi_var}.ival >= {lo_var}.ival ? (int)({hi_var}.ival - {lo_var}.ival + 1) : 0)"
lines = lo_lines + hi_lines + [
f"CentValue {tmp} = cent_list_new({cap});",
f"for (long {i_var} = {lo_var}.ival; {i_var} < {hi_var}.ival; {i_var}++) {{",
f"for (long {i_var} = {lo_var}.ival; {i_var} <= {hi_var}.ival; {i_var}++) {{",
f" cent_list_push(&{tmp}, cent_int({i_var}));",
"}",
]

View File

@@ -3,8 +3,8 @@
DESIGNA arr VT [V, III, VIII, I, IX, II, VII, IV, VI, X]
DESIGNA n VT LONGITVDO(arr)
DONICVM i VT I VSQVE n FACE {
DONICVM k VT I VSQVE n - i + I FACE {
DONICVM i VT I VSQVE n - I FACE {
DONICVM k VT I VSQVE n - i FACE {
SI arr[k] PLVS arr[k + I] TVNC {
DESIGNA temp VT arr[k]
DESIGNA arr[k] VT arr[k + I]

View File

@@ -6,7 +6,7 @@
// Returns the bottommost empty row in col, or NVLLVS if full
DEFINI find_slot(b, col) VT {
DESIGNA ans VT NVLLVS
DONICVM r VT I VSQVE VII FACE {
DONICVM r VT I VSQVE VI FACE {
SI b[(r - I) * VII + col] EST NVLLVS TVNC {
DESIGNA ans VT r
}
@@ -16,32 +16,32 @@ DEFINI find_slot(b, col) VT {
// Returns VERITAS if player has four in a row
DEFINI est_victor(b, player) VT {
DONICVM r VT I VSQVE VII FACE {
DONICVM c VT I VSQVE V FACE {
DONICVM r VT I VSQVE VI FACE {
DONICVM c VT I VSQVE IV FACE {
DESIGNA idx VT (r - I) * VII + c
SI b[idx] EST player ET b[idx + I] EST player ET b[idx + II] EST player ET b[idx + III] EST player TVNC {
REDI(VERITAS)
}
}
}
DONICVM r VT I VSQVE IV FACE {
DONICVM c VT I VSQVE VIII FACE {
DONICVM r VT I VSQVE III FACE {
DONICVM c VT I VSQVE VII FACE {
DESIGNA idx VT (r - I) * VII + c
SI b[idx] EST player ET b[idx + VII] EST player ET b[idx + XIV] EST player ET b[idx + XXI] EST player TVNC {
REDI(VERITAS)
}
}
}
DONICVM r VT I VSQVE IV FACE {
DONICVM c VT I VSQVE V FACE {
DONICVM r VT I VSQVE III FACE {
DONICVM c VT I VSQVE IV FACE {
DESIGNA idx VT (r - I) * VII + c
SI b[idx] EST player ET b[idx + VIII] EST player ET b[idx + XVI] EST player ET b[idx + XXIV] EST player TVNC {
REDI(VERITAS)
}
}
}
DONICVM r VT I VSQVE IV FACE {
DONICVM c VT IV VSQVE VIII FACE {
DONICVM r VT I VSQVE III FACE {
DONICVM c VT IV VSQVE VII FACE {
DESIGNA idx VT (r - I) * VII + c
SI b[idx] EST player ET b[idx + VI] EST player ET b[idx + XII] EST player ET b[idx + XVIII] EST player TVNC {
REDI(VERITAS)
@@ -53,9 +53,9 @@ DEFINI est_victor(b, player) VT {
DEFINI print_board(b) VT {
DICE("+---+---+---+---+---+---+---+")
DONICVM r VT I VSQVE VII FACE {
DONICVM r VT I VSQVE VI FACE {
DESIGNA line VT "| "
DONICVM c VT I VSQVE VIII FACE {
DONICVM c VT I VSQVE VII FACE {
DESIGNA cell VT b[(r - I) * VII + c]
SI cell EST I TVNC {
DESIGNA line VT line & "X | "
@@ -101,35 +101,35 @@ DEFINI score_fenestram(a, b, c, d) VT {
DEFINI aestima(b) VT {
DESIGNA score VT NVLLVS
// Center column preference: each AI piece in column IV is worth +1
DONICVM r VT I VSQVE VII FACE {
DONICVM r VT I VSQVE VI FACE {
SI b[(r - I) * VII + IV] EST II TVNC {
DESIGNA score VT score + I
}
}
// Horizontal windows (6 rows x 4 starting columns = 24)
DONICVM r VT I VSQVE VII FACE {
DONICVM c VT I VSQVE V FACE {
DONICVM r VT I VSQVE VI FACE {
DONICVM c VT I VSQVE IV FACE {
DESIGNA idx VT (r - I) * VII + c
DESIGNA score VT score + INVOCA score_fenestram(b[idx], b[idx + I], b[idx + II], b[idx + III])
}
}
// Vertical windows (3 starting rows x 7 columns = 21)
DONICVM r VT I VSQVE IV FACE {
DONICVM c VT I VSQVE VIII FACE {
DONICVM r VT I VSQVE III FACE {
DONICVM c VT I VSQVE VII FACE {
DESIGNA idx VT (r - I) * VII + c
DESIGNA score VT score + INVOCA score_fenestram(b[idx], b[idx + VII], b[idx + XIV], b[idx + XXI])
}
}
// Diagonal up-right windows (3 starting rows x 4 starting columns = 12)
DONICVM r VT I VSQVE IV FACE {
DONICVM c VT I VSQVE V FACE {
DONICVM r VT I VSQVE III FACE {
DONICVM c VT I VSQVE IV FACE {
DESIGNA idx VT (r - I) * VII + c
DESIGNA score VT score + INVOCA score_fenestram(b[idx], b[idx + VIII], b[idx + XVI], b[idx + XXIV])
}
}
// Diagonal up-left windows (3 starting rows x 4 starting columns = 12)
DONICVM r VT I VSQVE IV FACE {
DONICVM c VT IV VSQVE VIII FACE {
DONICVM r VT I VSQVE III FACE {
DONICVM c VT IV VSQVE VII FACE {
DESIGNA idx VT (r - I) * VII + c
DESIGNA score VT score + INVOCA score_fenestram(b[idx], b[idx + VI], b[idx + XII], b[idx + XVIII])
}
@@ -219,8 +219,8 @@ DEFINI ai_move(b) VT {
}
// --- Board setup ---
DESIGNA board VT [I VSQVE XLIII]
DONICVM i VT I VSQVE XLIII FACE {
DESIGNA board VT [I VSQVE XLII]
DONICVM i VT I VSQVE XLII FACE {
DESIGNA board[i] VT NVLLVS
}

View File

@@ -1,9 +1,9 @@
// Prints an X×X multiplication table
DESIGNA n VT X
DONICVM i VT I VSQVE n + I FACE {
DONICVM i VT I VSQVE n FACE {
DESIGNA line VT ""
DONICVM k VT I VSQVE n + I FACE {
DONICVM k VT I VSQVE n FACE {
DESIGNA line VT line & i * k & " "
}
DICE(line)

View File

@@ -2,9 +2,9 @@
DESIGNA n VT L
DONICVM i VT II VSQVE n + I FACE {
DONICVM i VT II VSQVE n FACE {
DESIGNA is_prime VT VERITAS
DONICVM k VT II VSQVE i FACE {
DONICVM k VT II VSQVE i - I FACE {
SI (i / k) * k EST i TVNC {
DESIGNA is_prime VT FALSITAS
}

View File

@@ -66,7 +66,7 @@
\languageline{literal}{\textbf{numeral}} \\
\languageline{literal}{\textbf{bool}} \\
\languageline{literal}{\texttt{[} \textit{optional-expressions} \texttt{]}} \\
\languageline{literal}{\texttt{[} \textit{expression} \texttt{VSQVE} \textit{expression} \texttt{]}} \\
\languageline{literal}{\texttt{[} \textit{expression} \texttt{VSQVE} \textit{expression} \texttt{]} \textnormal{\small\ (inclusive on both ends)}} \\
\languageline{literal}{\texttt{TABVLA} \texttt{\{} \textit{optional-dict-items} \texttt{\}}} \\ \hline
\languageline{optional-dict-items}{\textit{dict-items}} \\

View File

@@ -284,13 +284,13 @@ assignment_tests = [
Designa(ID("x"), BinOp(ID("x"), BinOp(Numeral("II"), Numeral("III"), "SYMBOL_PLUS"), "SYMBOL_PLUS")),
ExpressionStatement(ID("x"))]),
ValInt(6)),
# AVGE inside a loop (DONICVM range is exclusive of upper bound: I VSQVE III = [1, 2])
# AVGE inside a loop (DONICVM range is inclusive: I VSQVE III = [1, 2, 3])
("DESIGNA s VT NVLLVS\nDONICVM i VT I VSQVE III FACE {\ns AVGE i\n}\ns",
Program([], [Designa(ID("s"), Nullus()),
PerStatement(DataRangeArray(Numeral("I"), Numeral("III")), ID("i"),
[Designa(ID("s"), BinOp(ID("s"), ID("i"), "SYMBOL_PLUS"))]),
ExpressionStatement(ID("s"))]),
ValInt(3)),
ValInt(6)),
]
class TestAssignment(unittest.TestCase):
@@ -470,7 +470,7 @@ control_tests = [
# DONICVM range loop
("DONICVM i VT I VSQVE V FACE { DICE(i) }",
Program([], [PerStatement(DataRangeArray(Numeral("I"), Numeral("V")), ID("i"), [ExpressionStatement(BuiltIn("DICE", [ID("i")]))])]),
ValStr("IV"), "I\nII\nIII\nIV\n"),
ValStr("V"), "I\nII\nIII\nIV\nV\n"),
]
class TestControl(unittest.TestCase):
@@ -1191,10 +1191,10 @@ class TestFunctionEdge(unittest.TestCase):
# --- Loop edge cases ---
loop_edge_tests = [
# range(3, 3) is empty — body never runs, program returns ValNul
# [III VSQVE III] = [3] — single iteration
("DONICVM i VT III VSQVE III FACE { DICE(i) }",
Program([], [PerStatement(DataRangeArray(Numeral("III"), Numeral("III")), ID("i"), [ExpressionStatement(BuiltIn("DICE", [ID("i")]))])]),
ValNul(), ""),
ValStr("III"), "III\n"),
# empty array — body never runs
("PER i IN [] FACE { DICE(i) }",
Program([], [PerStatement(DataArray([]), ID("i"), [ExpressionStatement(BuiltIn("DICE", [ID("i")]))])]),
@@ -1278,7 +1278,7 @@ loop_edge_tests = [
ExpressionStatement(ID("cnt")),
]),
ValInt(3), ""),
# DONICVM with CONTINVA: skip value III, count remaining
# DONICVM with CONTINVA: skip value III, count remaining (I VSQVE IV = [1,2,3,4], skip 3 → 3 increments)
("DESIGNA cnt VT I\nDONICVM i VT I VSQVE IV FACE {\nSI i EST III TVNC { CONTINVA }\nDESIGNA cnt VT cnt + I\n}\ncnt",
Program([], [
Designa(ID("cnt"), Numeral("I")),
@@ -1290,7 +1290,7 @@ loop_edge_tests = [
),
ExpressionStatement(ID("cnt")),
]),
ValInt(3)),
ValInt(4)),
# DVM condition true from start — body never runs
("DESIGNA x VT I\nDVM VERITAS FACE {\nDESIGNA x VT x + I\n}\nx",
Program([], [
@@ -1299,10 +1299,21 @@ loop_edge_tests = [
ExpressionStatement(ID("x")),
]),
ValInt(1), ""),
# single iteration: [I VSQVE II] = [1]
# two iterations: [I VSQVE II] = [1, 2]
("DONICVM i VT I VSQVE II FACE { DICE(i) }",
Program([], [PerStatement(DataRangeArray(Numeral("I"), Numeral("II")), ID("i"), [ExpressionStatement(BuiltIn("DICE", [ID("i")]))])]),
ValStr("II"), "I\nII\n"),
# single iteration: [I VSQVE I] = [1]
("DONICVM i VT I VSQVE I FACE { DICE(i) }",
Program([], [PerStatement(DataRangeArray(Numeral("I"), Numeral("I")), ID("i"), [ExpressionStatement(BuiltIn("DICE", [ID("i")]))])]),
ValStr("I"), "I\n"),
# empty range: [V VSQVE I] = []
("DESIGNA x VT NVLLVS\nDONICVM i VT V VSQVE I FACE { DESIGNA x VT x + i }\nx",
Program([], [Designa(ID("x"), Nullus()),
PerStatement(DataRangeArray(Numeral("V"), Numeral("I")), ID("i"),
[Designa(ID("x"), BinOp(ID("x"), ID("i"), "SYMBOL_PLUS"))]),
ExpressionStatement(ID("x"))]),
ValNul(), ""),
]
class TestLoopEdge(unittest.TestCase):
@@ -1427,7 +1438,7 @@ array_index_tests = [
Program([], [Designa(ID("a"), DataArray([Numeral("X"), Numeral("XX"), Numeral("XXX")])), ExpressionStatement(ArrayIndex(ID("a"), Numeral("II")))]),
ValInt(20)), # second element
# index into range array
("[I VSQVE V][II]", Program([], [ExpressionStatement(ArrayIndex(DataRangeArray(Numeral("I"), Numeral("V")), Numeral("II")))]), ValInt(2)), # second element of [1,2,3,4]
("[I VSQVE V][II]", Program([], [ExpressionStatement(ArrayIndex(DataRangeArray(Numeral("I"), Numeral("V")), Numeral("II")))]), ValInt(2)), # second element of [1,2,3,4,5]
# expression as index
("[I, II, III][I + I]",
Program([], [ExpressionStatement(ArrayIndex(
@@ -1596,15 +1607,15 @@ scope_tests = [
]),
ValInt(100)),
# DONICVM: counter holds last range value after loop ends
# [I VSQVE IV] = [1,2,3]; last value assigned by loop is III=3
# [I VSQVE IV] = [1,2,3,4]; last value assigned by loop is IV=4
("DONICVM i VT I VSQVE IV FACE { DESIGNA nop VT I }\ni",
Program([], [
PerStatement(DataRangeArray(Numeral("I"), Numeral("IV")), ID("i"), [Designa(ID("nop"), Numeral("I"))]),
ExpressionStatement(ID("i")),
]),
ValInt(3)),
ValInt(4)),
# DONICVM: reassigning counter inside body doesn't reduce the number of iterations
# range [I VSQVE IV] evaluated once; i reset each time; cnt still increments 3 times → 4
# range [I VSQVE IV] evaluated once; i reset each time; cnt still increments 4 times → 5
("DESIGNA cnt VT I\nDONICVM i VT I VSQVE IV FACE { DESIGNA cnt VT cnt + I\nDESIGNA i VT C }\ncnt",
Program([], [
Designa(ID("cnt"), Numeral("I")),
@@ -1614,7 +1625,7 @@ scope_tests = [
]),
ExpressionStatement(ID("cnt")),
]),
ValInt(4)),
ValInt(5)),
# DONICVM: ERVMPE exits loop early; counter persists at break value
("DONICVM i VT I VSQVE X FACE {\nSI i EST III TVNC { ERVMPE }\n}\ni",
Program([], [