Domain

Finance and accounting in eTamil

Double-entry accounting, GST with CGST/SGST/IGST splitting, the three financial statements and Indian rupee formatting — all written in eTamil, not in Rust.

The financial vocabulary is not a library bolted on top — it is in the language. வரவு (credit), பற்று (debit), வரி (tax), இருப்புநிலை (balance sheet), பேரேடு (ledger) and மூலதனம் (capital) are keywords the lexer knows.

What sits above them — the chart of accounts, the ledger, GST, the statements — is written in eTamil, in nUlakam/kaNakkiyal/. That is deliberate: if the accounting framework needed Rust, the DSL would not be sufficient for the thing it exists to do.

Rupees, grouped the Indian way

இறக்கு "nUlakam/paNam.qmz";

அச்சு ரூபாய்(12345678.5);      // ₹1,23,45,678.50

Lakh and crore grouping, not thousands. paNam.qmz also gives you காசு_வடிவம், காசாக, லட்சம் and கோடி.

A GST invoice

GST splits into CGST and SGST within a state, or IGST across states. This is the whole of the split, from examples/finance/vaNikavari_pattiyal.qmz:

// வரி_பிரிப்பு(தொகை, விகிதம், மாநிலம்_ஒன்றா)
செயல் வரி_பிரிப்பு(தொகை, விகிதம், மாநிலம்_ஒன்றா) {
    மொத்த_வரி = சதவீதம்(தொகை, விகிதம்);
    (மாநிலம்_ஒன்றா) எனில் {
        பாதி = வட்டமிடு(மொத்த_வரி / 2, 2);
        திரும்பு {மொத்தம்: மொத்த_வரி, cgst: பாதி, sgst: மொத்த_வரி - பாதி, igst: 0};
    }
    திரும்பு {மொத்தம்: மொத்த_வரி, cgst: 0, sgst: 0, igst: மொத்த_வரி};
}

Note sgst: மொத்த_வரி - பாதி rather than a second வட்டமிடு. Halving an odd number of paise and rounding both halves would lose or invent a paisa; taking the remainder cannot. With exact decimals underneath, CGST + SGST equals the total by construction.

Line items are records and the invoice is an array of them:

உருப்படிகள் = [
    {விவரம்: "மடிக்கணினி",   hsn: "8471", அளவு: 3,  விலை: 54999, விகிதம்: 18},
    {விவரம்: "விசைப்பலகை",   hsn: "8471", அளவு: 10, விலை: 1299,  விகிதம்: 18},
    {விவரம்: "அச்சுத்தாள்",   hsn: "4802", அளவு: 25, விலை: 320,   விகிதம்: 12}
];

ஒவ்வொரு உருப்படி இல் உருப்படிகள் {
    அடிப்படை = வரிசை_மதிப்பு(உருப்படி);
    வரி = வரி_பிரிப்பு(அடிப்படை, உருப்படி.விகிதம், உள்_மாநிலம்);
    ...
}

The double-entry ledger

இறக்கு "nUlakam/kaNakkiyal/kaNakkukaL.qmz";
இறக்கு "nUlakam/kaNakkiyal/pErEtu.qmz";
இறக்கு "nUlakam/kaNakkiyal/aRikkYkaL.qmz";

கணக்குகள் = [
    மதிப்பு(கணக்கு_ஆக்கு("1000", "வங்கி",   வகை_சொத்து(), "நடப்பு")),
    மதிப்பு(கணக்கு_ஆக்கு("3000", "மூலதனம்", வகை_பங்கு(),  "பங்கு"))
];

பேரேடு = [];
பேரேடு = மதிப்பு(பதிவிடு(பேரேடு, பரிவர்த்தனை_ஆக்கு(
    "JV001", "2026-04-01", "தொடக்க மூலதனம்", [
        பற்று_வரிசை("1000", 500000),
        வரவு_வரிசை("3000", 500000)
    ])));

இருப்பாய்வு_அச்சிடு(இருப்பாய்வு(பேரேடு, கணக்குகள்));

Four design decisions hold this together:

The ledger is a value. Posting returns a new ledger rather than editing the old one, so an entry cannot be changed after the fact.

Double entry is enforced. பதிவிடு refuses a transaction whose sides disagree and returns தவறு. Nothing unbalanced reaches the ledger — and because failure is a value, the caller has to deal with it.

Balances read in the account’s own direction. A liability with more credits than debits is positive, just as an asset with more debits than credits is. Every report depends on பற்று_இயல்பா.

Reports derive from the ledger. Nothing is stored twice, so a statement cannot disagree with the postings behind it.

The framework is modelled on ekmungai/eloquent-ifrs, with IFRS-style presentation.

The modules

File Contents
kaNakkukaL.qmz Chart of accounts, the five IFRS roots, normal sides
kAlam.qmz Reporting periods, Indian and calendar years
pErEtu.qmz Transactions, line items, posting, balances, period filters
vari.qmz GST and every transaction type
oqukkItu.qmz Assignment, outstanding amounts, ageing
aRikkYkaL.qmz Trial balance, income statement, balance sheet, account statement, cash flow
niRuvaZam.qmz Entities, currencies, exchange differences
mutippu.qmz Year-end close

Account types

வகை_சொத்து() · வகை_பொறுப்பு() · வகை_பங்கு() · வகை_வருவாய்() · வகை_செலவு()

Assets and expenses increase on the debit side; the rest on the credit side.

Transaction types

eTamil eloquent-ifrs equivalent
பரிவர்த்தனை_ஆக்கு JournalEntry
விற்பனை_பரிவர்த்தனை ClientInvoice
கொள்முதல்_பரிவர்த்தனை SupplierBill
ரொக்க_விற்பனை CashSale
ரொக்க_கொள்முதல் CashPurchase
பணம்_பெறு ClientReceipt
பணம்_செலுத்து SupplierPayment
வரவு_குறிப்பு CreditNote
பற்று_குறிப்பு DebitNote
எதிர்_பதிவு ContraEntry

The rest of the standard library

File Contents
col.qmz strings — துண்டு தேடு பிரி ஒன்றிணை ஒழுங்கு தொடங்குகிறதா முடிகிறதா
kaNiqam.qmz math — முழுமதிப்பு சிறியது பெரியது கூட்டு சராசரி சதவீதம்
aNi.qmz arrays — உள்ளதா இடம்_காண் தலைகீழ் வெட்டு புலம்_எடு காலியா
paNam.qmz money — ரூபாய் காசு_வடிவம் காசாக லட்சம் கோடி
jEcAZ.qmz JSON — ஜேசான்_ஆக்கு ஜேசான்_படி

Everything above is eTamil source. The host provides only what a language cannot express — decimal arithmetic, text measurement, dates, file and socket access, and the four bcrypt/JWT builtins that need bytes and randomness.

Worked examples

Run these from the compiler repository:

etamil --vm examples/finance/kaNakkiyal.qmz          # a full accounting cycle
etamil --vm examples/finance/vaNikavari_pattiyal.qmz # a GST invoice
etamil --vm examples/finance/campaLam.qmz            # payroll
etamil --vm examples/finance/niluvY_vayaqu.qmz       # receivables ageing

What comes next

The accounting and taxation framework is the foundation, not the finished set. Four more domains are planned on top of the same ledger and the same vocabulary:

Alongside them: ITR and TDS templates, and REST bindings to the GSTN and NPCI portals.

Planned, not built. Everything in this section is design. What exists today is the compiler core and the accounting framework described above. The status page keeps a feature-by-feature line between the two — and anything unimplemented fails with an explicit message rather than quietly doing nothing.