🐐 String interpolation
This commit is contained in:
99
tests.py
99
tests.py
@@ -12,9 +12,9 @@ from fractions import Fraction
|
||||
from centvrion.ast_nodes import (
|
||||
ArrayIndex, Bool, BinOp, BuiltIn, DataArray, DataRangeArray, Defini,
|
||||
Continva, Designa, DesignaDestructure, DesignaIndex, DumStatement, Erumpe,
|
||||
ExpressionStatement, ID, Invoca, ModuleCall, Nullus, Numeral, PerStatement,
|
||||
Program, Redi, SiStatement, String, UnaryMinus, UnaryNot,
|
||||
Fractio, frac_to_fraction, fraction_to_frac,
|
||||
ExpressionStatement, ID, InterpolatedString, Invoca, ModuleCall, Nullus,
|
||||
Numeral, PerStatement, Program, Redi, SiStatement, String, UnaryMinus,
|
||||
UnaryNot, Fractio, frac_to_fraction, fraction_to_frac,
|
||||
num_to_int, int_to_num, make_string,
|
||||
)
|
||||
from centvrion.compiler.emitter import compile_program
|
||||
@@ -881,6 +881,99 @@ class TestStringConcat(unittest.TestCase):
|
||||
run_test(self, source, nodes, value)
|
||||
|
||||
|
||||
# --- String interpolation ---
|
||||
|
||||
interpolation_tests = [
|
||||
# basic variable interpolation
|
||||
('DESIGNA nomen VT "Marcus"\n"Salve, {nomen}!"',
|
||||
Program([], [
|
||||
Designa(ID("nomen"), String("Marcus")),
|
||||
ExpressionStatement(InterpolatedString([String("Salve, "), ID("nomen"), String("!")]))
|
||||
]), ValStr("Salve, Marcus!")),
|
||||
# arithmetic expression inside interpolation
|
||||
('DESIGNA x VT III\n"Sum: {x + II}"',
|
||||
Program([], [
|
||||
Designa(ID("x"), Numeral("III")),
|
||||
ExpressionStatement(InterpolatedString([String("Sum: "), BinOp(ID("x"), Numeral("II"), "SYMBOL_PLUS")]))
|
||||
]), ValStr("Sum: V")),
|
||||
# multiple interpolations
|
||||
('DESIGNA a VT I\nDESIGNA b VT II\n"{a} + {b} = {a + b}"',
|
||||
Program([], [
|
||||
Designa(ID("a"), Numeral("I")),
|
||||
Designa(ID("b"), Numeral("II")),
|
||||
ExpressionStatement(InterpolatedString([
|
||||
ID("a"), String(" + "), ID("b"), String(" = "),
|
||||
BinOp(ID("a"), ID("b"), "SYMBOL_PLUS"),
|
||||
]))
|
||||
]), ValStr("I + II = III")),
|
||||
# escaped braces become literal
|
||||
('"use {{braces}}"',
|
||||
Program([], [ExpressionStatement(String("use {braces}"))]),
|
||||
ValStr("use {braces}")),
|
||||
# single-quoted strings ignore braces
|
||||
("'hello {world}'",
|
||||
Program([], [ExpressionStatement(String("hello {world}"))]),
|
||||
ValStr("hello {world}")),
|
||||
# integer coercion
|
||||
('DESIGNA n VT V\n"n is {n}"',
|
||||
Program([], [
|
||||
Designa(ID("n"), Numeral("V")),
|
||||
ExpressionStatement(InterpolatedString([String("n is "), ID("n")]))
|
||||
]), ValStr("n is V")),
|
||||
# boolean coercion
|
||||
('DESIGNA b VT VERITAS\n"value: {b}"',
|
||||
Program([], [
|
||||
Designa(ID("b"), Bool(True)),
|
||||
ExpressionStatement(InterpolatedString([String("value: "), ID("b")]))
|
||||
]), ValStr("value: VERITAS")),
|
||||
# NVLLVS coercion
|
||||
('"value: {NVLLVS}"',
|
||||
Program([], [
|
||||
ExpressionStatement(InterpolatedString([String("value: "), Nullus()]))
|
||||
]), ValStr("value: NVLLVS")),
|
||||
# expression-only string (no literal parts around it)
|
||||
('DESIGNA x VT "hi"\n"{x}"',
|
||||
Program([], [
|
||||
Designa(ID("x"), String("hi")),
|
||||
ExpressionStatement(InterpolatedString([ID("x")]))
|
||||
]), ValStr("hi")),
|
||||
# adjacent interpolations
|
||||
('DESIGNA a VT "x"\nDESIGNA b VT "y"\n"{a}{b}"',
|
||||
Program([], [
|
||||
Designa(ID("a"), String("x")),
|
||||
Designa(ID("b"), String("y")),
|
||||
ExpressionStatement(InterpolatedString([ID("a"), ID("b")]))
|
||||
]), ValStr("xy")),
|
||||
# function call inside interpolation
|
||||
("DEFINI f () VT {\nREDI (V)\n}\n\"result: {INVOCA f()}\"",
|
||||
Program([], [
|
||||
Defini(ID("f"), [], [Redi([Numeral("V")])]),
|
||||
ExpressionStatement(InterpolatedString([String("result: "), Invoca(ID("f"), [])]))
|
||||
]), ValStr("result: V")),
|
||||
# single-quoted string inside interpolation
|
||||
("DESIGNA x VT 'hello'\n\"{x & '!'}\"",
|
||||
Program([], [
|
||||
Designa(ID("x"), String("hello")),
|
||||
ExpressionStatement(InterpolatedString([BinOp(ID("x"), String("!"), "SYMBOL_AMPERSAND")]))
|
||||
]), ValStr("hello!")),
|
||||
# plain double-quoted string (no braces) still works
|
||||
('"hello world"',
|
||||
Program([], [ExpressionStatement(String("hello world"))]),
|
||||
ValStr("hello world")),
|
||||
# interpolation in DICE output
|
||||
('DESIGNA name VT "Roma"\nDICE("Salve, {name}!")',
|
||||
Program([], [
|
||||
Designa(ID("name"), String("Roma")),
|
||||
ExpressionStatement(BuiltIn("DICE", [InterpolatedString([String("Salve, "), ID("name"), String("!")])]))
|
||||
]), ValStr("Salve, Roma!"), "Salve, Roma!\n"),
|
||||
]
|
||||
|
||||
class TestInterpolation(unittest.TestCase):
|
||||
@parameterized.expand(interpolation_tests)
|
||||
def test_interpolation(self, source, nodes, value, output=""):
|
||||
run_test(self, source, nodes, value, output)
|
||||
|
||||
|
||||
# --- Comparison operators ---
|
||||
|
||||
comparison_tests = [
|
||||
|
||||
Reference in New Issue
Block a user