200 lines
4.5 KiB
Plaintext
200 lines
4.5 KiB
Plaintext
it should look more like c, as i want my compiler to be able to compile c
|
|
|
|
#include <io.sterling>//sterling is the name of the language, but i need to think of a file extension name that doesn't conflict with other format
|
|
#include <string.h>//this should work
|
|
|
|
u32 add(u32 a, u32 b) {
|
|
return (a + b);
|
|
}
|
|
|
|
// also i should be able as the user to define
|
|
|
|
typedef struct {
|
|
u32 test = 12;
|
|
} new_struct;
|
|
// if new_struct struct = {0}; then all data even default init are set to 0
|
|
// but if new_struct struct = {}; then all data but default init are set to 0
|
|
|
|
//also pointer should work like c, but void* shouldn't be the same as ptr*
|
|
//i don't know what i could do, but i would like for ptr* to allow for implicite data cast, but void* should be explicit
|
|
|
|
meta define_add(T);
|
|
T add(T a, T b) {
|
|
return (a + b);
|
|
}
|
|
//the issue i have here is it need to have an explicit overload if T is a structure, and i don't really like it, could lead to a c++ like language with too many undefined behavior, what could be a better approach ?
|
|
|
|
|
|
#include <io.stgh>//for stg header but i could also just use .stg and have the possibility to include stg file as header
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
u32 x = 1;
|
|
u32 y = 2;
|
|
} vec2;
|
|
|
|
typedef struct {
|
|
u32 x;
|
|
u32 y;
|
|
} vec2_raw;
|
|
|
|
u32 add(u32 a, u32 b) {
|
|
return (a + b);
|
|
}
|
|
|
|
vec2_raw make_raw(u32 a, u32 b) {
|
|
return (vec2_raw){ a, b };
|
|
}
|
|
|
|
void* memcpy_explicit(void* dst, void* src, u32 n) {
|
|
// must explicitly cast outside
|
|
return memcpy(dst, src, n);
|
|
}
|
|
|
|
fn copy(ptr* dst, ptr* src, u32 n) {
|
|
// compiler auto-casts any ptr* to void* internally
|
|
memcpy(dst, src, n);
|
|
}
|
|
|
|
meta define_add(T);
|
|
T add(T a, T b) {
|
|
return (a + b);
|
|
}
|
|
|
|
// specialization for vec2
|
|
meta define_add(vec2);
|
|
vec2 add(vec2 a, vec2 b) {
|
|
return (vec2){ a.x + b.x, a.y + b.y };
|
|
}
|
|
|
|
fn main() -> u32 {
|
|
vec2 a = {}; // defaults apply
|
|
vec2 b = {0}; // defaults ignored, all zero
|
|
|
|
vec2 result = add(a, b);
|
|
|
|
u32* data = 0;
|
|
copy(data, data, 4); // OK
|
|
memcpy_explicit((void*)data, (void*)data, 4); // must cast
|
|
|
|
return 0;
|
|
}
|
|
|
|
fn_asm exit() {
|
|
section .text
|
|
global exit
|
|
exit:
|
|
mov rax, 60 ; syscall for exit
|
|
mov rdi, 0 ; exit code
|
|
syscall
|
|
ret
|
|
}
|
|
|
|
/*
|
|
rdi: dst
|
|
rsi: value
|
|
rdx: size
|
|
Returns in rax: dst
|
|
*/
|
|
/* implicit
|
|
section .text
|
|
global <symbol>
|
|
memset:
|
|
*/
|
|
fn_asm memset(void* dst, u8 value, u64 size) {
|
|
test rdx, rdx
|
|
je .done
|
|
|
|
mov rax, rsi ; value
|
|
mov rdi, rdi ; dst
|
|
mov rcx, rdx ; size
|
|
|
|
rep stosb
|
|
|
|
.done:
|
|
mov rax, rdi ; return dst
|
|
ret
|
|
}
|
|
//This uses the rep stosb instruction to rapidly write bytes into memory.
|
|
|
|
/*
|
|
rdi: void** old_sp — destination to store current rsp
|
|
rsi: void* new_sp — new stack pointer to switch into
|
|
No return value (control flow continues on new stack)
|
|
*/
|
|
fn_asm context_switch(void** old_sp, void* new_sp) {
|
|
mov [rdi], rsp ; save current stack pointer to *old_sp
|
|
mov rsp, rsi ; load new stack pointer
|
|
ret
|
|
}
|
|
|
|
|
|
/*
|
|
rdi: dst
|
|
rsi: value
|
|
rdx: size
|
|
Returns in rax: dst
|
|
*/
|
|
/* implicit
|
|
section .text
|
|
memset:
|
|
*/
|
|
fn_static_asm memset(void* dst, u8 value, u64 size) {
|
|
test rdx, rdx
|
|
je .done
|
|
|
|
mov rax, rsi ; value
|
|
mov rdi, rdi ; dst
|
|
mov rcx, rdx ; size
|
|
|
|
rep stosb
|
|
|
|
.done:
|
|
mov rax, rdi ; return dst
|
|
ret
|
|
}
|
|
//This uses the rep stosb instruction to rapidly write bytes into memory.
|
|
|
|
/*
|
|
| Keyword | Description |
|
|
| --------------- | ---------------------------------------------------------------------- |
|
|
| `fn` | Required for every function definition |
|
|
| `fn_inline` | Inline-only function, callable in the same TU |
|
|
| `fn_static` | Internal linkage (only visible in current TU) |
|
|
| `fn_extern` | Declaration only; expects symbol at link time |
|
|
| `fn_export` | Visible outside, exported in shared/static libs |
|
|
| `fn_asm` | Assembly-defined function, globally visible unless otherwise specified |
|
|
| `fn_static_asm` | Assembly-defined, internal linkage (hidden from linker) |
|
|
*/
|
|
|
|
//Keyword Examples
|
|
|
|
// header file (user_math.stgh)
|
|
fn_extern add(u32, u32);
|
|
fn_inline max(u32 a, u32 b) {
|
|
return (a > b) ? a : b;
|
|
}
|
|
|
|
// libmath.stg
|
|
fn_export add(u32 a, u32 b) {
|
|
return a + b;
|
|
}
|
|
|
|
// internal use only
|
|
fn_static log2_floor(u32 x) {
|
|
// implementation
|
|
}
|
|
|
|
// inline asm
|
|
fn_asm fast_add(u32 a, u32 b) {
|
|
mov eax, edi
|
|
add eax, esi
|
|
ret
|
|
}
|
|
|
|
// internal-only asm
|
|
fn_static_asm zero_block(void* dst, u64 size) {
|
|
rep stosb
|
|
ret
|
|
}
|