From 378c28102ce5d3f33cdaf2b49b34360f6d19c8c0 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Tue, 21 Apr 2026 22:53:40 +0200 Subject: [PATCH] :goat: Array slicing --- README.md | 8 + centvrion/ast_nodes.py | 43 ++++ centvrion/compiler/emit_expr.py | 11 +- centvrion/compiler/runtime/cent_runtime.c | 16 ++ centvrion/compiler/runtime/cent_runtime.h | 1 + centvrion/parser.py | 4 + language/main.aux | 2 + language/main.log | 269 ++++++++++++++++++++++ language/main.pdf | Bin 21474 -> 25220 bytes language/main.tex | 1 + snippets/array_slice.cent | 2 + snippets/array_slice.png | Bin 0 -> 15738 bytes tests.py | 68 +++++- 13 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 language/main.aux create mode 100644 language/main.log create mode 100644 snippets/array_slice.cent create mode 100644 snippets/array_slice.png diff --git a/README.md b/README.md index 5e71828..20d4c2b 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,14 @@ Individual elements can be accessed by index using square brackets. Indexing is > I ``` +A sub-array can be extracted with `VSQVE` inside the index brackets. Both bounds are inclusive and 1-based: + +![Array slicing](snippets/array_slice.png) + +``` +> [XX, XXX, XL] +``` + ### Dicts (TABVLA) Dicts are key-value maps created with the `TABVLA` keyword and curly braces: diff --git a/centvrion/ast_nodes.py b/centvrion/ast_nodes.py index 0559386..1168909 100644 --- a/centvrion/ast_nodes.py +++ b/centvrion/ast_nodes.py @@ -847,6 +847,49 @@ class ArrayIndex(Node): return vtable, lst[i - 1] +def _to_index_int(val): + if isinstance(val, ValInt): + return val.value() + if isinstance(val, ValFrac) and val.value().denominator == 1: + return val.value().numerator + raise CentvrionError("Array index must be a number") + + +class ArraySlice(Node): + def __init__(self, array, from_index, to_index) -> None: + self.array = array + self.from_index = from_index + self.to_index = to_index + + def __eq__(self, other): + return (type(self) == type(other) + and self.array == other.array + and self.from_index == other.from_index + and self.to_index == other.to_index) + + def __repr__(self) -> str: + return f"ArraySlice({self.array!r}, {self.from_index!r}, {self.to_index!r})" + + def print(self): + return f"{self.array.print()}[{self.from_index.print()} VSQVE {self.to_index.print()}]" + + def _eval(self, vtable): + vtable, array = self.array.eval(vtable) + vtable, from_val = self.from_index.eval(vtable) + vtable, to_val = self.to_index.eval(vtable) + if not isinstance(array, ValList): + raise CentvrionError("Cannot slice a non-array value") + from_int = _to_index_int(from_val) + to_int = _to_index_int(to_val) + lst = array.value() + if from_int < 1 or to_int > len(lst) or from_int > to_int: + raise CentvrionError( + f"Slice [{from_int} VSQVE {to_int}] out of range" + f" for array of length {len(lst)}" + ) + return vtable, ValList(lst[from_int - 1 : to_int]) + + class SiStatement(Node): def __init__(self, test, statements, else_part) -> None: self.test = test diff --git a/centvrion/compiler/emit_expr.py b/centvrion/compiler/emit_expr.py index 3c29c52..d9002a1 100644 --- a/centvrion/compiler/emit_expr.py +++ b/centvrion/compiler/emit_expr.py @@ -2,7 +2,7 @@ from centvrion.errors import CentvrionError from centvrion.ast_nodes import ( String, InterpolatedString, Numeral, Fractio, Bool, Nullus, ID, BinOp, UnaryMinus, UnaryNot, - ArrayIndex, DataArray, DataRangeArray, DataDict, + ArrayIndex, ArraySlice, DataArray, DataRangeArray, DataDict, BuiltIn, Invoca, Fvnctio, num_to_int, frac_to_fraction, ) @@ -120,6 +120,15 @@ def emit_expr(node, ctx): tmp = ctx.fresh_tmp() return arr_lines + idx_lines + [f"CentValue {tmp} = cent_list_index({arr_var}, {idx_var});"], tmp + if isinstance(node, ArraySlice): + arr_lines, arr_var = emit_expr(node.array, ctx) + lo_lines, lo_var = emit_expr(node.from_index, ctx) + hi_lines, hi_var = emit_expr(node.to_index, ctx) + tmp = ctx.fresh_tmp() + return arr_lines + lo_lines + hi_lines + [ + f"CentValue {tmp} = cent_list_slice({arr_var}, {lo_var}, {hi_var});" + ], tmp + if isinstance(node, DataArray): lines = [] tmp = ctx.fresh_tmp() diff --git a/centvrion/compiler/runtime/cent_runtime.c b/centvrion/compiler/runtime/cent_runtime.c index d48be47..c5d014e 100644 --- a/centvrion/compiler/runtime/cent_runtime.c +++ b/centvrion/compiler/runtime/cent_runtime.c @@ -735,6 +735,22 @@ CentValue cent_list_index(CentValue lst, CentValue idx) { return lst.lval.items[i - 1]; } +CentValue cent_list_slice(CentValue lst, CentValue lo, CentValue hi) { + if (lst.type != CENT_LIST) + cent_type_error("slice requires a list"); + if (lo.type != CENT_INT || hi.type != CENT_INT) + cent_type_error("slice indices must be integers"); + long from = lo.ival; + long to = hi.ival; + if (from < 1 || to > lst.lval.len || from > to) + cent_runtime_error("slice out of range"); + int len = (int)(to - from + 1); + CentValue result = cent_list_new(len); + for (long j = from; j <= to; j++) + cent_list_push(&result, lst.lval.items[j - 1]); + return result; +} + void cent_list_index_set(CentValue *lst, CentValue idx, CentValue v) { if (lst->type == CENT_DICT) { cent_dict_set(lst, idx, v); diff --git a/centvrion/compiler/runtime/cent_runtime.h b/centvrion/compiler/runtime/cent_runtime.h index c40cfa2..21f2d27 100644 --- a/centvrion/compiler/runtime/cent_runtime.h +++ b/centvrion/compiler/runtime/cent_runtime.h @@ -234,6 +234,7 @@ void cent_adivnge(CentValue path, CentValue content); /* ADIVNGE */ CentValue cent_list_new(int cap); void cent_list_push(CentValue *lst, CentValue v); CentValue cent_list_index(CentValue lst, CentValue idx); /* 1-based */ +CentValue cent_list_slice(CentValue lst, CentValue lo, CentValue hi); /* 1-based, inclusive */ void cent_list_index_set(CentValue *lst, CentValue idx, CentValue v); /* ------------------------------------------------------------------ */ diff --git a/centvrion/parser.py b/centvrion/parser.py index 3c207c5..e787084 100644 --- a/centvrion/parser.py +++ b/centvrion/parser.py @@ -326,6 +326,10 @@ class Parser(): def array_index(tokens): return ast_nodes.ArrayIndex(tokens[0], tokens[2]) + @self.pg.production('expression : expression SYMBOL_LBRACKET expression KEYWORD_VSQVE expression SYMBOL_RBRACKET', precedence='INDEX') + def array_slice(tokens): + return ast_nodes.ArraySlice(tokens[0], tokens[2], tokens[4]) + # ids @self.pg.production('ids : SYMBOL_LPARENS id_list') def ids(tokens): diff --git a/language/main.aux b/language/main.aux new file mode 100644 index 0000000..d490c35 --- /dev/null +++ b/language/main.aux @@ -0,0 +1,2 @@ +\relax +\gdef \@abspage@last{2} diff --git a/language/main.log b/language/main.log new file mode 100644 index 0000000..d08eed8 --- /dev/null +++ b/language/main.log @@ -0,0 +1,269 @@ +This is XeTeX, Version 3.141592653-2.6-0.999998 (TeX Live 2026/Arch Linux) (preloaded format=xelatex 2026.4.8) 21 APR 2026 22:51 +entering extended mode + restricted \write18 enabled. + %&-line parsing enabled. +**main.tex +(./main.tex +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> +(/usr/share/texmf-dist/tex/latex/base/article.cls +Document Class: article 2025/01/22 v1.4n Standard LaTeX document class +(/usr/share/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2025/01/22 v1.4n Standard LaTeX file (size option) +) +\c@part=\count271 +\c@section=\count272 +\c@subsection=\count273 +\c@subsubsection=\count274 +\c@paragraph=\count275 +\c@subparagraph=\count276 +\c@figure=\count277 +\c@table=\count278 +\abovecaptionskip=\skip49 +\belowcaptionskip=\skip50 +\bibindent=\dimen148 +) +(/usr/share/texmf-dist/tex/latex/geometry/geometry.sty +Package: geometry 2020/01/02 v5.9 Page Geometry + +(/usr/share/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2022/05/29 v1.15 key=value parser (DPC) +\KV@toks@=\toks17 +) +(/usr/share/texmf-dist/tex/generic/iftex/ifvtex.sty +Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead. + +(/usr/share/texmf-dist/tex/generic/iftex/iftex.sty +Package: iftex 2024/12/12 v1.0g TeX engine tests +)) +\Gm@cnth=\count279 +\Gm@cntv=\count280 +\c@Gm@tempcnt=\count281 +\Gm@bindingoffset=\dimen149 +\Gm@wd@mp=\dimen150 +\Gm@odd@mp=\dimen151 +\Gm@even@mp=\dimen152 +\Gm@layoutwidth=\dimen153 +\Gm@layoutheight=\dimen154 +\Gm@layouthoffset=\dimen155 +\Gm@layoutvoffset=\dimen156 +\Gm@dimlist=\toks18 +) +(/usr/share/texmf-dist/tex/latex/fontspec/fontspec.sty +(/usr/share/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +(/usr/share/texmf-dist/tex/latex/l3kernel/expl3.sty +Package: expl3 2026-01-19 L3 programming layer (loader) + +(/usr/share/texmf-dist/tex/latex/l3backend/l3backend-xetex.def +File: l3backend-xetex.def 2025-10-09 L3 backend support: XeTeX +\g__graphics_track_int=\count282 +\g__pdfannot_backend_int=\count283 +\g__pdfannot_backend_link_int=\count284 +)) +Package: xparse 2025-10-09 L3 Experimental document command parser +) +Package: fontspec 2025/09/29 v2.9g Font selection for XeLaTeX and LuaLaTeX + +(/usr/share/texmf-dist/tex/latex/fontspec/fontspec-xetex.sty +Package: fontspec-xetex 2025/09/29 v2.9g Font selection for XeLaTeX and LuaLaTe +X +\l__fontspec_script_int=\count285 +\l__fontspec_language_int=\count286 +\l__fontspec_strnum_int=\count287 +\l__fontspec_tmp_int=\count288 +\l__fontspec_tmpa_int=\count289 +\l__fontspec_tmpb_int=\count290 +\l__fontspec_tmpc_int=\count291 +\l__fontspec_em_int=\count292 +\l__fontspec_emdef_int=\count293 +\l__fontspec_strong_int=\count294 +\l__fontspec_strongdef_int=\count295 +\l__fontspec_tmpa_dim=\dimen157 +\l__fontspec_tmpb_dim=\dimen158 +\l__fontspec_tmpc_dim=\dimen159 + +(/usr/share/texmf-dist/tex/latex/base/fontenc.sty +Package: fontenc 2025/07/18 v2.1d Standard LaTeX package +) +(/usr/share/texmf-dist/tex/latex/fontspec/fontspec.cfg))) + +Package fontspec Info: +(fontspec) Hurmit Nerd Font Mono scale = 0.7. + + +Package fontspec Info: +(fontspec) Hurmit Nerd Font Mono scale = 0.7. + + +Package fontspec Info: +(fontspec) Hurmit Nerd Font Mono/B scale = 0.7. + + +Package fontspec Info: +(fontspec) Hurmit Nerd Font Mono/I scale = 0.7. + + +Package fontspec Info: +(fontspec) Hurmit Nerd Font Mono/BI scale = 0.7. + + +Package fontspec Info: +(fontspec) Font family 'HurmitNerdFontMono(0)' created for font +(fontspec) 'Hurmit Nerd Font Mono' with options +(fontspec) [WordSpace={1,0,0},HyphenChar=None,PunctuationSpace=Word +Space,Scale=0.7]. +(fontspec) +(fontspec) This font family consists of the following NFSS +(fontspec) series/shapes: +(fontspec) +(fontspec) - 'normal' (m/n) with NFSS spec.: <->s*[0.7]"Hurmit +(fontspec) Nerd Font Mono/OT:script=DFLT;language=dflt;" +(fontspec) - 'bold' (b/n) with NFSS spec.: <->s*[0.7]"Hurmit Nerd +(fontspec) Font Mono/B/OT:script=DFLT;language=dflt;" +(fontspec) - 'italic' (m/it) with NFSS spec.: <->s*[0.7]"Hurmit +(fontspec) Nerd Font Mono/I/OT:script=DFLT;language=dflt;" +(fontspec) - 'bold italic' (b/it) with NFSS spec.: +(fontspec) <->s*[0.7]"Hurmit Nerd Font +(fontspec) Mono/BI/OT:script=DFLT;language=dflt;" + + +No file main.aux. +\openout1 = `main.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 11. +LaTeX Font Info: ... okay on input line 11. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 11. +LaTeX Font Info: ... okay on input line 11. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 11. +LaTeX Font Info: ... okay on input line 11. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 11. +LaTeX Font Info: ... okay on input line 11. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 11. +LaTeX Font Info: ... okay on input line 11. +LaTeX Font Info: Checking defaults for TU/lmr/m/n on input line 11. +LaTeX Font Info: ... okay on input line 11. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 11. +LaTeX Font Info: ... okay on input line 11. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 11. +LaTeX Font Info: ... okay on input line 11. +*geometry* driver: auto-detecting +*geometry* detected driver: xetex +*geometry* verbose mode - [ preamble ] result: +* driver: xetex +* paper: a4paper +* layout: +* layoutoffset:(h,v)=(0.0pt,0.0pt) +* modes: +* h-part:(L,W,R)=(72.26999pt, 452.9679pt, 72.26999pt) +* v-part:(T,H,B)=(72.26999pt, 700.50687pt, 72.26999pt) +* \paperwidth=597.50787pt +* \paperheight=845.04684pt +* \textwidth=452.9679pt +* \textheight=700.50687pt +* \oddsidemargin=0.0pt +* \evensidemargin=0.0pt +* \topmargin=-37.0pt +* \headheight=12.0pt +* \headsep=25.0pt +* \topskip=10.0pt +* \footskip=30.0pt +* \marginparwidth=57.0pt +* \marginparsep=11.0pt +* \columnsep=10.0pt +* \skip\footins=9.0pt plus 4.0pt minus 2.0pt +* \hoffset=0.0pt +* \voffset=0.0pt +* \mag=1000 +* \@twocolumnfalse +* \@twosidefalse +* \@mparswitchfalse +* \@reversemarginfalse +* (1in=72.27pt=25.4mm, 1cm=28.453pt) + + +Package fontspec Info: +(fontspec) Adjusting the maths setup (use [no-math] to avoid +(fontspec) this). + +\symlegacymaths=\mathgroup4 +LaTeX Font Info: Overwriting symbol font `legacymaths' in version `bold' +(Font) OT1/cmr/m/n --> OT1/cmr/bx/n on input line 11. +LaTeX Font Info: Redeclaring math accent \acute on input line 11. +LaTeX Font Info: Redeclaring math accent \grave on input line 11. +LaTeX Font Info: Redeclaring math accent \ddot on input line 11. +LaTeX Font Info: Redeclaring math accent \tilde on input line 11. +LaTeX Font Info: Redeclaring math accent \bar on input line 11. +LaTeX Font Info: Redeclaring math accent \breve on input line 11. +LaTeX Font Info: Redeclaring math accent \check on input line 11. +LaTeX Font Info: Redeclaring math accent \hat on input line 11. +LaTeX Font Info: Redeclaring math accent \dot on input line 11. +LaTeX Font Info: Redeclaring math accent \mathring on input line 11. +LaTeX Font Info: Redeclaring math symbol \colon on input line 11. +LaTeX Font Info: Redeclaring math symbol \Gamma on input line 11. +LaTeX Font Info: Redeclaring math symbol \Delta on input line 11. +LaTeX Font Info: Redeclaring math symbol \Theta on input line 11. +LaTeX Font Info: Redeclaring math symbol \Lambda on input line 11. +LaTeX Font Info: Redeclaring math symbol \Xi on input line 11. +LaTeX Font Info: Redeclaring math symbol \Pi on input line 11. +LaTeX Font Info: Redeclaring math symbol \Sigma on input line 11. +LaTeX Font Info: Redeclaring math symbol \Upsilon on input line 11. +LaTeX Font Info: Redeclaring math symbol \Phi on input line 11. +LaTeX Font Info: Redeclaring math symbol \Psi on input line 11. +LaTeX Font Info: Redeclaring math symbol \Omega on input line 11. +LaTeX Font Info: Redeclaring math symbol \mathdollar on input line 11. +LaTeX Font Info: Redeclaring symbol font `operators' on input line 11. +LaTeX Font Info: Encoding `OT1' has changed to `TU' for symbol font +(Font) `operators' in the math version `normal' on input line 11. +LaTeX Font Info: Overwriting symbol font `operators' in version `normal' +(Font) OT1/cmr/m/n --> TU/lmr/m/n on input line 11. +LaTeX Font Info: Encoding `OT1' has changed to `TU' for symbol font +(Font) `operators' in the math version `bold' on input line 11. +LaTeX Font Info: Overwriting symbol font `operators' in version `bold' +(Font) OT1/cmr/bx/n --> TU/lmr/m/n on input line 11. +LaTeX Font Info: Overwriting symbol font `operators' in version `normal' +(Font) TU/lmr/m/n --> TU/lmr/m/n on input line 11. +LaTeX Font Info: Overwriting math alphabet `\mathit' in version `normal' +(Font) OT1/cmr/m/it --> TU/lmr/m/it on input line 11. +LaTeX Font Info: Overwriting math alphabet `\mathbf' in version `normal' +(Font) OT1/cmr/bx/n --> TU/lmr/b/n on input line 11. +LaTeX Font Info: Overwriting math alphabet `\mathsf' in version `normal' +(Font) OT1/cmss/m/n --> TU/lmss/m/n on input line 11. +LaTeX Font Info: Overwriting math alphabet `\mathtt' in version `normal' +(Font) OT1/cmtt/m/n --> TU/HurmitNerdFontMono(0)/m/n on input +line 11. +LaTeX Font Info: Overwriting symbol font `operators' in version `bold' +(Font) TU/lmr/m/n --> TU/lmr/b/n on input line 11. +LaTeX Font Info: Overwriting math alphabet `\mathit' in version `bold' +(Font) OT1/cmr/bx/it --> TU/lmr/b/it on input line 11. +LaTeX Font Info: Overwriting math alphabet `\mathsf' in version `bold' +(Font) OT1/cmss/bx/n --> TU/lmss/b/n on input line 11. +LaTeX Font Info: Overwriting math alphabet `\mathtt' in version `bold' +(Font) OT1/cmtt/m/n --> TU/HurmitNerdFontMono(0)/b/n on input +line 11. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <7> on input line 14. +LaTeX Font Info: External font `cmex10' loaded for size +(Font) <5> on input line 14. +LaTeX Font Info: Font shape `TU/HurmitNerdFontMono(0)/m/n' will be +(Font) scaled to size 6.99997pt on input line 22. + +LaTeX Warning: Float too large for page by 44.293pt on input line 93. + +[1 + +] [2] (./main.aux) + *********** +LaTeX2e <2025-11-01> +L3 programming layer <2026-01-19> + *********** + ) +Here is how much of TeX's memory you used: + 3526 strings out of 470191 + 106539 string characters out of 5479698 + 562689 words of memory out of 5000000 + 32135 multiletter control sequences out of 15000+600000 + 627857 words of font info for 57 fonts, out of 8000000 for 9000 + 14 hyphenation exceptions out of 8191 + 73i,9n,93p,432b,328s stack positions out of 10000i,1000n,20000p,200000b,200000s + +Output written on main.pdf (2 pages). diff --git a/language/main.pdf b/language/main.pdf index 6d031a83fd1358c25fc28a1abafde7f0f035a8da..28d0d6e35c3049a3907ca01f9e217832091acaff 100644 GIT binary patch delta 18525 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 delta 14980 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 KF0Lp6^Zx-J7q1}z diff --git a/language/main.tex b/language/main.tex index 347f017..b64a1d2 100644 --- a/language/main.tex +++ b/language/main.tex @@ -59,6 +59,7 @@ \languageline{expression}{\texttt{FVNCTIO} \texttt{(} \textit{optional-ids} \texttt{)} \texttt{VT} \textit{scope}} \\ \languageline{expression}{\textit{literal}} \\ \languageline{expression}{\textit{expression} \texttt{[} \textit{expression} \texttt{]}} \\ + \languageline{expression}{\textit{expression} \texttt{[} \textit{expression} \texttt{VSQVE} \textit{expression} \texttt{]} \textnormal{\small\ (inclusive slice)}} \\ \languageline{expression}{\textit{expression} \textbf{binop} \textit{expression}} \\ \languageline{expression}{\textbf{unop} \textit{expression}} \\ \hline \languageline{literal}{\textbf{string}} \\ diff --git a/snippets/array_slice.cent b/snippets/array_slice.cent new file mode 100644 index 0000000..8838f03 --- /dev/null +++ b/snippets/array_slice.cent @@ -0,0 +1,2 @@ +DESIGNA x VT [X, XX, XXX, XL, L] +DICE(x[II VSQVE IV]) diff --git a/snippets/array_slice.png b/snippets/array_slice.png new file mode 100644 index 0000000000000000000000000000000000000000..6f09fbcd1aeb824a4a0ec3f77c6cd75a55f99231 GIT binary patch literal 15738 zcmeHudstIvzHSheszs`(sYOXEMMkYgrGiKx-U*qE*r)*vuEStoAlCdJ}2b!U>+P_bI4&%ql_G?43?%Zl#Z4qLk<2q+a|)Qk&yEx%JDQg zb4_qZ9Wyn<9zQEHGIhkwa~qqR;t{W9p+h+wbsW5z5g2saymxkXiQ zsvyz$TH(W4<}e5wA0hR$uc+#BGee!*^~g%}mA*Q!=XiI8(!GRnIg*p@p|x)(H#h}c zncn2ba~$Xx4PBVo*DW@@B%7P%huc>e?!eeNd5V-|6d5mwj7Q{2qbtn9-s)Lt=}&pi zrRFc1HpQ=ZuQ86gD-1j6$F%oYkF4X$ih3oL+x)D}>FszpjcL*N4Q@#MhN&h(eRFxx zlew8$^0j@PjBg6VD2F>Bany+2XvOMuvP5JK;C*y_b+BLx=- zl>Q3~Md-)f6!mw>6SLof(O|yS(L}y32WXCMEQcDepGFUpX@CW@_ zIQ5&f2&+5zYs9XPQtL_ZR|hp*UPk{hahkc{aB=ysfyNv-F}sQS&5W8&@t2H4qF>v6 zyf?V1m?TzxpYYdyBaNQld`F(XNqRi~vT?eo>iD~8iM_jNF@75kQo#Sp^j@Iyk@-sD z0ZDDF{_SjHLq$&pca(>@WR9;kovD;2KfUY6hQ-{KXyKKV!<9C&iA8g+;r4n^7i30q zZ+i^*lF*1nH&+<~X||21?gsUPA590zw#Sl};oNyrTCA(mXlB-&s47{b=NaitQ!?dI z*G@UhXhams^dMgOpgY?cX zawu=WK80*Eurym41Fcp*@=yc^(_jaS!0wizDc&5jmyyh|?}6)RPMw>7M3`ivmAjmb zy|P@}oE0Zvcau%w&{+1*O(BX=cc`dPl;NvmO{hJs)eMf;Nn_@|!a!p+6D@7C#|aAK zs)vb+Q*L`K2PKMDXaTt`gGiFHP{b>#J-f+({~N-%_tq+79M!yGQCY_n!$zhvt*DE; zS{fJPZRn($zKmj-d^!9;>l}N$Yo^{YAdbGP80e&%uCA{he|ugngVI}RbCfvO6Z8`& zsS(RUN_*$hD$Qb>*)QFX>Ab9LyGk0nj>MFkt8>y7V(06DdyF z?|Wq0K1pwmQ9N*U-)EX3%m@~lOuHrK?jkjG*^jcnIWR+(L1>FnhliRMcz^w70nIwn z%{k9ks*9DHdD77tv@c9sl}AVf^CfG(RC2=Yt;T-OP)7=VU_i{)ih~-k_i5~we5Sq3 zLAWTb=cj8{QXZ{dDm1(ho0pT}hG4jTnV{QK@JoMT^>8Rb<8Sm8a%OqFf2P?lePUG7 z(#kY;Fq2PfC;mqsS4u)(gi=jUi3GMWjLgPZR1nExYaO*)8^*OyA&}8m)AX1w=4?IO z>95<+M9h#$%_^@5bF<#8K?2{gk`LRhJ{3yis9R!^_B&9tTFnPU_VbeGt?4rdvz3lQ zvX+I}TiM)?2P-u7`^x`N)WvztFU9*oc5zn1m)dutlGSS@)=kO_;ywn2<1Nn9X%csX5xPxg|X6<thuQ8P zLq9o8tD3hv$6v00SwQXpmHlLv!thdpu1F6M+2@j)SL@8w=BuP?)qMH^&&zpaIV_U_*gMv0_Ia7ZH zGyrZki(9z;aIsZ5w3Tjob57JmI9$={#QUFhn2+c37Fjm2{~sU2Zv5kmvN!(sj{Wn8 z`C(@wJQopdFD+-xKt*p`N&R=}cFzi>9vh7`>Wx2PaXU2R2E(R1#Ve zbmW)5^9+E+V&tI)4_ed|!&5lnC_nwSyZ3}D2rDSw@WR+a7Ei13k0)8P{8qVG2N~rx z;niK!J<<$CM9s72yhv`vN`fHKQA4F9&Zwbb52n#g4FT+~<64B4GW1o`3Ru2?AT7^O zkp$&aRV7d_XmMY9QATQ$=@+;A1=DQ<_XzC9QCG}R?@ORMXA#-W#BNozhrs-x=%3yl zYmO)$VGr=Tr>GW+J&-z2J^>jcN2z=nhmL23use2O!*3uSNj*3Cs>_}{7uEAhh<~+{ zgWg5eGnDNB86y;{T}DtXv>@+L$Ad}rkB6p6OW2vW@9YMir~6F)Jg)g)ycW!U>@{Ytf7IN=Ejr{ZK&Xn!1`i+Vo`$KXheZ8&Wy z*Q%Ex2BpZ>3p31h5Uk0v81c>RynRIy9V&4SYJ}cE)5Lrz@{^;FPnaMqLn)sn8JCm{Q|{!V})WU zmuLQ-T_+3uU>Tlgw_EWJm`&Sb+{sKYA~twcPptX4_ZNmecaOmEtuHNo=(ISsuMc4w zPKq+ld|E!j=kDX<-Pu!kUwu4$FaC1TpEZqvg;<*8j70_Y)7KK33t<+|aKXRR0;I4!jm`-Ey)dF$V7 zlbq(vC$lmJlDXPb%KJxD^W%RkiaLe8j=yK0`2>OCjIi%0J_;lq8a@!AqkN0CMl2HH z{oXafQS7Q5KOVyw4h*Sn{N4c9X7`AddO_4z#dJiok19B8Am?gp zSWeX!3j0>tt=qqo{O(`AeVLt+t%5E-ZSrn*uF_GD6TdpR0_`VNU!vNwm>L?|TWGrq zW7D}NF%^H4v68oUd&x}kpqUnhPJBq%S+@!{`3YNCn7S~bDFbSRt~;+*y1W`*dM7>y z63MtPX!v+WFnB>|&bdtVc) zs&he8%oG((zX;SpWq@gU;Erl^>pgZ?^RahPe=tWHRm1ef_-Wx^MacCZ{kd)#v04yx zv+pK-p>z`&p6o`Lrjw$oO*f;STWVKG#ui|2fiMn!*0Mi?BzX|dG{VjQ{@-Ik{OkX? zfRJ1-uH#KxX3Eb+x2@AA6%a%N^(ya7Qv3#xe}+c-<> z;M(E<9_M;h>-ox)LR*!`J{A@r5bn}Q8cLy+-?gk?Y)pm>kGq<4@VZhk3CJ8Fnp)ziJ0lE<{nyWl8iyCuVyiECS_)>8Ka31yKaI4lRgCSZJ`&d6T20cS_$d!BF4L&2G!a6P{wf z5IBJ4Q0;eI^DgAd*aN@SMm-6t#}+_iF>Z@idWnoJzg0OU6+K1lBspKWgta!tN=&~M zMGKFrhW^tllf_#r*(Yg&5nOxuKPnN>ZTSJGcUJXr`N-M%?8e2tg zTdP6Aw40;SObssOdUc;ItHe1EJ6A>>|5UCY(Rs2r9&96k6Ue7eJt%}2c??ZaFLuckLCZzNMxc55t;^3()!F#WjYirV9 zGQCZVL6EPpc+mxI(ZYT*3O@h?lLmoqL658zjGlpFg?%0qx!?3E&Bc%d-_D6cOS-9F zBXW_>6v50m9mwt3H&#WkHYmFq0k-~#%M=w6+DGgL**?1#dwctCbALB9KXWv9lBMfqlmRKje+paa)jXVHZ9*O+i=^tm#!b6&dN-#r1fV@ zty=^_@Yk21WGcqpp>J8KPQA96jyX6bGK{Mj9EXLhj5^YOJp8GY(Gsh4;wpAaGZEe# z2^*IZ;E7+)>9Owl*bZ;*)8WUmtpx5cIaJs%G8GJ;`IrZHh`7q|DfwP)oi`;W_Ksnf z=oj~zViphS>Ek0b%XS;68?eT#uR$natf8*#==QDtLuhD)N8H?tefJ*&(&=v9{IuYjz826Kgd*G&7Nno)5 zqAg;|YGJX8`Xq-switx9ixnip)JvY&Il6t0z6ED;2~RwwQatL}W5*R|b{(LIPqpCT zOOR)vqKaFV_t87Zc!;NRg1-VUrJTB~aY<8n2f_M;`njq6jwd$%;3e~^Lgj0j$$UZm zRVK$DrLxrkiw*)TYRcs$!?KLr#TtJX1Hhtq=%@bUgY>h0q5GQ)1ozb|mDcr^v>sVk zbf_l*N5owk=%;^ja2mkT|LB(g{i`a6d8nFDh}}hBk!RnsDUYe(vpwvMx=@P@Q81t& z0%*#+4WD{IF#=)RIjH$yc|FrPKuj8KCiYc0hlJeerO`ZX%(|#AE2;@Ko64ZAsPCm* z$2C9t#p-UAJHu#p=?W>&rDn**Ceitz{CLUROj8S^@ynEaZOOo7En<&=!Gzeq#)CUc zXR**6Gf@AckWWI_Z}`dzBYpU5r@3~p}xJ^{|%0wV2*TV|zhp=}tZs;7NaNQLB2ZKZw`*KQ>8 zt&{y>T+I}w`GDVx&*$mH0L4Bp)e#b8AwH1P5=Nocokbo>qf~K$w$SUI|TqrTe<-PAKt+tln)Ee!KlMWAdLQy+aI&a5Wq~y2anDL_l&I? znoVH!_?u)9R6i>}07A=4%#k$q^m{hZ`>!|ikhW6vRavLvt$-!O0B3tPn)20~9xuR1iO)OfN^;dY zM;0s5-sQuNCr$`jJkX);WLX8QKDx8c7pJUeXEudeZ*m?T5w*bm>RSJDWkXeonalxE za9Wl=NF%6Ns6E`;2U(Zy%9HCsQ%~G5Pdt(5xgi{b{`&1yLLI^A2 zmV{pr?9n?d=-v^3i=)sFd!vqB5B-o++J78EGsT=wq~VOn3I?N|SfyA>5bJ$~hS;oM z-^X5fCplwpT`X4hchs#lR~+^glk+vWcdk%3`ZZV?S_U})(b-GO0FpoEy6ygqRGTty#w@v1=O)z@7ur-X-loQe)_iAVsA~yF{R1Jlvzbg}@CxWI6pH-r*9o0m~u-H+@&8eeJQ+1jZXMaL@N& z&sH)U0gT4pf(&9tJC2ie>m4z2eG@dC0VGr9X)sN+R{$-t7s~ewInpe`bl$Y|meZfA za6TlEQ`IMDTAtLCk(aA1mA}fYPegDbAP!c77DqEIYP*Bz7$N7xY0gM6gMbFsFN0V- z(66>E!`ohKp+u3W6N7?7jeM@NXHxRGz)U~(FMq)wN>JL~!bA zsfbnN7^Ppfo?vtjaQPE&G3?{4N!ew0wQ+{vIOl@WS?Xs>5n(ftn6!WO3lcz+$pVz% z1*Adgodm;3r4MS-=dro>0*|-nJ}|GAnku33%?jN(<0v-spZ_y9_s7LO@u(2zq#(Jh>JAh0+6L19|$GUcV$$$nE4HylReqBU3sN?Mo z-;|~HrdWg@{+}M}?!h$Se7!r^3n{|B-m~XX=d?&? zYaWw&3fwCnAUlzEq#?umaNRd3d=AJt=^-&>o%xDaL~5sS@1eLvYy>Zl1nd+CE)8l=~mg1w=)*CXN!%$FU(m;9)GyoD*g7- z=BXHC|I#_NJFtLDA8j^ZI}Xg9gD~$wmP&f_x!EfWz&Dl z?J^aU-fVK!Ra)7A`DhHVbW`saVh6KY*U>7R^fJ4Ud2j`OP#1)W7cJ^(bsb%-XwUhw z=t5Li+6Mk?T}=S+*#PPKelG69fnHyZZ9&Hpm5oZuK-T9T4moXZ&WjoM7RXFjh8ej{ zlvgWXypRZp{r@HB#zt>wSZXZcIdedUQyW}yc! zxfcJ*%f$itM zcLIy1tE>}%re032on<=HEu##6vx1-t4g?(b&j1E4!L`zh?Nc&kX}OD+)VqfCO{}A( z0@lsZkxMZyTLFOQYjouCtOIuls&V?htk;aBULbS<9)iVa($$X2^(UW_K^?8nN_O7h ztGReDv=uaE_-j*yuLC#7ZqRXTUx5^zU#?8bIHyE%q-p#GGxh2oW;@t5w7ml&@s2vp<=j!3 zRQ8UAgTiO*je>@*l`HYqg7zmW+W=B>1>DX8x?_LnrNT1Kw14EsLBdiSM`HzJzs@IE zioL)fvl9T;ITGttV%q_in&GO(*>k3-5@}JUSU5S`O!U)Pt`w#!RCn_dTekwC5Ld6; zL2VY?@gbB%e5O$6=9wS4wR5f{S2~cFB+QjC9NoW=CDdMzr5U(P=PtlUdv~kDpivs< zX=K_*_X0F{lw&vXct?mfocVwaS)^GtE8wmyQ@#h}m$#E>Ei6Ia#t9Lh&p3Da$k+5y zU+QUM0}ruRn#U?3w@h)yC{ueb5T1kO146$QLO#Mt{L?rd04^NIvPtDDM2lTe+FQw! zq78wBra&Elgp-Tz9@SfIfhquC!H~)p1=@nVzdkgX7hFBFx+qLOHXYZ2XOmAeumVW+ z;F_z#=+4N-ma`PBb5h4WVej?W2*V)BuoKyx{*H2B~x=J#NvP)_)Z>UxLXBap_P!%f+v zZf5!OJ{N}5hujD#(0mr>IO#iFG5@c+RZ#zozk3bzvsd?<;Flr%j}0 zC*Enmm@#lYmM#cP>l6X8RI~j<+N6U9cE}iwIqETESP~qY2lUI24)g&BSP0BbfHH{&RomhH$6C4IM5kBH0DTx zbJA#9TVh04vzJ7zeZumh{Bc=`tcd-3pSt{^Qofo<-vf$v}J4ko^}}~fGO(>5)u=1`%beL0OyAJN=x{nMK{awR@?ms zLY%pSem0V0^cZ+2Py+aID~r)u9E0UUA7!^Vmux_NAp?t17iU4&6q@}dk5^>4NO|)l z&86wfcIOO#?#^e&&k4cu@khcFgOSu!MYMj$K=&y$M;Li!3sCX0EppL3qiDzJa>g<> zwL2$dEUrQcbfozL;ch*efiF?~dgoe-xI|&|A^>6PHGvQ)TD7GTYnTD~IV*!Z$P0A| z=3EM^_AAWsr-&mnvUz)-$0bWozymz2*9(k<|HyZMY#u|x@jFBuqF%%fT|4DCzXbLD zZGyzDWo9$pV8H6T^-%h#-TO$XK7J_yHh~b!m_!BvQ?cWc=i$&2i^B;!m!m$TKn0^B zl_D3_HE-jpXKS_728WJCvPT?ub}`h-p&bmh53shp5;>Ro9^-SK9WNiEDmygp^23_> z1U7DbJkVDWVw_;80qc@15dKGJfS{WZVsiw2u9#JWlWPlD2{3f3T0OJx9^YwOK3DhcwC+{xQ0O4^H>3vrf6YV|qiCKC@i`E1g9V z19F)SA|O~gsu$Y(2;j}*wec8uu>&q|miPz`J46P#x8tmM%HE3V8W65?Jl?;%j#kwd zh!d7YP$|rQ!16y6hS0`;Ay>?(>D^}PFA=e?e6tpJB#@nRy^u&wbC~>fK$WA)1Ym4- zih-R&Gno`ACZNa_W51(SnFA}7`1}erHy3A_&U(=cpqnL1XJw|1k33caH>sO4;WDuy zr+67*u>%DR*uWLwr>dF3zE$@spegiB4b;l>tqqU0$L6bDraPFZ}JAi z_q3p7HQ9Qzam{Q{@FaoP04ma}RdfM=(W{!hSOk9m^uWAcF^hWJ|$jJ($ zJOZt-|5rSHS7FR*xL?ok*ISQ zE5~>4UL>56Nv%rm=fY6;!&3QYHhbU;b+q5C{PH1A+&>hFj~$AOYOSp5<>Bm@%jfQu zNQ*Fixzd@#e6ZN!Tu6SXLjfBmp*GICa}l3y-NZ(DfTo0PI3k+;n^gt?qaV7V>@e!9 zcJ{VU;u?fVU7-1|k3VKn*3i%ix8FqA=6eCNcGGSYm&n}!A1D4ZI$CkENhXWEt~4()@4)cn0R0JX|znp*2LFs1%xJiyTz|P&PRaI0Gz& zFE10X-#zN+T&uNl`rDap=8*rU3HvohmRbe#Arv?dQrz> z_4U|c@_3g!cPysEf2$!9Vu9hfTGdQrBp#|v7`>E-9W;O8R$~j#`fILyu4r}U#VH;_ zQ;s-i=;WyfxDt)}y0y-?3|F?m4NcW8$N1IvR{Q?YzBTwnDgFIB+`_CL z>jnbFc#p9pS)DC*F5y)VY_-X{qKY)R3|lx`8i+0gQ0mP|GXlxcZuw#0p)(~QUd0{m zol9;z*wx3y3yAH~csEXjxv0Q3=7Ok^j1oCxE14~D*yi5o!0J`l({^nwu#*#1Osx0R z^EM^ooI@U0dm*e>2VM47yfq0CTIV1hIQOjK1`0SF^eX*&8=Grcroi z%|s*a?k_cvfbn}`Hf}?4t|gxa4m{{)b@%4EDM{e=Y;FM2Ul$mW3+0fUS?k1%kE`vu zfiBj&CAsOCvaEb)iy1gzc-8S!47(wt?Y#qj>obsZlGX4yQ7E0Y78u1Bh$hy_^G9GGqhlc#-|atz1HaHKMB$&BD2XmA;5 zSzq#A?tMNhQ)nB=Ido`VS><&tT(>%caEJ+*4*=uvH8K%tNIXy!2qN@T5?Ekr%Q)Ed z065e}0tJ08#94n%v>;W>GTp=eX%mxJJIarlAwE1zy_hz2-FAkCQb_*j}?WYA1=640G!%> z>?@J%F^9jN=W4L-hE8gm0%+yqS^^uet1X}d8IFPWJqOHy1kk&(!<422V7A5e@I6}e zGIryBgrt67Afa4aeU8sHx}%kgR=N=)7Aw_&V6v0L42*|B0AmRqv0S|fUX%$6`AYVU zEZ85*Z)lkZ@c|!71uk zTJ@V!TI4LSE9QLyan)i_kSA8#tc;NUR>j_er(P~KP4Lh$V(|7iJwxq$j~9$WZ03tL z=Pr}zLc3h#iw)p$33f98Tbc2DYbVwD`p!CUsT7EONf|DgSy9+!%A=o^8h5%e*~JQ6 z@x<2gErM=k=y+IH@ckTs{$*)4sfJ;~bH$Pdz{(lo7R^KWE3nZ=jGAWQ*_PlrzDYIv0uCH-?~!;dDJj<1j8btYu@IAaW8M@%kKBdT@q8ji;#OwJmNU+!>R^@jV(RtdEOK>lMSq?3h@+;c8@67bDN!O*xbGQr@! z14uST-aN|L|GI3okv{R*V+u~u8NRP>%lH;8k3A2Iqw+XlKyxYB&vgMngOSL z7;YAh%1>lFibJR-(GlH)dS{1#WD`xC9cCN{nmw4E8ZUYBG+Pp*^*0ces5*pI>{#Lb zHF!Nl)X+y@j~rKC1{)lHqKN-OBHZ}-?-(y;$!mUFlYc>^IR;Eki4PfbdQoAqvg&vtvlc8OT>Wtw!%W-O=fDa9B zJy1npAD3V|pki?Xe@tVl? z1nl*~y-n}nc6LxO88u>LEY<`jhT|aY0XlHQ?Y=-X?@b0f%-*2Sn{z&_$8-QEP{_7o z*gkjC@yXRMlk3yC#&*uevS8cX&7Yw@|AnVzM}Itr>{NRlil2v8%2O?gUZm0GlrWm)sKV2O~|wHk{-o z{BBL3Q)!X~0WS@@?ym|2bXfP`!xq0NcT)}#;3lA|ZpquxT8t~Lpo>cvW?QFUiVEvKB*~GPZpcinOGtz5PSZXcG6l;EVbbwZdHf}7(&-vHCQVs(U^quipC=$FK>EH<(ADx5Jh zpKS@u*fGfv?3`2)>`d7%Q#bfB@e<8c9@j9A#02lUX&d%aG`hyEIv{!G!|eSDqvM{^ z$_~_bW!R+odOJ8;?65;9rzF<$Ng`Hh2)<^=TKDmY%@l5YYese~&HxA^ to + ("CVM SVBNVLLA\n[I, II, III][-I VSQVE II]", CentvrionError), # slice with negative lower bound + ("CVM SVBNVLLA\n[I, II, III][I VSQVE -I]", CentvrionError), # slice with negative upper bound + ("CVM FRACTIO\n[I, II, III][IIIS VSQVE III]", CentvrionError), # slice with fractional lower bound + ("CVM FRACTIO\n[I, II, III][I VSQVE IIIS]", CentvrionError), # slice with fractional upper bound + ("CVM FRACTIO\n[I, II, III][I / II VSQVE III]", CentvrionError), # slice with division-fraction lower bound ] class TestErrors(unittest.TestCase): @@ -1517,6 +1526,63 @@ class TestArrayIndexAssign(unittest.TestCase): run_test(self, source, nodes, value) +# --- Array slicing --- + +array_slice_tests = [ + # basic slice from middle + ("[X, XX, XXX, XL, L][II VSQVE IV]", + Program([], [ExpressionStatement(ArraySlice( + DataArray([Numeral("X"), Numeral("XX"), Numeral("XXX"), Numeral("XL"), Numeral("L")]), + Numeral("II"), Numeral("IV")))]), + ValList([ValInt(20), ValInt(30), ValInt(40)])), + # slice of length 1 + ("[I, II, III][II VSQVE II]", + Program([], [ExpressionStatement(ArraySlice( + DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), + Numeral("II"), Numeral("II")))]), + ValList([ValInt(2)])), + # full array slice + ("[I, II, III][I VSQVE III]", + Program([], [ExpressionStatement(ArraySlice( + DataArray([Numeral("I"), Numeral("II"), Numeral("III")]), + Numeral("I"), Numeral("III")))]), + ValList([ValInt(1), ValInt(2), ValInt(3)])), + # slice on variable + ("DESIGNA a VT [I, II, III, IV, V]\na[II VSQVE IV]", + Program([], [ + Designa(ID("a"), DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V")])), + ExpressionStatement(ArraySlice(ID("a"), Numeral("II"), Numeral("IV"))), + ]), + ValList([ValInt(2), ValInt(3), ValInt(4)])), + # slice then index (chained) + ("[I, II, III, IV][I VSQVE III][II]", + Program([], [ExpressionStatement(ArrayIndex( + ArraySlice( + DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV")]), + Numeral("I"), Numeral("III")), + Numeral("II")))]), + ValInt(2)), + # slice on range array + ("[I VSQVE X][III VSQVE VII]", + Program([], [ExpressionStatement(ArraySlice( + DataRangeArray(Numeral("I"), Numeral("X")), + Numeral("III"), Numeral("VII")))]), + ValList([ValInt(3), ValInt(4), ValInt(5), ValInt(6), ValInt(7)])), + # expression as slice bounds + ("[I, II, III, IV, V][I + I VSQVE II + II]", + Program([], [ExpressionStatement(ArraySlice( + DataArray([Numeral("I"), Numeral("II"), Numeral("III"), Numeral("IV"), Numeral("V")]), + BinOp(Numeral("I"), Numeral("I"), "SYMBOL_PLUS"), + BinOp(Numeral("II"), Numeral("II"), "SYMBOL_PLUS")))]), + ValList([ValInt(2), ValInt(3), ValInt(4)])), +] + +class TestArraySlice(unittest.TestCase): + @parameterized.expand(array_slice_tests) + def test_array_slice(self, source, nodes, value): + run_test(self, source, nodes, value) + + # --- Comments --- comment_tests = [