├── CompilerOverview ├── CompilerOverview.md ├── asm.md ├── directives.md ├── options.md ├── preprocessor.md └── scopinglinkage.md ├── HC ├── ClassMeta.HC ├── Directives.HC ├── Exceptions.HC ├── LastClass.HC ├── Lock.HC ├── NullCase.HC ├── StkGrow.HC ├── SubIntAccess.HC └── SubSwitch.HC ├── LICENSE ├── README.md └── helloworld.HC /CompilerOverview/CompilerOverview.md: -------------------------------------------------------------------------------- 1 | # Compiler Index 2 | ![asm.md](https://github.com/SpaciousCoder78/holyc-docs/blob/main/CompilerOverview/asm.md) 3 | 4 | ![directives.md](https://github.com/SpaciousCoder78/holyc-docs/blob/main/CompilerOverview/directives.md) 5 | 6 | ![options.md](https://github.com/SpaciousCoder78/holyc-docs/blob/main/CompilerOverview/options.md) 7 | 8 | ![preprocessor.md](https://github.com/SpaciousCoder78/holyc-docs/blob/main/CompilerOverview/preprocessor.md) 9 | 10 | ![scopinglinkage.md](https://github.com/SpaciousCoder78/holyc-docs/blob/main/CompilerOverview/scopinglinkage.md) 11 | 12 | See ![Hello World](https://github.com/SpaciousCoder78/holyc-docs/blob/main/helloworld.HC) 13 | -------------------------------------------------------------------------------- /CompilerOverview/asm.md: -------------------------------------------------------------------------------- 1 | # Assembler 2 | See `::/Compiler/OpCodes.DD` for opcodes. They're not standard. Some invalid 3 | insts are not flagged and some valid insts are not implemented. 16-bit asm 4 | support is limited. 5 | 6 | Here are example inst formats: 7 | ```asm 8 | ADD RAX,I64 FS:DISP[RSI+RDI*8] 9 | ADD RAX,I64 [DISP] 10 | ``` 11 | 12 | $ Current compiler output pos (inst ptr). Even works in HolyC expressions. 13 | 14 | $ works in classes. 15 | ```c 16 | class MyFun 17 | { 18 | $=-16; 19 | I64 local1; 20 | I64 local2; 21 | $=$+256; 22 | I64 crazy; 23 | }; 24 | ``` 25 | 26 | LABEL:: 27 | Defines an exported glbl label. 28 | 29 | LABEL: 30 | Defines an non-exported glbl label. 31 | 32 | `@@LABEL`: 33 | Defines a local label with scope valid between two global labels. 34 | 35 | `DU8`, `DU16`, `DU32`, `DU64` 36 | Define BYTE, WORD, DWORD or QWORD. Can be used with DUP() and ASCII strings. 37 | For your convenience, the ASCII strings do not have terminating zeros. Define 38 | cmds must end with a semicolon. 39 | 40 | `USE16`, `USE32`, `USE64` 41 | 42 | ```c 43 | IMPORT sym1name, sym2name; 44 | ``` 45 | 46 | `LIST`, `NOLIST` 47 | 48 | `ALIGN num`, `c fill_byte` 49 | Align to num boundary and fill with `fill_byte`. 50 | 51 | ```c 52 | ORG num 53 | ``` 54 | Set code addr for JIT or set module `Load()` addr -- has 16-byte `CBinFile` header 55 | and patch table trailing. 56 | 57 | ```c 58 | BINFILE "FileName.BIN"; 59 | ``` 60 | 61 | See Assembly Language, `::/Demo/Asm/AsmAndC1.HC`, `::/Demo/Asm/AsmAndC2.HC` and 62 | `::/Demo/Asm/AsmAndC3.HC.` 63 | -------------------------------------------------------------------------------- /CompilerOverview/directives.md: -------------------------------------------------------------------------------- 1 | ```c 2 | #define __DATE__ #exe{StreamPrint("\"%D\"",Now);} 3 | #define __TIME__ #exe{StreamPrint("\"%T\"",Now);} 4 | #define __LINE__ #exe{StreamPrint("%d",Fs->last_cc->lex_include_stk->line_num);} 5 | #define __CMD_LINE__ #exe{StreamPrint("%d",Fs->last_cc->flags&CCF_CMD_LINE && Fs->last_cc->lex_include_stk->depth<1);} 6 | #define __FILE__ #exe{StreamPrint("\"%s\"",Fs->last_cc->lex_include_stk->full_name);} 7 | #define __DIR__ #exe{StreamDir;} 8 | ``` 9 | See ![Directives.HC](https://github.com/SpaciousCoder78/holyc-docs/blob/main/HC/Directives.HC) 10 | -------------------------------------------------------------------------------- /CompilerOverview/options.md: -------------------------------------------------------------------------------- 1 | Use `Option()`. You might need to do `#exe {Option();}`. 2 | 3 | `OPTf_GLBLS_ON_DATA_HEAP` without this option, global vars are placed in the code 4 | heap which is limited to 2Gig. In AOT modules, global vars take-up room in the 5 | `.BIN` file, so you might want to use this option, instead. You might wish to 6 | turn it on and off around specific vars. A disadvantage of data heap global 7 | vars in AOT modules is they can't be initialized. 8 | 9 | `OPTf_EXTERNS_TO_IMPORTS` and `OPTf_KEEP_PRIVATE` are strange options, you'll never 10 | need. They're to allow the same header file for Kernel to act as externs when 11 | compiling itself and imports when compiled by AOT modules. 12 | 13 | `OPTf_WARN_UNUSED_VAR` warning if unused var. It is applied to functions. 14 | 15 | `OPTf_WARN_PAREN ` warning if parenthesis are not needed. 16 | 17 | `OPTf_WARN_DUP_TYPES` warning if dup local var type stmts. 18 | 19 | `OPTf_WARN_HEADER_MISMATCH` warning if fun header does not match. 20 | 21 | `OPTf_NO_REG_VAR` forces all function local vars to the stk not regs. Applied to 22 | functions. 23 | 24 | `OPTf_NO_BUILTIN_CONST` Disable 10-byte float consts for pi, log2_10, log10_2, 25 | loge_2. Applied to functions. 26 | -------------------------------------------------------------------------------- /CompilerOverview/preprocessor.md: -------------------------------------------------------------------------------- 1 | # PreProcessor 2 | 3 | There is no separate preprocessor pass. The parser front-end calls `Lex()` which 4 | has the preprocessor built-in. The compiler looks ahead a token, most of the 5 | time, so you might throw an extra semicolon after a directive if it's not taking 6 | affect right away. 7 | 8 | Put an extra semicolon `#exe {Cd("DirName");;}` in case a #include follows. 9 | 10 | `#include ""` There is no angle bracket <> form of this directive. 11 | 12 | `#exe {}` Will execute code at compile-time and can be used to insert code 13 | into the stream being compiled using `StreamPrint()`. 14 | 15 | `#define` Define string const 16 | 17 | `#assert` Print a warning during compilation if an expression is not true. 18 | 19 | `#if` Include code if an expresion is true. 20 | 21 | `#else` 22 | 23 | `#endif` 24 | 25 | `#ifdef`,`#ifndef` Include code if a sym is defined. 26 | 27 | `#ifaot`,`#ifjit` Include code if in AOT compiler mode. 28 | 29 | `defined()` Is a function that can be used in expressions. 30 | 31 | `#help_index`, `#help_file` See Help System. 32 | 33 | See PreProcessor. 34 | -------------------------------------------------------------------------------- /CompilerOverview/scopinglinkage.md: -------------------------------------------------------------------------------- 1 | # Scoping and Linkage 2 | 3 | JIT Compile Mode makes use of the current task's hash sym table and its parent 4 | tasks' tables. It fetches syms from parent tasks' tables if not found locally 5 | in the current task's table and it places new syms in the current task's table. 6 | Conceptually, syms are at the scope of environment vars in other operating 7 | systems. 8 | 9 | When a sym is placed into a table, older syms with ident names will be 10 | overshadowed if they exist. Duplicates are not allowed in many cases, 11 | especially in asm blks. Dupicates are allowed, by design in other cases, so 12 | that you can repeatedly `#include` the same file from the cmd line while 13 | developing it. Or, so you can repeatedly declare a function with a standard 14 | name, like `DrawIt()`. This case might occur when the Adam Task is starting-up 15 | loading-in many little utilities. 16 | 17 | `extern` binds a new `HTT_FUN` or `HTT_GLBL_VAR` sym to an existing sym of the same 18 | name if it exists in the sym table (just in just-in-time code). It also can be 19 | used to generate a fwd reference. 20 | 21 | `import` binds a new `HTT_FUN` or `HTT_GLBL_VAR` sym to a sym of the same name 22 | imported from the task's sym table at `Load()` time. If no sym exists to bind to 23 | at `Load()` time, the code using this sym will be left incomplete until the sym is 24 | defined. 25 | 26 | 27 | `_extern` binds a new `HTT_FUN` or `HTT_GLBL_VAR` sym to an existing sym, of a differe 28 | nt name. It must exists in the sym table. Basically, this binds C to asm. 29 | 30 | `_import` binds a new `HTT_FUN` or `HTT_GLBL_VAR` sym to a sym, of a different name 31 | imported from the task's sym table at `Load()` time. If no sym exists to bind to 32 | at `Load()` time, the code using this sym will be left incomplete until the sym is 33 | defined. Basically, this binds C to asm from elsewhere. 34 | 35 | ``` 36 | Ahead of Time Compilation 37 | GlobalScope/FunctionScope 38 | | CodeHeap/DataHeap/Stack/Register 39 | | | TaskHashEntry:ExportSysSym/Define/Function/Class 40 | | | | UsageScope: Module/AsmLocal/AsmBlk/TaskAndChildren/Function 41 | | | | |UsageScope: Glbl/AsmLocal/Remainder/glblThisBlkAndRemainder 42 | | | | || StaticVarInit/DynamicVarInitAllowed/NoInitAllowed 43 | | | | || | Are dups allowed within the namespace? A dup overshadows the original. 44 | | | | || | DupsAllowed/NoDups/NoDupsButPad/WarningUnlessClosedOut 45 | ``` 46 | ```c 47 | asm export label:: G C S MG N 48 | asm label: G C MG N 49 | asm local @@label: G C AL N 50 | asm IMPORT label; G C MR N 51 | asm export label:: F C S BG N 52 | asm label: F C BG N 53 | asm local @@label: F C AL N 54 | asm IMPORT label; F C BR N 55 | C goto label: F C FG N 56 | 57 | #define x MR D 58 | function G C S MR D 59 | var F R FR N 60 | var F S FR N 61 | static var F C FR D N 62 | var G C S MR D D 63 | var G D MR N D 64 | class G MR D 65 | class member G MR P 66 | extern class G MR D 67 | extern function G C MR W 68 | import function G C MR D 69 | import var G C MR D 70 | _extern function G C MR D 71 | _extern var G C MR D 72 | _import function G C MR D 73 | _import var G C MR D 74 | ``` 75 | ``` 76 | Just in Time Compilation 77 | GlobalScope/FunctionScope 78 | | CodeHeap/DataHeap/Stack/Register 79 | | | TaskHashEntry:ExportSysSym/Define/Function/Class 80 | | | | UsageScope: Module/AsmLocal/AsmBlk/TaskAndChildren/Function 81 | | | | |UsageScope: Glbl/AsmLocal/Remainder/glblThisBlkAndRemainder 82 | | | | || StaticVarInit/DynamicVarInitAllowed/NoInitAllowed 83 | | | | || | Are dups allowed within the namespace? A dup overshadows the original. 84 | | | | || | DupsAllowed/NoDups/NoDupsButPad/WarningUnlessClosedOut 85 | ``` 86 | ```c 87 | asm export label:: G C S Tg N 88 | asm label: G C BG N 89 | asm local @@label: G C AL N 90 | asm IMPORT label; G C TR N 91 | asm export label:: F C BG N 92 | asm label: F C BG N 93 | asm local @@label: F C AL N 94 | asm IMPORT label; F C BR N 95 | C goto label: F C FG N 96 | 97 | #define x D TR D 98 | function G C F TR D 99 | var F R FR N 100 | var F S FR N 101 | static var F C FR D N 102 | var G C G TR D D 103 | var G D G TR S D 104 | class G C TR D 105 | class member G TR P 106 | extern class G C TR D 107 | extern function G C F TR W 108 | extern var G C G TR D 109 | extern var G D G TR D 110 | _extern function G C F TR D 111 | _extern var G C G TR D 112 | ``` 113 | 114 | * Goto labels must not have the same name as global scope objects. GoTo's are 115 | rare and I don't want to slow the compiler and add code to fix this. You will 116 | get errors if a collision happens, so it's not very dangerous, but the error 117 | message is baffling. 118 | 119 | * The member names `pad` and `reserved` are special because multiple instances with 120 | the same name are allowed in a class. 121 | 122 | * Use `reg` or `noreg` in front of local var names to override automatic reg var 123 | allocation. You can, optionally, specify a `reg` after the reg keyword. 124 | 125 | * Local non-reg function vars can be accessed in asm blks with `&i[RBP]` for 126 | example. 127 | 128 | * Glbl vars and functions can be accessed in asm with and & as in 129 | 130 | ```asm 131 | MOV RAX,I64 [&glbl_var] 132 | CALL I32 &Fun 133 | CALL I32 &SYS_SYM 134 | ``` 135 | * In JIT asm code, `&SYS_SYM` and `&Fun` don't need `IMPORT`. 136 | 137 | * All offspring tasks of a task inherit syms. 138 | 139 | * The `sizeof()` and HolyC structure members can be used in asm blks. 140 | 141 | * Using `&i` in HolyC or `i.u8[2]` on a local var, `i`, will force it to noreg. 142 | 143 | * Using try/catch in a function will force all local vars to noreg. 144 | 145 | * An unused gap on the stk is left for reg vars. 146 | 147 | * Note: static function vars do not go on the data heap, no matter the setting 148 | of the `OPTf_GLBLS_ON_DATA_HEAP`. They may in the future. 149 | 150 | * `OPTf_EXTERNS_TO_IMPORTS` will treat `_extern` as `_import` and `extern` as `import`. 151 | This allows a header to be used either as a JIT compiled or AOT compiled header. 152 | -------------------------------------------------------------------------------- /HC/ClassMeta.HC: -------------------------------------------------------------------------------- 1 | /*Demonstrates class meta data. 2 | Basically, we make use of the compiler's 3 | data about a class. We can add to the 4 | compilers data arbitrary items, either string or 5 | or int or F64 (if you typecast). 6 | 7 | This stuff is not high performance. 8 | Don't get carried away -- it might be slow. 9 | */ 10 | 11 | U0 RankOut(I64 i) 12 | { 13 | " %z",i,"Cadet\0Ensign\0Captain\0Admiral\0President\0"; 14 | } 15 | 16 | class Test1Struct 17 | { 18 | I64 age print_str "%2d" dft_val 38; 19 | I64 color dft_val RED; //Accepts expressions 20 | I64 rank print_str "%1d" dft_val 6/2 output_fun &RankOut; 21 | }; 22 | 23 | class Test2Struct 24 | { 25 | I64 age print_str "%2d" dft_val 38 percentile 54.20; 26 | I64 rank print_str "%1d" dft_val 5; 27 | I64 serial_num print_str "%6d" dft_val 123456; 28 | }; 29 | 30 | U0 DumpStruct(U8 *_d,U8 *class_name=lastclass) 31 | {//lastclass is keyword. See ::/Demo/LastClass.HC. 32 | CHashClass *tmpc=HashFind(class_name,Fs->hash_table,HTT_CLASS); 33 | U8 *print_str; 34 | I64 *q,dft_val; 35 | U0 (* fp_output_fun)(I64 i); 36 | F64 percentile; 37 | if (!tmpc) return; 38 | CMemberLst *ml; 39 | ml=tmpc->member_lst_and_root; 40 | while (ml) { 41 | "%s:",ml->str; 42 | 43 | //All our items are I64's. If you want, you can check 44 | //the data type of the member var. See ClassRep(). 45 | q=_d+ml->offset; 46 | 47 | if (print_str=MemberMetaData("print_str",ml)) 48 | "" print_str,*q; 49 | 50 | //This is slightly ambiguous -- if no meta is present it will return zero. 51 | if (dft_val=MemberMetaData("dft_val",ml)) 52 | " default:%d",dft_val; 53 | 54 | //This corrects for the ambiguity, allowing zero percentile. 55 | if (MemberMetaFind("percentile",ml)) {//check if it exists 56 | //We could use the CMemberLstMeta structure returned by 57 | //MemberMetaFind() and save a search. 58 | percentile=MemberMetaData("percentile",ml)(F64); 59 | " percentile: %5.2f",percentile; 60 | } 61 | 62 | if (fp_output_fun=MemberMetaData("output_fun",ml)) 63 | (*fp_output_fun)(*q); 64 | '\n'; 65 | ml=ml->next; 66 | } 67 | } 68 | 69 | Test1Struct t1; 70 | t1.age=44; 71 | t1.rank=3; 72 | 73 | DumpStruct(&t1); 74 | 75 | Test2Struct t2; 76 | t2.age=22; 77 | t2.rank=2; 78 | t2.serial_num=55555; 79 | 80 | DumpStruct(&t2); 81 | -------------------------------------------------------------------------------- /HC/Directives.HC: -------------------------------------------------------------------------------- 1 | 2 | U0 Directives() 3 | { 4 | "Date\t:%s\n",__DATE__; 5 | "Time\t:%s\n",__TIME__; 6 | "File\t:%s\n",__FILE__; 7 | "Dir\t:%s\n",__DIR__; 8 | "Line\t:%d\n",__LINE__; 9 | "CmdLine\t:%d\n",__CMD_LINE__; 10 | "Inst1\t:%P:%08X\n",$,$; 11 | "Inst2\t:%P:%08X\n",$,$; 12 | } 13 | 14 | Directives; 15 | -------------------------------------------------------------------------------- /HC/Exceptions.HC: -------------------------------------------------------------------------------- 1 | //WARNING: Don't return out of a catch{}. This 2 | //might get fixed. 3 | 4 | //You can use PutExcept() in a catch stmt 5 | //and it will report args. 6 | Bool Prompt(I64 i) 7 | { 8 | "%d ",i; 9 | return YorN; 10 | } 11 | 12 | U0 D1() 13 | { 14 | "D1\n"; 15 | if (Prompt(1)) throw('Point1'); 16 | if (Prompt(2)) throw('Point2'); 17 | } 18 | 19 | U0 D2() 20 | { 21 | "D2\n"; 22 | try { 23 | D1; 24 | if (Prompt(4)) throw('Point4'); 25 | } catch { 26 | "D2 hndlr\n" 27 | "Ch:%c:%P\n",Fs->except_ch,Fs->except_callers[0]; 28 | if (Fs->except_ch=='Point1') { 29 | "Caught in D2\n"; 30 | Fs->catch_except=TRUE; 31 | } 32 | } 33 | } 34 | 35 | U0 Demo() 36 | { 37 | try { 38 | D2; 39 | if (Prompt(3)) throw('Point3'); 40 | } catch { 41 | "Demo hndlr\n" 42 | "Ch:%c:%P\n",Fs->except_ch,Fs->except_callers[0]; 43 | Fs->catch_except=TRUE; 44 | } 45 | } 46 | 47 | Demo; 48 | -------------------------------------------------------------------------------- /HC/LastClass.HC: -------------------------------------------------------------------------------- 1 | U0 StructName(U8 *d,U8 *class_name=lastclass) 2 | {//lastclass is the prev fun arg's class as a string. 3 | "%X is a \"%s\".\n",d,class_name; 4 | } 5 | 6 | class Student 7 | { 8 | Student *next; 9 | I64 age; 10 | U8 name[32]; 11 | } a; 12 | 13 | class School 14 | { 15 | U8 name[32]; 16 | Student *students; 17 | } s; 18 | 19 | I64 i; 20 | 21 | StructName(Fs); 22 | StructName(&a); 23 | StructName(&s); 24 | StructName(&i); 25 | PressAKey; 26 | 27 | //lastclass is used in ClassRep() and ClassRepD(). 28 | ClassRepD(Gs); 29 | PressAKey; 30 | 31 | ClassRep(Fs); 32 | 33 | //See also DocForm(), ::/Demo/Dsk/BlkDevRep.HC and ::/Demo/ClassMeta.HC. 34 | -------------------------------------------------------------------------------- /HC/Lock.HC: -------------------------------------------------------------------------------- 1 | /*lock{} is a compiler stmt 2 | which places asm LOCK inst 3 | prefixes on code. Only use it on 4 | read-modify-write stmts. 5 | It will generate invalid insts 6 | if you misuse it and it will crash. 7 | U() to see what code was generated. 8 | */ 9 | 10 | #define CNT 0x1000000 11 | 12 | I64 glbl; 13 | 14 | U0 MPUnlockedInc(I64) 15 | { 16 | I64 i; 17 | for (i=0;iDir("*"); 47 | >Dir(); 48 | >Dir; 49 | ``` 50 | 51 | * Default args don't have to be on the end. This code is valid: 52 | 53 | ```c 54 | U0 Test(I64 i=4,I64 j,I64 k=5) 55 | { 56 | Print("%X %X %X\n",i,j,k); 57 | } 58 | 59 | Test(,3); 60 | ``` 61 | * A char const all alone is sent to `PutChars()`. A string with or without args 62 | is sent to `Print()`. An empty string literal signals a variable fmt_str follows. 63 | ```c 64 | void DemoC(char drv,char *fmt,char *name,int age) 65 | { 66 | printf("Hello World!\n"); 67 | printf("%s age %d\n",name,age); 68 | printf(fmt,name,age); 69 | putchar(drv); 70 | putchar('*'); 71 | } 72 | 73 | U0 DemoHolyC(U8 drv,U8 *fmt,U8 *name,I64 age) 74 | { 75 | "Hello World!\n"; 76 | "%s age %d\n",name,age; 77 | "" fmt,name,age; 78 | '' drv; 79 | '*'; 80 | } 81 | ``` 82 | * When dealing with function addresses such as for callbacks, precede the name 83 | with "&". 84 | 85 | * Type casting is postfix. To typecast int or F64, use `ToI64()`, `ToBool()` or 86 | `ToF64()`. (TempleOS follows normal C float<-->int conversion, but sometimes you 87 | want to override. These functions are better than multiplying by "1.0" to 88 | convert to float.) 89 | 90 | * There is no `main()` function. Any code outside of functions gets executed upon 91 | start-up, in order. 92 | 93 | * There are no bit fields, but there are bit access routines and you can access 94 | bytes or words within any int. See `I64` declaration. A class can be accessed as 95 | a whole are subints, if you put a type in front of the class declaration. 96 | ```c 97 | public I64i union I64 //"I64i" is intrinsic. We are defining "I64". 98 | { 99 | I8i i8[8]; 100 | U8i u8[8]; 101 | I16 i16[4]; 102 | U16 u16[4]; 103 | I32 i32[2]; 104 | U32 u32[2]; 105 | }; 106 | 107 | I64 i=0x123456780000DEF0; 108 | i.u16[1]=0x9ABC; 109 | ``` 110 | 111 | * Variable arg count functions (...) can access their args with built-in 112 | variables similar to 'this' in C++. They are 'I64 argc' and 'I64 argv[]'. 113 | ```c 114 | I64 AddNums(...) 115 | { 116 | I64 i,res=0; 117 | for (i=0;iAddNums(1,2,3); 123 | ans=6 124 | 125 | 126 | public U0 GrPrint(CDC *dc,I64 x,I64 y,U8 *fmt,...) 127 | { 128 | U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);//SPrintF() with MAlloc()ed string. 129 | GrPutS(dc,x,y,buf); //Plot string at x,y pixels. GrPutS is not public. 130 | Free(buf); 131 | } 132 | 133 | ... 134 | 135 | GrPrint(gr.dc,(GR_WIDTH-10*FONT_WIDTH)>>1,(GR_HEIGHT-FONT_HEIGHT)>>1, 136 | "Score:%4d",score); //Print score in the center of the scrn. 137 | ... 138 | ``` 139 | 140 | * Allows "5Zero [One] Two [Three] Four [Five] 191 | ``` 192 | * A `no_warn` stmt will suppress an unused var warning. 193 | 194 | * You can have multiple member vars of a class named "pad" or "reserved", and it 195 | won't issue warnings. 196 | 197 | * `noreg` or `reg` can be placed before a function local var name. You can, 198 | optionally, specify a reg after the reg keyword. 199 | ```c 200 | U0 Main() 201 | { 202 | //Only use REGG_LOCAL_VARS or REGG_LOCAL_NON_PTR_VARS for reg vars or else 203 | clobbered. 204 | I64 reg R15 i=5, noreg j=4; 205 | no_warn i; 206 | asm { 207 | MOV RAX,R15 208 | CALL &PUT_HEX_U64 209 | MOV RAX,'\n' 210 | CALL &PUT_CHARS 211 | MOV RAX,U64 &j[RBP] 212 | CALL &PUT_HEX_U64 213 | MOV RAX,'\n' 214 | CALL &PUT_CHARS 215 | } 216 | } 217 | ``` 218 | * `interrupt`, `haserrcode`, `public`, `argpop` or `noargpop` are function flags. See 219 | IRQKbd(). 220 | 221 | * A single quote can encompass multiple characters. 'ABC' is equ to 0x434241. 222 | `PutChars()` takes multiple characters. 223 | 224 | ```c 225 | asm { 226 | HELLO_WORLD:: 227 | PUSH RBP 228 | MOV RBP,RSP 229 | MOV RAX,'Hello ' 230 | CALL &PUT_CHARS 231 | MOV RAX,'World\n' 232 | CALL &PUT_CHARS 233 | LEAVE 234 | RET 235 | } 236 | Call(HELLO_WORLD); 237 | PutChars('Hello '); 238 | PutChars('World\n'); 239 | ``` 240 | * The "`" operator raises a base to a power. 241 | 242 | * There is no question-colon operator. 243 | 244 | * TempleOS operator precedence 245 | `,>>,<< 246 | *,/,% 247 | & 248 | ^ 249 | | 250 | +,- 251 | <,>,<=,>= 252 | ==,!= 253 | && 254 | ^^ 255 | || 256 | =,<<=,>>=,*=,/=,&=,|=,^=,+=,-= 257 | 258 | * You can use `Option(OPTf_WARN_PAREN,ON)` to find unnecessary parentheses in 259 | code. 260 | 261 | * You can use `Option(OPTf_WARN_DUP_TYPES,ON)` to find dup local var type stmts. 262 | 263 | * With the `#exe{}` feature in your src code, you can place programs that insert 264 | text into the stream of code being compiled. See `#exe {}` for an example where 265 | the date/time and compile-time prompting for cfguration data is placed into a 266 | program. `StreamPrint()` places text into a src program stream following the 267 | conclusion of the `#exe{}` blk. 268 | 269 | * No `#define` functions exist (I'm not a fan) 270 | 271 | * No `typedef`, use `class`. 272 | 273 | * No type-checking 274 | 275 | * Can't use `<>` with `#include`, use `""`. 276 | 277 | * "$" is an escape character. Two dollar signs signify an ordinary $. See 278 | DolDoc. In asm or HolyC code, it also refers to the inst's address or the 279 | offset in a class definition. 280 | 281 | * `union` is more like a class, so you don't reference it with a `union` label after 282 | you define it. Some common unions are declared in KernelA.HH for 1,2,4 and 8 283 | byte objects. If you place a type in front of a union declaration, that is the 284 | type when used by itself. See ![SubIntAccess.HC](https://github.com/SpaciousCoder78/holyc-docs/blob/main/HC/SubIntAccess.HC). 285 | 286 | * `class` member vars can have meta data. format and data are two meta data types 287 | now used. All compiler structures are saved and you can access the compiler's 288 | info about classes and vars. See ![ClassMeta.HC](https://github.com/SpaciousCoder78/holyc-docs/blob/main/HC/ClassMeta.HC) and DocForm(). 289 | 290 | * There is a keyword `lastclass` you use as a dft arg. It is set to the class 291 | name of the prev arg. See ![LastClass.HC](https://github.com/SpaciousCoder78/holyc-docs/blob/main/HC/LastClass.HC), ClassRep(), DocForm() and 292 | ::/Demo/Dsk/BlkDevRep.HC. 293 | 294 | * See ![Exceptions.HC](https://github.com/SpaciousCoder78/holyc-docs/blob/main/HC/Exceptions.HC). ` try{}` `catch{}` and throw are different from C++. `th 295 | row` is a function with an 8-byte or less char arg. The char string passed in `th 296 | row()` can be accessed from within a `catch{}` using the Fs->except_ch. Within a `c 297 | atch {}` blk, set the var Fs->catch_except to TRUE if you want to terminate the 298 | search for a hndlr. Use PutExcept() as a hndlr, if you like. 299 | 300 | * A function is available similar to sizeof which provides the offset of a 301 | member of a class. It's called `offset`. You place the class name and member 302 | inside as in `offset(classname.membername)`. It has nothing to do with 16-bit 303 | code. Both `sizeof` and `offset` only accept one level of member vars. That is, 304 | you can't do `sizeof(classname.membername.submembername)`. 305 | 306 | * There is no `continue` stmt. Use `goto`. 307 | 308 | * `lock{}` can be used to apply asm LOCK prefixes to code for safe multicore 309 | read-modify-write accesses. The code bracked with have LOCK asm prefix's 310 | applied to relevant insts within. It's a little shoddy. See 311 | ![Lock.HC](https://github.com/SpaciousCoder78/holyc-docs/blob/main/HC/Lock.HC). 312 | 313 | * There is a function called `MSize()` which gives the size of an object alloced 314 | off the heap. For larger size allocations, the system rounds-up to a power of 315 | two, so `MSize()` lets you know the real size and you can take full advantage of 316 | it. 317 | 318 | * You CAN `Free()` a NULL ptr. Useful variants of `MAlloc()` can be found Here. 319 | Each task has a heap and you can `MAlloc` and Free off-of other task's heaps, or 320 | make an independent heap with `HeapCtrlInit()`. See `HeapLog()` for an example. 321 | 322 | * The stk does not grow because virtual mem is not used. I recommend allocating 323 | large local vars from the heap. You can change `MEM_DFT_STK` and recompile Kernel 324 | or request more when doing a `Spawn()`. You can use `CallStkGrow()`, but it's odd. 325 | See ![StkGrow.HC](https://github.com/SpaciousCoder78/holyc-docs/blob/main/HC/StkGrow.HC). 326 | 327 | * Only one base class is allowed. 328 | 329 | * `printf()` has new codes. See `Print("")` Fmt Strings. 330 | 331 | * All values are extended to 64-bit when accessed. Intermediate calculations 332 | are done with 64-bit values. 333 | ```c 334 | U0 Main() 335 | { 336 | I16 i1; 337 | I32 j1; 338 | j1=i1=0x12345678; //Resulting i1 is 0x5678 but j1 is 0x12345678 339 | 340 | I64 i2=0x8000000000000000; 341 | Print("%X\n",i2>>1); //Res is 0xC000000000000000 as expected 342 | 343 | U64 u3=0x8000000000000000; 344 | Print("%X\n",u3>>1); //Res is 0x4000000000000000 as expected 345 | 346 | I32 i4=0x80000000; //const is loaded into a 64-bit reg var. 347 | Print("%X\n",i4>>1); //Res is 0x40000000 348 | 349 | I32 i5=-0x80000000; 350 | Print("%X\n",i5>>1); //Res is 0xFFFFFFFFC0000000 351 | } 352 | ``` 353 | -------------------------------------------------------------------------------- /helloworld.HC: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | //Press F5 in the editor to compile and run. 5 | 6 | --------Hello.HC.Z--------- 7 | "Hello World\n"; 8 | 9 | 10 | --------Hello.HC.Z--------- 11 | U0 Main() 12 | { 13 | "Hello World\n"; 14 | } 15 | Main; 16 | 17 | 18 | --------Hello.HC.Z--------- 19 | U0 MyPrint(U8 *st) 20 | { 21 | "%s",st; 22 | } 23 | MyPrint("Hello World\n"); 24 | 25 | 26 | --------Hello.HC.Z--------- 27 | U0 MyPrint2(U8 *st1,U8 *st2) //Any number of args. 28 | { 29 | "%s %s\n",st1,st2; //Any number of args. 30 | } 31 | MyPrint2("Hello","World"); 32 | 33 | 34 | --------Hello.HC.Z--------- 35 | U0 MyPrint(U8 *st) 36 | { 37 | "" st; //Empty with no comma means first is fmt str. 38 | } 39 | MyPrint("Hello World\n"); 40 | 41 | 42 | --------Hello.HC.Z--------- 43 | asm { 44 | MSG: DU8 "Hello World\n",0; 45 | 46 | //The convention is underscore on C callable. 47 | //Two colons means exported symbol. 48 | _HELLO_WORLD:: 49 | //You can only clobber RAX,RBX,RCX,RDX 50 | PUSH RSI 51 | MOV RSI,MSG 52 | CALL PUT_STR 53 | POP RSI 54 | RET 55 | } 56 | Call(_HELLO_WORLD); 57 | 58 | 59 | --------Hello.HC.Z--------- 60 | asm { 61 | _HELLO_WORLD:: 62 | //You can only clobber RAX,RBX,RCX,RDX 63 | MOV RAX,'Hello ' 64 | CALL PUT_CHARS //Up to 8 chars packed into one 64-bit int. 65 | MOV RAX,'World\n' 66 | CALL PUT_CHARS 67 | RET 68 | } 69 | Call(_HELLO_WORLD); 70 | 71 | 72 | --------Hello.HC.Z--------- 73 | asm { 74 | _MY_PRINT:: 75 | //You can only clobber RAX,RBX,RCX,RDX 76 | PUSH RBP 77 | MOV RBP,RSP 78 | PUSH RSI 79 | MOV RSI,U64 SF_ARG1[RBP] 80 | CALL PUT_STR 81 | POP RSI 82 | POP RBP 83 | RET1 8 //Callee pops the stack to clear args. 84 | } 85 | _extern _MY_PRINT U0 MyPrint(U8 *st); 86 | MyPrint("Hello World\n"); 87 | 88 | 89 | --------Hello.HC.Z--------- 90 | asm { 91 | _MY_PRINT:: 92 | //You can only clobber RAX,RBX,RCX,RDX 93 | PUSH RBP 94 | MOV RBP,RSP 95 | PUSH U64 SF_ARG1[RBP] 96 | CALL &PutS //Callee pops the stack to clear args. 97 | POP RBP 98 | RET1 8 99 | } 100 | _extern _MY_PRINT U0 MyPrint(U8 *st); 101 | MyPrint("Hello World\n"); 102 | --------------------------------------------------------------------------------