Cannot understand how does Arduino memory work for program code
Assumption: The developed code mentioned in the question is not a very advanced and sophisticated application, and does not contain large amounts (10s of kilobytes) of data / arrays.



The Arduino code size limitations apply to the final compiled binary of the application, not the source code size, and not the size of the HEX file generated from the source code. As @DaveTweed has pointed out, Hex files will be more than twice the size of the actual binary bytes that need to be written into the MCU's Flash memory. Source code files will, further, be many times the Hex file size, depending on code specifics, commenting and coding style.

A 20-kilobyte binary output would typically represent a fairly sophisticated, complex application on an Arduino / LilyPad - or, an application incorporating a large amount of data arrays or data buffers. The source code for such an application could well be in the 100s of kilobytes!

Even the more complex of the sample applications that come with the Arduino IDE, for instance, compile to just around 2-5 kilobytes of binary output. 




UNO has this capacity in its Flash, the Lilypad doesn't!


About Arduino LilyPads: These are built around lower power but not lower memory specification versions of the same microcontrollers used in the Arduino Uno: The ATmega168V or the ATmega328 (#1). Hence, the available flash memory on the LilyPad is the same as on the corresponding Uno board.


Where did those numbers come from?


The Arduino IDE's support for ~30 kilobytes of application binary stems from the support for the ATmega328 family of microcontrollers on both the boards mentioned. The ATmega328 has 32 kilobytes of Flash memory, of which the Arduino bootloader takes somewhere between half and a couple of kilobytes, depending on which variant is loaded.

The remaining 30-odd kilobytes (ATmega328) of Flash are thus available for user-created Arduino applications, their data, buffers et cetera. 

Besides this, 1 - 2 kilobytes of SRAM and 0.5 - 1 kilobytes of EEPROM are also available on the ATmega168 and ATmega328 controllers respectively.



(#1) While the Arduino Lilypad official page mentions an ATmega328V microcontroller, the Atmel web site does not yield (for me, anyway) any such variant of the ATmega328, on a search. Hence, no datasheet found either.