Copyright (c) 2026 Muhammad Anisur Rahman. All rights reserved.
Version 1.0.0
icpp is kcpp -icpp: the same compiler, running your C in-process instead of producing assembly. No build step, no object files, no target hardware involved - it executes on the machine you are sitting at.
// hello.icpp
void main()
{
int i;
for (i = 0; i < 3; i++) iprint(i);
iprint("icpp works");
}
kcpp -icpp -icppquiet hello.icpp
0
1
2
icpp works
-icppquiet suppresses the compiler's own status lines (Compiling:, Total errors:). Real error text and your program's output are unaffected, so it is the right flag for a script whose output you intend to consume.
| Option | Does |
|---|---|
-icpp | interpret and execute in-process. No .asm or .o is produced |
-icppquiet | drop kcpp's status lines from stdout |
-Ipath | additional include directory (repeatable) |
-Dname[=value] | define a macro |
-llmtrace | walk through every LLM-pipeline builtin as it runs, explaining each step |
The compiler options that describe a target - -cpu32, exe=, -core= - have no meaning here. icpp runs host-native, which is the point: it is independent of whatever hardware kcpp would otherwise be compiling for.
An icpp library is just a .icpp file of reusable functions, pulled in with an ordinary include. There is no packaging step and no archive format.
#include "stringutil.icpp"
void main()
{
iprint(su_shout("hi")); // -> HI!
iprint(su_wordcount("a b c")); // -> 3
}
lib_icpp/stringutil.icpp is the reference example.
By convention a library starts with a block of tagged comments. They are comments, so the interpreter ignores them when running the library - but a script can read them, which is what makes version checking possible.
//@icpp-library stringutil
//@icpp-version 1.2.0
//@icpp-author Muhammad Anisur Rahman
//@icpp-copyright (c) 2026 Muhammad Anisur Rahman - MIT
//@icpp-contact anisfrombd693@gmail.com
//@icpp-requires 0.40 ; minimum interpreter version
//@icpp-since 1.2.0: added su_repeat()
| Field | Meaning |
|---|---|
library | the library's name |
version | dotted numbers, MAJOR.MINOR.PATCH |
author | who wrote it |
copyright | copyright or licence line |
contact | email or URL |
requires | minimum interpreter version it needs |
since | what changed, newest first |
Rules: one tag per line; the value runs to end-of-line or an inline ; comment, whichever comes first, and is trimmed; the first occurrence of a tag wins; put the manifest in the first ~200 lines, because that is where the reader stops looking. Extra fields of your own are fine.
icpp_lib_field(file, field) // the @icpp-<field> value, or "" if absent
icpp_lib_version(file) // shorthand for the "version" field
icpp_version_cmp(a, b) // -1 / 0 / 1, comparing dotted numbers
icpp_version_cmp compares semantically, not as text - so 1.10.0 is correctly greater than 1.9.0, which a string comparison gets backwards.
#include "stringutil.icpp"
void main()
{
if (icpp_version_cmp(icpp_lib_version("stringutil.icpp"), "1.2.0") < 0)
{
iprint("stringutil >= 1.2.0 required");
icpp_exit(1);
}
iprint(su_repeat("ab", 3)); // -> ababab
}
A gate like that is worth writing whenever a script depends on a function added in a particular version. Without it the failure is a missing symbol at the point of use, which says nothing about which version you needed.
-llmtrace prints a step-by-step walkthrough of the LLM-pipeline builtins as they run - tokenising, embeddings, positional encoding, attention, softmax, loss, backward pass, SGD - including why each step is there. It exists to show how a language model works rather than to help you debug one.
kcpp -rtl adder.icpp # -> adder.v and adder_tb.v
-rtl translates the script's integer functions into synthesizable Verilog plus a self-checking testbench, instead of running them. The testbench matters: it is what lets you confirm the generated hardware agrees with the C you wrote, rather than assuming the translation was faithful.
KCPP=<path to kcpp.exe> bash test/icpp_conformance/run_conformance.sh
Prints per-test results and a final RESULT: line. Always pass KCPP= explicitly - the runner otherwise defaults to a binary that may not be the one you just built, and a suite that silently tested the wrong compiler is worse than one that failed.
python(<file>) and java(<file>) - system functions to read and execute a Python script or a Java source file from inside icpp. Not in this release.