diff --git a/_test_closure/build/closure_test b/_test_closure/build/closure_test index 4637bfd..4b7c03c 100755 Binary files a/_test_closure/build/closure_test and b/_test_closure/build/closure_test differ diff --git a/_test_closure/build/main b/_test_closure/build/main deleted file mode 100755 index 91e1ee8..0000000 Binary files a/_test_closure/build/main and /dev/null differ diff --git a/_test_closure/build/main.c b/_test_closure/build/main.c index 456eed2..70094b7 100644 --- a/_test_closure/build/main.c +++ b/_test_closure/build/main.c @@ -1,67 +1,4820 @@ -// Generated by Bux C Backend v2 +/* Generated by Bux Compiler (LIR backend) */ +#include +#include #include #include #include -#include -#include -typedef const char* String; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -typedef unsigned long long uint64; -typedef signed char int8; -typedef short int16; -typedef long long int64; -typedef float float32; -typedef double float64; -typedef char char8; +typedef struct TaskHandle TaskHandle; +typedef struct Mutex Mutex; +typedef struct RwLock RwLock; +typedef struct JsonValue JsonValue; +typedef struct JsonParser JsonParser; +typedef struct StringBuilder StringBuilder; +typedef struct Channel_int Channel_int; +typedef struct Channel_float64 Channel_float64; -void* bux_alloc(unsigned int size); -void bux_free(void* ptr); +/* Extern function declarations */ +extern void* bux_alloc(unsigned int size); +extern void* bux_realloc(void* ptr, unsigned int size); +extern void bux_free(void* ptr); +extern void bux_bounds_check(unsigned int index, unsigned int len); +extern void* bux_channel_new(int64_t capacity, int64_t elem_size); +extern void bux_channel_send(void* handle, void* elem); +extern int bux_channel_recv(void* handle, void* out); +extern void bux_channel_close(void* handle); +extern void bux_channel_free(void* handle); +extern int bux_dir_exists(const char* path); +extern int bux_mkdir_if_needed(const char* path); +extern const char** bux_list_dir(const char* dir, const char* ext, int* out_count); +extern void PrintLine(const char* s); +extern void Print(const char* s); +extern void PrintInt(int n); +extern void PrintInt64(int64_t n); +extern void PrintFloat(double f); +extern void PrintBool(bool b); +extern const char* ReadLine(void); +extern const char* bux_read_file(const char* path); +extern int bux_write_file(const char* path, const char* content); +extern int bux_file_exists(const char* path); +extern unsigned int bux_hash_bytes(void* ptr, unsigned int size); +extern unsigned int bux_hash_string(const char* s); +extern double bux_sqrt(double x); +extern double bux_pow(double x, double y); +extern int64_t bux_abs_i64(int64_t x); +extern double bux_abs_f64(double x); +extern int64_t bux_min_i64(int64_t a, int64_t b); +extern int64_t bux_max_i64(int64_t a, int64_t b); +extern double bux_min_f64(double a, double b); +extern double bux_max_f64(double a, double b); +extern void* bux_alloc(unsigned int size); +extern void* bux_realloc(void* ptr, unsigned int size); +extern void bux_free(void* ptr); +extern int bux_mem_eq(void* a, void* b, unsigned int size); +extern const char* bux_path_join(const char* a, const char* b); +extern const char* bux_path_parent(const char* path); +extern const char* bux_path_ext(const char* path); +extern unsigned int bux_hash_bytes(void* ptr, unsigned int size); +extern int bux_mem_eq(void* a, void* b, unsigned int size); +extern void* bux_alloc(unsigned int size); +extern void bux_free(void* ptr); +extern void* bux_task_spawn(void* fn, void* arg); +extern void bux_task_join(void* handle); +extern void bux_task_sleep(int64_t ms); +extern int bux_argc(void); +extern const char* bux_argv(int index); +extern const char* bux_getenv(const char* name); +extern int bux_setenv(const char* name, const char* value); +extern const char* bux_getcwd(void); +extern int bux_chdir(const char* path); +extern int64_t bux_time_ms(void); +extern int64_t bux_time_us(void); +extern void bux_sleep_ms(int64_t ms); +extern int bux_process_run(const char* cmd); +extern const char* bux_process_output(const char* cmd); +extern int bux_socket_create(void); +extern int bux_socket_reuse(int fd); +extern int bux_socket_bind(int fd, const char* addr, int port); +extern int bux_socket_listen(int fd, int backlog); +extern int bux_socket_accept(int fd); +extern int bux_socket_connect(int fd, const char* addr, int port); +extern int bux_socket_send(int fd, const char* data, int len); +extern const char* bux_socket_recv(int fd, int maxLen); +extern int bux_socket_close(int fd); +extern const char* bux_socket_error(void); +extern unsigned int bux_strlen(const char* s); +extern int64_t bux_str_to_int(const char* s); +extern void* bux_alloc(unsigned int size); +extern void bux_sha256(const char* data, int len, void* out); +extern void bux_hmac_sha256(const char* key, int keylen, const char* msg, int msglen, void* out); +extern int bux_random_bytes(void* buf, int len); +extern const char* bux_base64_encode(const char* data, int len); +extern const char* bux_base64_decode(const char* data, int len, int* outlen); +extern const char* bux_bytes_to_hex(void* data, int len); +extern void* bux_mutex_new(void); +extern void bux_mutex_lock(void* handle); +extern void bux_mutex_unlock(void* handle); +extern void bux_mutex_free(void* handle); +extern void* bux_rwlock_new(void); +extern void bux_rwlock_rdlock(void* handle); +extern void bux_rwlock_wrlock(void* handle); +extern void bux_rwlock_unlock(void* handle); +extern void bux_rwlock_free(void* handle); +extern void bux_exit(int code); +extern void bux_assert(int cond, const char* file, int line, const char* expr); +extern JsonValue JsonParser_ParseValue(JsonParser* p); +extern unsigned int bux_strlen(const char* s); +extern int bux_strcmp(const char* a, const char* b); +extern int bux_strncmp(const char* a, const char* b, unsigned int n); +extern char* bux_strcpy(char* dest, const char* src); +extern char* bux_strcat(char* dest, const char* src); +extern char* bux_strncpy(char* dest, const char* src, unsigned int n); +extern const char* bux_strstr(const char* haystack, const char* needle); +extern int bux_str_contains(const char* haystack, const char* needle); +extern unsigned int bux_str_offset(const char* pos, const char* base); +extern int bux_str_is_null(const char* s); +extern const char* bux_str_slice(const char* s, unsigned int start, unsigned int len); +extern const char* bux_str_trim_left(const char* s); +extern const char* bux_str_trim_right(const char* s); +extern const char* bux_str_trim(const char* s); +extern const char* bux_int_to_str(int64_t n); +extern int64_t bux_str_to_int(const char* s); +extern void* bux_sb_new(unsigned int initial_cap); +extern void bux_sb_append(void* sb, const char* s); +extern void bux_sb_append_int(void* sb, int64_t n); +extern void bux_sb_append_float(void* sb, double f); +extern void bux_sb_append_char(void* sb, char c); +extern const char* bux_sb_build(void* sb); +extern void bux_sb_free(void* sb); +extern unsigned int bux_str_split_count(const char* s, const char* delim); +extern const char* bux_str_split_part(const char* s, const char* delim, unsigned int index); +extern const char* bux_str_join2(const char* a, const char* b, const char* sep); +extern const char* bux_float_to_string(double f); +extern const char* bux_str_format(const char* pattern, const char* a0, const char* a1, const char* a2, const char* a3, const char* a4, const char* a5, const char* a6, const char* a7); +extern double bux_str_to_float(const char* s); +extern void bux_sha1(const char* data, int len, void* out); +extern void bux_sha256(const char* data, int len, void* out); +extern void bux_sha384(const char* data, int len, void* out); +extern void bux_sha512(const char* data, int len, void* out); +extern const char* bux_bytes_to_hex(void* data, int len); +extern const char* bux_base64_encode(const char* data, int len); +extern const char* bux_base64_decode(const char* data, int len, int* outlen); +extern const char* bux_base64url_encode(const char* data, int len); +extern const char* bux_base64url_decode(const char* data, int len, int* outlen); +extern void bux_hmac_sha256(const char* key, int keylen, const char* msg, int msglen, void* out); +extern void bux_hmac_sha384(const char* key, int keylen, const char* msg, int msglen, void* out); +extern void bux_hmac_sha512(const char* key, int keylen, const char* msg, int msglen, void* out); +extern const char* bux_bytes_to_hex(void* data, int len); +extern const char* bux_base64_encode(const char* data, int len); +extern int bux_random_bytes(void* buf, int len); +extern const char* bux_base64_encode(const char* data, int len); +extern const char* bux_bytes_to_hex(void* data, int len); +extern int bux_random_bytes(void* buf, int len); +extern const char* bux_aes_256_cbc_encrypt(const char* plain, int plainlen, const char* key, const char* iv, int* outlen); +extern const char* bux_aes_256_cbc_decrypt(const char* cipher, int cipherlen, const char* key, const char* iv, int* outlen); +extern const char* bux_aes_256_gcm_encrypt(const char* plain, int plainlen, const char* key, const char* iv, void* tag, int* outlen); +extern const char* bux_aes_256_gcm_decrypt(const char* cipher, int cipherlen, const char* key, const char* iv, const char* tag, int* outlen); +extern const char* bux_base64_encode(const char* data, int len); +extern unsigned int bux_str_split_count(const char* s, const char* delim); +extern const char* bux_str_split_part(const char* s, const char* delim, unsigned int index); +extern const char* bux_ecdsa_sign_p256(const char* key, int keylen, const char* data, int datalen, int* outlen); +extern int bux_ecdsa_verify_p256(const char* key, int keylen, const char* data, int datalen, const char* sig, int siglen); +extern const char* bux_ecdsa_sign_p384(const char* key, int keylen, const char* data, int datalen, int* outlen); +extern int bux_ecdsa_verify_p384(const char* key, int keylen, const char* data, int datalen, const char* sig, int siglen); +extern const char* bux_base64_encode(const char* data, int len); +extern const char* bux_base64_decode(const char* data, int len, int* outlen); +extern int bux_ed25519_keypair(void* pubKey, void* privKey); +extern int bux_ed25519_sign(const char* privKey, const char* data, int datalen, void* sig); +extern int bux_ed25519_verify(const char* pubKey, const char* sig, const char* data, int datalen); +extern const char* bux_base64_encode(const char* data, int len); +extern const char* bux_base64_decode(const char* data, int len, int* outlen); +extern const char* bux_rsa_sign_sha256(const char* key, int keylen, const char* data, int datalen, int* outlen); +extern const char* bux_rsa_sign_sha384(const char* key, int keylen, const char* data, int datalen, int* outlen); +extern const char* bux_rsa_sign_sha512(const char* key, int keylen, const char* data, int datalen, int* outlen); +extern int bux_rsa_verify_sha256(const char* key, int keylen, const char* data, int datalen, const char* sig, int siglen); +extern int bux_rsa_verify_sha384(const char* key, int keylen, const char* data, int datalen, const char* sig, int siglen); +extern int bux_rsa_verify_sha512(const char* key, int keylen, const char* data, int datalen, const char* sig, int siglen); +extern const char* bux_base64_encode(const char* data, int len); +extern const char* bux_base64_decode(const char* data, int len, int* outlen); + +/* Constants */ +#define JsonTagNull 0 +#define JsonTagBool 1 +#define JsonTagNumber 2 +#define JsonTagString 3 +#define JsonTagArray 4 +#define JsonTagObject 5 +#define AES_KEY_SIZE 32 +#define AES_IV_SIZE 16 +#define AES_GCM_TAG_SIZE 16 +#define ED25519_PUBKEY_SIZE 32 +#define ED25519_PRIVKEY_SIZE 32 +#define ED25519_SIG_SIZE 64 + +typedef enum { + Result_Ok, + Result_Err +} Result_Tag; + +typedef union { + int Ok_0; + const char* Err_0; +} Result_Data; + +typedef struct { + Result_Tag tag; + Result_Data data; +} Result; + +typedef enum { + Option_Some, + Option_None +} Option_Tag; + +typedef union { + int Some_0; +} Option_Data; + +typedef struct { + Option_Tag tag; + Option_Data data; +} Option; + +typedef enum { + JwtAlg_HS256, + JwtAlg_HS384, + JwtAlg_HS512, + JwtAlg_RS256, + JwtAlg_RS384, + JwtAlg_RS512, + JwtAlg_ES256, + JwtAlg_ES384, + JwtAlg_EdDSA +} JwtAlg; -int Apply(int x, int (*op)(int)); -int Double(int x); -int __closure_2(int a, int b); -int __closure_3(int x); -int main(); +typedef struct TaskHandle { + void* handle; +} TaskHandle; -void PrintInt(int x); -void PrintLine(String msg); +typedef struct Mutex { + void* handle; +} Mutex; -int Apply(int x, int (*op)(int)) { - return op(x); +typedef struct RwLock { + void* handle; +} RwLock; +typedef struct JsonValue { + int tag; + bool boolVal; + double numVal; + const char* strVal; + JsonValue* arrData; + unsigned int arrLen; + unsigned int arrCap; + const char** objKeys; + JsonValue* objValues; + unsigned int objLen; + unsigned int objCap; +} JsonValue; + +typedef struct JsonParser { + const char* src; + unsigned int pos; + unsigned int len; + const char* error; +} JsonParser; + +typedef struct StringBuilder { + void* handle; +} StringBuilder; + +typedef struct Channel_int { + void* handle; +} Channel_int; + +typedef struct Channel_float64 { + void* handle; +} Channel_float64; + +void Channel_SendInt(Channel_int* ch, int value); +int Channel_RecvInt(Channel_int* ch); +void Channel_SendFloat64(Channel_float64* ch, double value); +double Channel_RecvFloat64(Channel_float64* ch); +bool DirExists(const char* path); +bool Mkdir(const char* path); +const char** ListDir(const char* dir, const char* ext, int* count); +const char* ReadFile(const char* path); +bool WriteFile(const char* path, const char* content); +bool FileExists(const char* path); +double Sqrt(double x); +double Pow(double x, double y); +int64_t Abs(int64_t n); +double AbsF(double f); +int64_t Min(int64_t a, int64_t b); +int64_t Max(int64_t a, int64_t b); +double MinF(double a, double b); +double MaxF(double a, double b); +void* Alloc(unsigned int size); +void* Realloc(void* ptr, unsigned int size); +void Free(void* ptr); +bool MemEq(void* a, void* b, unsigned int size); +const char* Path_Join(const char* a, const char* b); +const char* Path_Parent(const char* path); +const char* Path_Ext(const char* path); +TaskHandle Task_Spawn(void* fn, void* arg); +void Task_Join(TaskHandle t); +void Task_Sleep(int64_t ms); +int Os_ArgsCount(void); +const char* Os_Args(int index); +const char* Os_GetEnv(const char* name); +bool Os_SetEnv(const char* name, const char* value); +const char* Os_GetCwd(void); +bool Os_Chdir(const char* path); +int64_t Time_NowMs(void); +int64_t Time_NowUs(void); +void Time_SleepMs(int64_t ms); +int Process_Run(const char* cmd); +const char* Process_Output(const char* cmd); +int Net_Create(void); +bool Net_SetReuse(int fd); +bool Net_Bind(int fd, const char* addr, int port); +bool Net_Listen(int fd, int backlog); +int Net_Accept(int fd); +bool Net_Connect(int fd, const char* addr, int port); +int Net_Send(int fd, const char* data); +const char* Net_Recv(int fd, int maxLen); +bool Net_Close(int fd); +const char* Net_LastError(void); +const char* Fmt_Format(const char* tmpl, const char** argStrs, int argCount); +const char* Fmt_Fmt1(const char* tmpl, const char* a1); +const char* Fmt_FmtInt(const char* tmpl, int64_t val); +const char* Fmt_FmtBool(const char* tmpl, bool val); +const char* Fmt_FmtFloat(const char* tmpl, double val); +const char* Fmt_Fmt2(const char* tmpl, const char* a1, const char* a2); +const char* Fmt_Fmt3(const char* tmpl, const char* a1, const char* a2, const char* a3); +const char* Crypto_Sha256(const char* data); +const char* Crypto_HmacSha256(const char* key, const char* message); +const char* Crypto_RandomBytes(int n); +const char* Crypto_Base64Encode(const char* s); +const char* Crypto_HmacSha256Raw(const char* key, const char* message); +const char* Crypto_Base64Decode(const char* s); +Mutex Mutex_New(void); +void Mutex_Lock(Mutex* m); +void Mutex_Unlock(Mutex* m); +void Mutex_Free(Mutex* m); +RwLock RwLock_New(void); +void RwLock_ReadLock(RwLock* rw); +void RwLock_WriteLock(RwLock* rw); +void RwLock_Unlock(RwLock* rw); +void RwLock_Free(RwLock* rw); +void Test_Exit(int code); +void Test_Assert(bool cond); +void Test_AssertEqInt(int a, int b); +void Test_AssertTrue(bool cond); +void Test_AssertFalse(bool cond); +void Test_Fail(const char* msg); +Result Result_NewOk(int value); +Result Result_NewErr(const char* msg); +bool Result_IsOk(Result r); +bool Result_IsErr(Result r); +int Result_Unwrap(Result r); +int Result_UnwrapOr(Result r, int fallback); +Option Option_NewSome(int value); +Option Option_NewNone(void); +bool Option_IsSome(Option o); +bool Option_IsNone(Option o); +int Option_Unwrap(Option o); +int Option_UnwrapOr(Option o, int fallback); +JsonValue Json_Null(void); +JsonValue Json_Bool(bool b); +JsonValue Json_Number(double n); +JsonValue Json_String(const char* s); +JsonValue Json_Array(void); +JsonValue Json_Object(void); +unsigned int Json_ArrayLen(JsonValue v); +JsonValue Json_ArrayGet(JsonValue v, unsigned int index); +void Json_ArrayPush(JsonValue* self, JsonValue val); +unsigned int Json_ObjectLen(JsonValue v); +JsonValue Json_ObjectGet(JsonValue v, const char* key); +bool Json_ObjectHas(JsonValue v, const char* key); +void Json_ObjectSet(JsonValue* self, const char* key, JsonValue val); +bool Json_IsNull(JsonValue v); +bool Json_AsBool(JsonValue v); +double Json_AsNumber(JsonValue v); +const char* Json_AsString(JsonValue v); +int JsonParser_Peek(JsonParser* p); +void JsonParser_Advance(JsonParser* p); +void JsonParser_SkipWhitespace(JsonParser* p); +bool JsonParser_Match(JsonParser* p, const char* expected); +const char* JsonParser_ParseString(JsonParser* p); +JsonValue JsonParser_ParseNumber(JsonParser* p); +JsonValue JsonParser_ParseArray(JsonParser* p); +JsonValue JsonParser_ParseObject(JsonParser* p); +JsonValue JsonParser_ParseValue(JsonParser* p); +JsonValue Json_Parse(const char* s); +void Json_StringifyImpl(StringBuilder* sb, JsonValue v); +const char* Json_Stringify(JsonValue v); +unsigned int String_Len(const char* s); +bool String_IsNull(const char* s); +bool String_Eq(const char* a, const char* b); +const char* String_Concat(const char* a, const char* b); +const char* String_Copy(const char* s); +bool String_StartsWith(const char* s, const char* prefix); +bool String_EndsWith(const char* s, const char* suffix); +bool String_Contains(const char* s, const char* substr); +const char* String_Slice(const char* s, unsigned int start, unsigned int len); +const char* String_Trim(const char* s); +const char* String_TrimLeft(const char* s); +const char* String_TrimRight(const char* s); +const char* String_FromInt(int64_t n); +int64_t String_ToInt(const char* s); +StringBuilder StringBuilder_New(void); +StringBuilder StringBuilder_NewCap(unsigned int cap); +void StringBuilder_Append(StringBuilder* sb, const char* s); +void StringBuilder_AppendInt(StringBuilder* sb, int64_t n); +void StringBuilder_AppendFloat(StringBuilder* sb, double f); +void StringBuilder_AppendChar(StringBuilder* sb, char c); +const char* StringBuilder_Build(StringBuilder* sb); +void StringBuilder_Free(StringBuilder* sb); +unsigned int String_SplitCount(const char* s, const char* delim); +const char* String_SplitPart(const char* s, const char* delim, unsigned int index); +const char* String_Join2(const char* a, const char* b, const char* sep); +const char* String_Chars(const char* s, unsigned int index); +const char* String_Find(const char* haystack, const char* needle); +unsigned int String_Offset(const char* pos, const char* base); +const char* String_Replace(const char* s, const char* old, const char* new); +double String_ToFloat(const char* s); +const char* String_FromBool(bool b); +const char* String_FromFloat(double f); +const char* String_Format1(const char* pattern, const char* a0); +const char* String_Format2(const char* pattern, const char* a0, const char* a1); +const char* String_Format3(const char* pattern, const char* a0, const char* a1, const char* a2); +const char* Hash_Sha1(const char* data); +const char* Hash_Sha256(const char* data); +const char* Hash_Sha384(const char* data); +const char* Hash_Sha512(const char* data); +void Hash_Sha256Raw(const char* data, void* out); +void Hash_Sha384Raw(const char* data, void* out); +void Hash_Sha512Raw(const char* data, void* out); +int Hash_Sha1Size(void); +int Hash_Sha256Size(void); +int Hash_Sha384Size(void); +int Hash_Sha512Size(void); +const char* Base64_Encode(const char* s); +const char* Base64_Decode(const char* s); +const char* Base64URL_Encode(const char* s); +const char* Base64URL_Decode(const char* s); +const char* Hmac_Sha256(const char* key, const char* message); +void Hmac_Sha256Raw(const char* key, const char* message, void* out); +const char* Hmac_Sha256Base64(const char* key, const char* message); +const char* Hmac_Sha384(const char* key, const char* message); +void Hmac_Sha384Raw(const char* key, const char* message, void* out); +const char* Hmac_Sha384Base64(const char* key, const char* message); +const char* Hmac_Sha512(const char* key, const char* message); +void Hmac_Sha512Raw(const char* key, const char* message, void* out); +const char* Hmac_Sha512Base64(const char* key, const char* message); +const char* Random_Bytes(int n); +const char* Random_Hex(int n); +const char* Random_Base64(int n); +unsigned int Random_Uint32(void); +const char* Aes_GenerateKey(void); +const char* Aes_GenerateIV(void); +const char* Aes_CbcEncrypt(const char* plain, const char* key, const char* iv); +const char* Aes_CbcDecrypt(const char* cipher, const char* key, const char* iv); +const char* Aes_GcmEncrypt(const char* plain, const char* key, const char* iv, void* tag); +const char* Aes_GcmDecrypt(const char* cipher, const char* key, const char* iv, const char* tag); +const char* Jwt_MakeHeader(JwtAlg alg); +const char* Jwt_Sign(JwtAlg alg, const char* signingInput, const char* key); +bool Jwt_Verify(JwtAlg alg, const char* signingInput, const char* signatureB64, const char* key); +const char* Jwt_Encode(const char* headerJson, const char* payloadJson, JwtAlg alg, const char* key); +bool Jwt_Decode(const char* token, JwtAlg alg, const char* key, const char** headerOut, const char** payloadOut); +const char* Jwt_EncodeHS256(const char* payloadJson, const char* secret); +const char* Jwt_EncodeHS384(const char* payloadJson, const char* secret); +const char* Jwt_EncodeHS512(const char* payloadJson, const char* secret); +const char* Jwt_EncodeRS256(const char* payloadJson, const char* pemPrivateKey); +const char* Jwt_EncodeES256(const char* payloadJson, const char* pemPrivateKey); +const char* Jwt_EncodeEdDSA(const char* payloadJson, const char* rawPrivKey); +const char* Ecdsa_SignP256(const char* pemPrivateKey, const char* data); +const char* Ecdsa_SignP256Base64(const char* pemPrivateKey, const char* data); +bool Ecdsa_VerifyP256(const char* pemPublicKey, const char* data, const char* signature); +bool Ecdsa_VerifyP256Base64(const char* pemPublicKey, const char* data, const char* signatureB64); +const char* Ecdsa_SignP384(const char* pemPrivateKey, const char* data); +const char* Ecdsa_SignP384Base64(const char* pemPrivateKey, const char* data); +bool Ecdsa_VerifyP384(const char* pemPublicKey, const char* data, const char* signature); +bool Ecdsa_VerifyP384Base64(const char* pemPublicKey, const char* data, const char* signatureB64); +bool Ed25519_Keypair(void* pubKey, void* privKey); +const char* Ed25519_KeypairBase64(void); +const char* Ed25519_Sign(const char* privKey, const char* data); +const char* Ed25519_SignBase64(const char* privKey, const char* data); +bool Ed25519_Verify(const char* pubKey, const char* signature, const char* data); +bool Ed25519_VerifyBase64(const char* pubKey, const char* signatureB64, const char* data); +const char* Rsa_SignSha256(const char* pemPrivateKey, const char* data); +const char* Rsa_SignSha384(const char* pemPrivateKey, const char* data); +const char* Rsa_SignSha512(const char* pemPrivateKey, const char* data); +const char* Rsa_SignSha256Base64(const char* pemPrivateKey, const char* data); +const char* Rsa_SignSha384Base64(const char* pemPrivateKey, const char* data); +const char* Rsa_SignSha512Base64(const char* pemPrivateKey, const char* data); +bool Rsa_VerifySha256(const char* pemPublicKey, const char* data, const char* signature); +bool Rsa_VerifySha384(const char* pemPublicKey, const char* data, const char* signature); +bool Rsa_VerifySha512(const char* pemPublicKey, const char* data, const char* signature); +bool Rsa_VerifySha256Base64(const char* pemPublicKey, const char* data, const char* signatureB64); +bool Rsa_VerifySha384Base64(const char* pemPublicKey, const char* data, const char* signatureB64); +bool Rsa_VerifySha512Base64(const char* pemPublicKey, const char* data, const char* signatureB64); +int apply(int (*f)(int), int x); +int Main(void); +int __closure_10(int a); + +void Channel_SendInt(Channel_int* ch, int value) { + void* _t2; + void* _t3; + void* _t1; + _t1 = ch->handle; + _t2 = &value; + _t3 = (void*)_t2; + bux_channel_send(_t1, _t3); } -int Double(int x) { - return x * 2; - +int Channel_RecvInt(Channel_int* ch) { + void* _t5; + void* _t6; + int result; + result = 0; + void* _t4; + _t4 = ch->handle; + _t5 = &result; + _t6 = (void*)_t5; + bux_channel_recv(_t4, _t6); + return result; } -int __closure_2(int a, int b) { - return a + b; - +void Channel_SendFloat64(Channel_float64* ch, double value) { + void* _t8; + void* _t9; + void* _t7; + _t7 = ch->handle; + _t8 = &value; + _t9 = (void*)_t8; + bux_channel_send(_t7, _t9); } -int __closure_3(int x) { - return x * 3; - +double Channel_RecvFloat64(Channel_float64* ch) { + void* _t11; + void* _t12; + double result; + result = 0.0; + void* _t10; + _t10 = ch->handle; + _t11 = &result; + _t12 = (void*)_t11; + bux_channel_recv(_t10, _t12); + return result; } -int main() { - int (*add)(int, int) = &__closure_2; - int sum = add(3, 4); - PrintInt(sum); - PrintLine(""); - int result = Apply(5, &__closure_3); - PrintInt(result); - PrintLine(""); - int (*d)(int) = &Double; - PrintInt(d(7)); - PrintLine(""); +bool DirExists(const char* path) { + int _t14; + int _t13; + _t13 = bux_dir_exists(path); + _t14 = (_t13 != 0); + return _t14; +} + +bool Mkdir(const char* path) { + int _t16; + int _t15; + _t15 = bux_mkdir_if_needed(path); + _t16 = (_t15 != 0); + return _t16; +} + +const char** ListDir(const char* dir, const char* ext, int* count) { + const char** _t17; + _t17 = bux_list_dir(dir, ext, count); + return _t17; +} + +const char* ReadFile(const char* path) { + const char* _t18; + _t18 = bux_read_file(path); + return _t18; +} + +bool WriteFile(const char* path, const char* content) { + int _t20; + int r; + int _t19; + _t19 = bux_write_file(path, content); + r = _t19; + _t20 = (r != 0); + return _t20; +} + +bool FileExists(const char* path) { + int _t22; + int r; + int _t21; + _t21 = bux_file_exists(path); + r = _t21; + _t22 = (r != 0); + return _t22; +} + +double Sqrt(double x) { + double _t23; + _t23 = bux_sqrt(x); + return _t23; +} + +double Pow(double x, double y) { + double _t24; + _t24 = bux_pow(x, y); + return _t24; +} + +int64_t Abs(int64_t n) { + int64_t _t25; + _t25 = bux_abs_i64(n); + return _t25; +} + +double AbsF(double f) { + double _t26; + _t26 = bux_abs_f64(f); + return _t26; +} + +int64_t Min(int64_t a, int64_t b) { + int64_t _t27; + _t27 = bux_min_i64(a, b); + return _t27; +} + +int64_t Max(int64_t a, int64_t b) { + int64_t _t28; + _t28 = bux_max_i64(a, b); + return _t28; +} + +double MinF(double a, double b) { + double _t29; + _t29 = bux_min_f64(a, b); + return _t29; +} + +double MaxF(double a, double b) { + double _t30; + _t30 = bux_max_f64(a, b); + return _t30; +} + +void* Alloc(unsigned int size) { + void* _t31; + _t31 = bux_alloc(size); + return _t31; +} + +void* Realloc(void* ptr, unsigned int size) { + void* _t32; + _t32 = bux_realloc(ptr, size); + return _t32; +} + +void Free(void* ptr) { + bux_free(ptr); +} + +bool MemEq(void* a, void* b, unsigned int size) { + int _t34; + int _t33; + _t33 = bux_mem_eq(a, b, size); + _t34 = (_t33 != 0); + return _t34; +} + +const char* Path_Join(const char* a, const char* b) { + const char* _t35; + _t35 = bux_path_join(a, b); + return _t35; +} + +const char* Path_Parent(const char* path) { + const char* _t36; + _t36 = bux_path_parent(path); + return _t36; +} + +const char* Path_Ext(const char* path) { + const char* _t37; + _t37 = bux_path_ext(path); + return _t37; +} + +TaskHandle Task_Spawn(void* fn, void* arg) { + TaskHandle _t39; + void* _t38; + _t38 = bux_task_spawn(fn, arg); + _t39 = (TaskHandle){.handle = _t38}; + return _t39; +} + +void Task_Join(TaskHandle t) { + void* _t40; + _t40 = t.handle; + bux_task_join(_t40); +} + +void Task_Sleep(int64_t ms) { + bux_task_sleep(ms); +} + +int Os_ArgsCount(void) { + int _t41; + _t41 = bux_argc(); + return _t41; +} + +const char* Os_Args(int index) { + const char* _t42; + _t42 = bux_argv(index); + return _t42; +} + +const char* Os_GetEnv(const char* name) { + const char* _t43; + _t43 = bux_getenv(name); + return _t43; +} + +bool Os_SetEnv(const char* name, const char* value) { + int _t45; + int _t44; + _t44 = bux_setenv(name, value); + _t45 = (_t44 == 0); + return _t45; +} + +const char* Os_GetCwd(void) { + const char* _t46; + _t46 = bux_getcwd(); + return _t46; +} + +bool Os_Chdir(const char* path) { + int _t48; + int _t47; + _t47 = bux_chdir(path); + _t48 = (_t47 == 0); + return _t48; +} + +int64_t Time_NowMs(void) { + int64_t _t49; + _t49 = bux_time_ms(); + return _t49; +} + +int64_t Time_NowUs(void) { + int64_t _t50; + _t50 = bux_time_us(); + return _t50; +} + +void Time_SleepMs(int64_t ms) { + bux_sleep_ms(ms); +} + +int Process_Run(const char* cmd) { + int _t51; + _t51 = bux_process_run(cmd); + return _t51; +} + +const char* Process_Output(const char* cmd) { + const char* _t52; + _t52 = bux_process_output(cmd); + return _t52; +} + +int Net_Create(void) { + int _t53; + _t53 = bux_socket_create(); + return _t53; +} + +bool Net_SetReuse(int fd) { + int _t55; + int _t54; + _t54 = bux_socket_reuse(fd); + _t55 = (_t54 == 0); + return _t55; +} + +bool Net_Bind(int fd, const char* addr, int port) { + int _t57; + int _t56; + _t56 = bux_socket_bind(fd, addr, port); + _t57 = (_t56 == 0); + return _t57; +} + +bool Net_Listen(int fd, int backlog) { + int _t59; + int _t58; + _t58 = bux_socket_listen(fd, backlog); + _t59 = (_t58 == 0); + return _t59; +} + +int Net_Accept(int fd) { + int _t60; + _t60 = bux_socket_accept(fd); + return _t60; +} + +bool Net_Connect(int fd, const char* addr, int port) { + int _t62; + int _t61; + _t61 = bux_socket_connect(fd, addr, port); + _t62 = (_t61 == 0); + return _t62; +} + +int Net_Send(int fd, const char* data) { + int _t64; + unsigned int _t63; + _t63 = bux_strlen(data); + _t64 = (int)_t63; + int _t65; + _t65 = bux_socket_send(fd, data, _t64); + return _t65; +} + +const char* Net_Recv(int fd, int maxLen) { + const char* _t66; + _t66 = bux_socket_recv(fd, maxLen); + return _t66; +} + +bool Net_Close(int fd) { + int _t68; + int _t67; + _t67 = bux_socket_close(fd); + _t68 = (_t67 == 0); + return _t68; +} + +const char* Net_LastError(void) { + const char* _t69; + _t69 = bux_socket_error(); + return _t69; +} + +const char* Fmt_Format(const char* tmpl, const char** argStrs, int argCount) { + int _t72; + int _t75; + int _t76; + int _t79; + int64_t _t80; + int _t81; + int _t83; + int _t84; + int _t87; + unsigned int _t88; + void* _t90; + void* _t91; + int _t92; + void* _t93; + StringBuilder sb; + StringBuilder _t70; + _t70 = StringBuilder_New(); + sb = _t70; + unsigned int i; + i = 0; + unsigned int tmplLen; + unsigned int _t71; + _t71 = bux_strlen(tmpl); + tmplLen = _t71; + while1:; + _t72 = (i < tmplLen); + if (!_t72) goto wend3; + { + const char* ch; + const char* _t73; + _t73 = String_Chars(tmpl, i); + ch = _t73; + bool _t74; + _t74 = String_Eq(ch, "{"); + if (!_t74) goto endif5; + { + unsigned int digitIdx; + _t75 = i + 1; + digitIdx = _t75; + _t76 = (digitIdx < tmplLen); + if (!_t76) goto endif7; + { + const char* digitCh; + const char* _t77; + _t77 = String_Chars(tmpl, digitIdx); + digitCh = _t77; + int64_t d; + int64_t _t78; + _t78 = bux_str_to_int(digitCh); + d = _t78; + bool __and_tmp_0; + _t79 = (d >= 0); + if (!_t79) goto else8; + _t80 = (int64_t)argCount; + _t81 = (d < _t80); + *(bool*)&__and_tmp_0 = _t81; + goto endif9; + else8:; + *(bool*)&__and_tmp_0 = 0; + endif9:; + bool _t82; + _t82 = *(bool*)&__and_tmp_0; + if (!_t82) goto endif11; + { + _t83 = i + 2; + i = _t83; + _t84 = (i < tmplLen); + if (!_t84) goto endif13; + { + const char* closeCh; + const char* _t85; + _t85 = String_Chars(tmpl, i); + closeCh = _t85; + bool _t86; + _t86 = String_Eq(closeCh, "}"); + if (!_t86) goto endif15; + { + _t87 = i + 1; + i = _t87; + const char* argStr; + _t88 = (unsigned int)d; + const char* _t89; + _t89 = argStrs[_t88]; + argStr = _t89; + _t90 = &sb; + StringBuilder_Append(_t90, argStr); + goto while1; + } + endif15:; + } + endif13:; + } + endif11:; + } + endif7:; + } + endif5:; + _t91 = &sb; + StringBuilder_Append(_t91, ch); + _t92 = i + 1; + i = _t92; + } + goto while1; + wend3:; + _t93 = &sb; + const char* _t94; + _t94 = StringBuilder_Build(_t93); + return _t94; +} + +const char* Fmt_Fmt1(const char* tmpl, const char* a1) { + const char** _t97; + const char** args; + /* sizeof(const char*) */ + void* _t96; + _t96 = bux_alloc(sizeof(const char*)); + _t97 = (const char**)_t96; + args = _t97; + args[0] = a1; + const char* _t98; + _t98 = Fmt_Format(tmpl, args, 1); + return _t98; +} + +const char* Fmt_FmtInt(const char* tmpl, int64_t val) { + const char* s; + const char* _t99; + _t99 = String_FromInt(val); + s = _t99; + const char* _t100; + _t100 = Fmt_Fmt1(tmpl, s); + return _t100; +} + +const char* Fmt_FmtBool(const char* tmpl, bool val) { + const char* s; + const char* _t101; + _t101 = String_FromBool(val); + s = _t101; + const char* _t102; + _t102 = Fmt_Fmt1(tmpl, s); + return _t102; +} + +const char* Fmt_FmtFloat(const char* tmpl, double val) { + const char* s; + const char* _t103; + _t103 = String_FromFloat(val); + s = _t103; + const char* _t104; + _t104 = Fmt_Fmt1(tmpl, s); + return _t104; +} + +const char* Fmt_Fmt2(const char* tmpl, const char* a1, const char* a2) { + int _t106; + const char** _t108; + const char** args; + /* sizeof(const char*) */ + _t106 = 2 * sizeof(const char*); + void* _t107; + _t107 = bux_alloc(_t106); + _t108 = (const char**)_t107; + args = _t108; + args[0] = a1; + args[1] = a2; + const char* _t109; + _t109 = Fmt_Format(tmpl, args, 2); + return _t109; +} + +const char* Fmt_Fmt3(const char* tmpl, const char* a1, const char* a2, const char* a3) { + int _t111; + const char** _t113; + const char** args; + /* sizeof(const char*) */ + _t111 = 3 * sizeof(const char*); + void* _t112; + _t112 = bux_alloc(_t111); + _t113 = (const char**)_t112; + args = _t113; + args[0] = a1; + args[1] = a2; + args[2] = a3; + const char* _t114; + _t114 = Fmt_Format(tmpl, args, 3); + return _t114; +} + +const char* Crypto_Sha256(const char* data) { + int _t116; + void* _t118; + int len; + unsigned int _t115; + _t115 = String_Len(data); + _t116 = (int)_t115; + len = _t116; + void* hashBuf; + void* _t117; + _t117 = Alloc(32); + hashBuf = _t117; + bux_sha256(data, len, hashBuf); + const char* result; + _t118 = (void*)hashBuf; + const char* _t119; + _t119 = bux_bytes_to_hex(_t118, 32); + result = _t119; + Free(hashBuf); + return result; +} + +const char* Crypto_HmacSha256(const char* key, const char* message) { + int _t121; + int _t123; + void* _t125; + int keylen; + unsigned int _t120; + _t120 = String_Len(key); + _t121 = (int)_t120; + keylen = _t121; + int msglen; + unsigned int _t122; + _t122 = String_Len(message); + _t123 = (int)_t122; + msglen = _t123; + void* hmacBuf; + void* _t124; + _t124 = Alloc(32); + hmacBuf = _t124; + bux_hmac_sha256(key, keylen, message, msglen, hmacBuf); + const char* result; + _t125 = (void*)hmacBuf; + const char* _t126; + _t126 = bux_bytes_to_hex(_t125, 32); + result = _t126; + Free(hmacBuf); + return result; +} + +const char* Crypto_RandomBytes(int n) { + int _t127; + unsigned int _t128; + int _t131; + const char* _t132; + _t127 = (n <= 0); + if (!_t127) goto endif17; + { + return ""; + } + endif17:; + void* buf; + _t128 = (unsigned int)n; + void* _t129; + _t129 = Alloc(_t128); + buf = _t129; + int _t130; + _t130 = bux_random_bytes(buf, n); + _t131 = (_t130 != 1); + if (!_t131) goto endif19; + { + Free(buf); + return ""; + } + endif19:; + const char* result; + _t132 = (const char*)buf; + const char* _t133; + _t133 = bux_base64_encode(_t132, n); + result = _t133; + Free(buf); + return result; +} + +const char* Crypto_Base64Encode(const char* s) { + int _t135; + unsigned int _t134; + _t134 = String_Len(s); + _t135 = (int)_t134; + const char* _t136; + _t136 = bux_base64_encode(s, _t135); + return _t136; +} + +const char* Crypto_HmacSha256Raw(const char* key, const char* message) { + int _t138; + int _t140; + const char* _t142; + int keylen; + unsigned int _t137; + _t137 = String_Len(key); + _t138 = (int)_t137; + keylen = _t138; + int msglen; + unsigned int _t139; + _t139 = String_Len(message); + _t140 = (int)_t139; + msglen = _t140; + void* hmacBuf; + void* _t141; + _t141 = Alloc(32); + hmacBuf = _t141; + bux_hmac_sha256(key, keylen, message, msglen, hmacBuf); + const char* result; + _t142 = (const char*)hmacBuf; + const char* _t143; + _t143 = bux_base64_encode(_t142, 32); + result = _t143; + Free(hmacBuf); + return result; +} + +const char* Crypto_Base64Decode(const char* s) { + int _t145; + void* _t146; + int outlen; + outlen = 0; + unsigned int _t144; + _t144 = String_Len(s); + _t145 = (int)_t144; + _t146 = &outlen; + const char* _t147; + _t147 = bux_base64_decode(s, _t145, _t146); + return _t147; +} + +Mutex Mutex_New(void) { + Mutex _t149; + void* _t148; + _t148 = bux_mutex_new(); + _t149 = (Mutex){.handle = _t148}; + return _t149; +} + +void Mutex_Lock(Mutex* m) { + void* _t150; + _t150 = m->handle; + bux_mutex_lock(_t150); +} + +void Mutex_Unlock(Mutex* m) { + void* _t151; + _t151 = m->handle; + bux_mutex_unlock(_t151); +} + +void Mutex_Free(Mutex* m) { + void* _t152; + _t152 = m->handle; + bux_mutex_free(_t152); +} + +RwLock RwLock_New(void) { + RwLock _t154; + void* _t153; + _t153 = bux_rwlock_new(); + _t154 = (RwLock){.handle = _t153}; + return _t154; +} + +void RwLock_ReadLock(RwLock* rw) { + void* _t155; + _t155 = rw->handle; + bux_rwlock_rdlock(_t155); +} + +void RwLock_WriteLock(RwLock* rw) { + void* _t156; + _t156 = rw->handle; + bux_rwlock_wrlock(_t156); +} + +void RwLock_Unlock(RwLock* rw) { + void* _t157; + _t157 = rw->handle; + bux_rwlock_unlock(_t157); +} + +void RwLock_Free(RwLock* rw) { + void* _t158; + _t158 = rw->handle; + bux_rwlock_free(_t158); +} + +void Test_Exit(int code) { + bux_exit(code); +} + +void Test_Assert(bool cond) { + int _t159; + _t159 = (int)cond; + bux_assert(_t159, "", 0, ""); +} + +void Test_AssertEqInt(int a, int b) { + int _t160; + _t160 = (a != b); + if (!_t160) goto endif21; + { + PrintLine("ASSERT_EQ FAILED:"); + PrintInt(a); + PrintLine(" != "); + PrintInt(b); + bux_exit(1); + } + endif21:; +} + +void Test_AssertTrue(bool cond) { + int _t161; + _t161 = !cond; + if (!_t161) goto endif23; + { + PrintLine("ASSERT_TRUE FAILED"); + bux_exit(1); + } + endif23:; +} + +void Test_AssertFalse(bool cond) { + if (!cond) goto endif25; + { + PrintLine("ASSERT_FALSE FAILED"); + bux_exit(1); + } + endif25:; +} + +void Test_Fail(const char* msg) { + PrintLine("FAIL:"); + PrintLine(msg); + bux_exit(1); +} + +Result Result_NewOk(int value) { + Result _t162; + Result r; + _t162 = (Result){.tag = Result_Ok}; + r = _t162; + r.data.Ok_0 = value; + return r; +} + +Result Result_NewErr(const char* msg) { + Result _t163; + Result r; + _t163 = (Result){.tag = Result_Err}; + r = _t163; + r.data.Err_0 = msg; + return r; +} + +bool Result_IsOk(Result r) { + int _t165; + Result_Tag _t164; + _t164 = r.tag; + _t165 = (_t164 == Result_Ok); + return _t165; +} + +bool Result_IsErr(Result r) { + int _t167; + Result_Tag _t166; + _t166 = r.tag; + _t167 = (_t166 == Result_Err); + return _t167; +} + +int Result_Unwrap(Result r) { + int _t169; + Result_Tag _t168; + _t168 = r.tag; + _t169 = (_t168 != Result_Ok); + if (!_t169) goto endif27; + { + PrintLine("panic: unwrap on Err"); return 0; - + } + endif27:; + Result_Data _t170; + _t170 = r.data; + int _t171; + _t171 = _t170.Ok_0; + return _t171; } +int Result_UnwrapOr(Result r, int fallback) { + int _t173; + Result_Tag _t172; + _t172 = r.tag; + _t173 = (_t172 == Result_Ok); + if (!_t173) goto endif29; + { + Result_Data _t174; + _t174 = r.data; + int _t175; + _t175 = _t174.Ok_0; + return _t175; + } + endif29:; + return fallback; +} + +Option Option_NewSome(int value) { + Option _t176; + Option o; + _t176 = (Option){.tag = Option_Some}; + o = _t176; + o.data.Some_0 = value; + return o; +} + +Option Option_NewNone(void) { + Option _t177; + _t177 = (Option){.tag = Option_None}; + return _t177; +} + +bool Option_IsSome(Option o) { + int _t179; + Option_Tag _t178; + _t178 = o.tag; + _t179 = (_t178 == Option_Some); + return _t179; +} + +bool Option_IsNone(Option o) { + int _t181; + Option_Tag _t180; + _t180 = o.tag; + _t181 = (_t180 == Option_None); + return _t181; +} + +int Option_Unwrap(Option o) { + int _t183; + Option_Tag _t182; + _t182 = o.tag; + _t183 = (_t182 != Option_Some); + if (!_t183) goto endif31; + { + PrintLine("panic: unwrap on None"); + return 0; + } + endif31:; + Option_Data _t184; + _t184 = o.data; + int _t185; + _t185 = _t184.Some_0; + return _t185; +} + +int Option_UnwrapOr(Option o, int fallback) { + int _t187; + Option_Tag _t186; + _t186 = o.tag; + _t187 = (_t186 == Option_Some); + if (!_t187) goto endif33; + { + Option_Data _t188; + _t188 = o.data; + int _t189; + _t189 = _t188.Some_0; + return _t189; + } + endif33:; + return fallback; +} + +JsonValue Json_Null(void) { + JsonValue _t190; + _t190 = (JsonValue){.tag = JsonTagNull, .boolVal = 0, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0}; + return _t190; +} + +JsonValue Json_Bool(bool b) { + JsonValue _t191; + _t191 = (JsonValue){.tag = JsonTagBool, .boolVal = b, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0}; + return _t191; +} + +JsonValue Json_Number(double n) { + JsonValue _t192; + _t192 = (JsonValue){.tag = JsonTagNumber, .boolVal = 0, .numVal = n, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0}; + return _t192; +} + +JsonValue Json_String(const char* s) { + JsonValue _t193; + _t193 = (JsonValue){.tag = JsonTagString, .boolVal = 0, .numVal = 0.0, .strVal = s, .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0}; + return _t193; +} + +JsonValue Json_Array(void) { + JsonValue _t194; + _t194 = (JsonValue){.tag = JsonTagArray, .boolVal = 0, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0}; + return _t194; +} + +JsonValue Json_Object(void) { + JsonValue _t195; + _t195 = (JsonValue){.tag = JsonTagObject, .boolVal = 0, .numVal = 0.0, .strVal = "", .arrData = 0, .arrLen = 0, .arrCap = 0, .objKeys = 0, .objValues = 0, .objLen = 0, .objCap = 0}; + return _t195; +} + +unsigned int Json_ArrayLen(JsonValue v) { + int _t197; + int _t196; + _t196 = v.tag; + _t197 = (_t196 != JsonTagArray); + if (!_t197) goto endif35; + { + return 0; + } + endif35:; + unsigned int _t198; + _t198 = v.arrLen; + return _t198; +} + +JsonValue Json_ArrayGet(JsonValue v, unsigned int index) { + int _t200; + int _t203; + int _t199; + _t199 = v.tag; + _t200 = (_t199 != JsonTagArray); + if (!_t200) goto endif37; + { + JsonValue _t201; + _t201 = Json_Null(); + return _t201; + } + endif37:; + unsigned int _t202; + _t202 = v.arrLen; + _t203 = (index >= _t202); + if (!_t203) goto endif39; + { + JsonValue _t204; + _t204 = Json_Null(); + return _t204; + } + endif39:; + JsonValue* _t205; + _t205 = v.arrData; + JsonValue _t206; + _t206 = _t205[index]; + return _t206; +} + +void Json_ArrayPush(JsonValue* self, JsonValue val) { + int _t208; + int _t211; + int _t213; + int _t215; + JsonValue* _t217; + int _t218; + void* _t220; + int _t222; + JsonValue* _t224; + int _t228; + int _t207; + _t207 = self->tag; + _t208 = (_t207 != JsonTagArray); + if (!_t208) goto endif41; + { + return; + } + endif41:; + unsigned int _t209; + _t209 = self->arrLen; + unsigned int _t210; + _t210 = self->arrCap; + _t211 = (_t209 >= _t210); + if (!_t211) goto endif43; + { + unsigned int arrNewCap; + unsigned int _t212; + _t212 = self->arrCap; + arrNewCap = _t212; + _t213 = (arrNewCap == 0); + if (!_t213) goto else44; + { + self->arrCap = 4; + /* sizeof(JsonValue) */ + _t215 = 4 * sizeof(JsonValue); + void* _t216; + _t216 = Alloc(_t215); + _t217 = (JsonValue*)_t216; + self->arrData = _t217; + } + goto endif45; + else44:; + { + unsigned int doubleCap; + _t218 = arrNewCap * 2; + doubleCap = _t218; + self->arrCap = doubleCap; + JsonValue* _t219; + _t219 = self->arrData; + _t220 = (void*)_t219; + /* sizeof(JsonValue) */ + _t222 = doubleCap * sizeof(JsonValue); + void* _t223; + _t223 = Realloc(_t220, _t222); + _t224 = (JsonValue*)_t223; + self->arrData = _t224; + } + endif45:; + } + endif43:; + JsonValue* _t225; + _t225 = self->arrData; + unsigned int _t226; + _t226 = self->arrLen; + _t225[_t226] = val; + unsigned int _t227; + _t227 = self->arrLen; + _t228 = _t227 + 1; + self->arrLen = _t228; +} + +unsigned int Json_ObjectLen(JsonValue v) { + int _t230; + int _t229; + _t229 = v.tag; + _t230 = (_t229 != JsonTagObject); + if (!_t230) goto endif47; + { + return 0; + } + endif47:; + unsigned int _t231; + _t231 = v.objLen; + return _t231; +} + +JsonValue Json_ObjectGet(JsonValue v, const char* key) { + int _t233; + int _t236; + int _t242; + int _t232; + _t232 = v.tag; + _t233 = (_t232 != JsonTagObject); + if (!_t233) goto endif49; + { + JsonValue _t234; + _t234 = Json_Null(); + return _t234; + } + endif49:; + unsigned int i; + i = 0; + while50:; + unsigned int _t235; + _t235 = v.objLen; + _t236 = (i < _t235); + if (!_t236) goto wend52; + { + const char** _t237; + _t237 = v.objKeys; + const char* _t238; + _t238 = _t237[i]; + bool _t239; + _t239 = String_Eq(_t238, key); + if (!_t239) goto endif54; + { + JsonValue* _t240; + _t240 = v.objValues; + JsonValue _t241; + _t241 = _t240[i]; + return _t241; + } + endif54:; + _t242 = i + 1; + i = _t242; + } + goto while50; + wend52:; + JsonValue _t243; + _t243 = Json_Null(); + return _t243; +} + +bool Json_ObjectHas(JsonValue v, const char* key) { + int _t245; + int _t247; + int _t251; + int _t244; + _t244 = v.tag; + _t245 = (_t244 != JsonTagObject); + if (!_t245) goto endif56; + { + return 0; + } + endif56:; + unsigned int i; + i = 0; + while57:; + unsigned int _t246; + _t246 = v.objLen; + _t247 = (i < _t246); + if (!_t247) goto wend59; + { + const char** _t248; + _t248 = v.objKeys; + const char* _t249; + _t249 = _t248[i]; + bool _t250; + _t250 = String_Eq(_t249, key); + if (!_t250) goto endif61; + { + return 1; + } + endif61:; + _t251 = i + 1; + i = _t251; + } + goto while57; + wend59:; + return 0; +} + +void Json_ObjectSet(JsonValue* self, const char* key, JsonValue val) { + int _t253; + int _t255; + int _t260; + int _t263; + int _t265; + int _t267; + const char** _t269; + int _t271; + JsonValue* _t273; + int _t274; + void* _t276; + int _t278; + const char** _t280; + void* _t282; + int _t284; + JsonValue* _t286; + int _t292; + int _t252; + _t252 = self->tag; + _t253 = (_t252 != JsonTagObject); + if (!_t253) goto endif63; + { + return; + } + endif63:; + unsigned int i; + i = 0; + while64:; + unsigned int _t254; + _t254 = self->objLen; + _t255 = (i < _t254); + if (!_t255) goto wend66; + { + const char** _t256; + _t256 = self->objKeys; + const char* _t257; + _t257 = _t256[i]; + bool _t258; + _t258 = String_Eq(_t257, key); + if (!_t258) goto endif68; + { + JsonValue* _t259; + _t259 = self->objValues; + _t259[i] = val; + return; + } + endif68:; + _t260 = i + 1; + i = _t260; + } + goto while64; + wend66:; + unsigned int _t261; + _t261 = self->objLen; + unsigned int _t262; + _t262 = self->objCap; + _t263 = (_t261 >= _t262); + if (!_t263) goto endif70; + { + unsigned int objNewCap; + unsigned int _t264; + _t264 = self->objCap; + objNewCap = _t264; + _t265 = (objNewCap == 0); + if (!_t265) goto else71; + { + self->objCap = 4; + /* sizeof(const char*) */ + _t267 = 4 * sizeof(const char*); + void* _t268; + _t268 = Alloc(_t267); + _t269 = (const char**)_t268; + self->objKeys = _t269; + /* sizeof(JsonValue) */ + _t271 = 4 * sizeof(JsonValue); + void* _t272; + _t272 = Alloc(_t271); + _t273 = (JsonValue*)_t272; + self->objValues = _t273; + } + goto endif72; + else71:; + { + unsigned int doubleCap; + _t274 = objNewCap * 2; + doubleCap = _t274; + self->objCap = doubleCap; + const char** _t275; + _t275 = self->objKeys; + _t276 = (void*)_t275; + /* sizeof(const char*) */ + _t278 = doubleCap * sizeof(const char*); + void* _t279; + _t279 = Realloc(_t276, _t278); + _t280 = (const char**)_t279; + self->objKeys = _t280; + JsonValue* _t281; + _t281 = self->objValues; + _t282 = (void*)_t281; + /* sizeof(JsonValue) */ + _t284 = doubleCap * sizeof(JsonValue); + void* _t285; + _t285 = Realloc(_t282, _t284); + _t286 = (JsonValue*)_t285; + self->objValues = _t286; + } + endif72:; + } + endif70:; + const char** _t287; + _t287 = self->objKeys; + unsigned int _t288; + _t288 = self->objLen; + _t287[_t288] = key; + JsonValue* _t289; + _t289 = self->objValues; + unsigned int _t290; + _t290 = self->objLen; + _t289[_t290] = val; + unsigned int _t291; + _t291 = self->objLen; + _t292 = _t291 + 1; + self->objLen = _t292; +} + +bool Json_IsNull(JsonValue v) { + int _t294; + int _t293; + _t293 = v.tag; + _t294 = (_t293 == JsonTagNull); + return _t294; +} + +bool Json_AsBool(JsonValue v) { + int _t296; + int _t295; + _t295 = v.tag; + _t296 = (_t295 == JsonTagBool); + if (!_t296) goto endif74; + { + bool _t297; + _t297 = v.boolVal; + return _t297; + } + endif74:; + return 0; +} + +double Json_AsNumber(JsonValue v) { + int _t299; + int _t298; + _t298 = v.tag; + _t299 = (_t298 == JsonTagNumber); + if (!_t299) goto endif76; + { + double _t300; + _t300 = v.numVal; + return _t300; + } + endif76:; + return 0.0; +} + +const char* Json_AsString(JsonValue v) { + int _t302; + int _t301; + _t301 = v.tag; + _t302 = (_t301 == JsonTagString); + if (!_t302) goto endif78; + { + const char* _t303; + _t303 = v.strVal; + return _t303; + } + endif78:; + return ""; +} + +int JsonParser_Peek(JsonParser* p) { + int _t306; + int _t310; + unsigned int _t304; + _t304 = p->pos; + unsigned int _t305; + _t305 = p->len; + _t306 = (_t304 >= _t305); + if (!_t306) goto endif80; + { + return 0; + } + endif80:; + const char* _t307; + _t307 = p->src; + unsigned int _t308; + _t308 = p->pos; + int _t309; + _t309 = _t307[_t308]; + _t310 = (int)_t309; + return _t310; +} + +void JsonParser_Advance(JsonParser* p) { + int _t313; + int _t315; + unsigned int _t311; + _t311 = p->pos; + unsigned int _t312; + _t312 = p->len; + _t313 = (_t311 < _t312); + if (!_t313) goto endif82; + { + unsigned int _t314; + _t314 = p->pos; + _t315 = _t314 + 1; + p->pos = _t315; + } + endif82:; +} + +void JsonParser_SkipWhitespace(JsonParser* p) { + int _t317; + int _t318; + int _t320; + int _t322; + while83:; + if (!1) goto wend85; + { + int c; + int _t316; + _t316 = JsonParser_Peek(p); + c = _t316; + bool __or_tmp_1; + bool __or_tmp_2; + bool __or_tmp_3; + _t317 = (c == 32); + if (!_t317) goto else86; + *(bool*)&__or_tmp_3 = 1; + goto endif87; + else86:; + _t318 = (c == 9); + *(bool*)&__or_tmp_3 = _t318; + endif87:; + bool _t319; + _t319 = *(bool*)&__or_tmp_3; + if (!_t319) goto else88; + *(bool*)&__or_tmp_2 = 1; + goto endif89; + else88:; + _t320 = (c == 10); + *(bool*)&__or_tmp_2 = _t320; + endif89:; + bool _t321; + _t321 = *(bool*)&__or_tmp_2; + if (!_t321) goto else90; + *(bool*)&__or_tmp_1 = 1; + goto endif91; + else90:; + _t322 = (c == 13); + *(bool*)&__or_tmp_1 = _t322; + endif91:; + bool _t323; + _t323 = *(bool*)&__or_tmp_1; + if (!_t323) goto else92; + { + JsonParser_Advance(p); + } + goto endif93; + else92:; + { + return; + } + endif93:; + } + goto while83; + wend85:; +} + +bool JsonParser_Match(JsonParser* p, const char* expected) { + int _t326; + int _t328; + int _t329; + int _t332; + int _t335; + int _t336; + int _t338; + unsigned int elen; + unsigned int _t324; + _t324 = String_Len(expected); + elen = _t324; + unsigned int _t325; + _t325 = p->pos; + _t326 = _t325 + elen; + unsigned int _t327; + _t327 = p->len; + _t328 = (_t326 > _t327); + if (!_t328) goto endif95; + { + return 0; + } + endif95:; + unsigned int i; + i = 0; + while96:; + _t329 = (i < elen); + if (!_t329) goto wend98; + { + const char* _t330; + _t330 = p->src; + unsigned int _t331; + _t331 = p->pos; + _t332 = _t331 + i; + int _t333; + _t333 = _t330[_t332]; + int _t334; + _t334 = expected[i]; + _t335 = (_t333 != _t334); + if (!_t335) goto endif100; + { + return 0; + } + endif100:; + _t336 = i + 1; + i = _t336; + } + goto while96; + wend98:; + unsigned int _t337; + _t337 = p->pos; + _t338 = _t337 + elen; + p->pos = _t338; + return 1; +} + +const char* JsonParser_ParseString(JsonParser* p) { + int _t340; + int _t343; + int _t344; + int _t346; + int _t348; + void* _t349; + int _t350; + void* _t351; + char _t352; + int _t353; + void* _t354; + char _t355; + int _t356; + void* _t357; + char _t358; + int _t359; + void* _t360; + char _t361; + int _t362; + void* _t363; + char _t364; + int _t365; + void* _t366; + char _t367; + int _t368; + void* _t369; + char _t370; + void* _t371; + char _t372; + void* _t373; + char _t374; + void* _t375; + char _t376; + int _t378; + void* _t379; + void* _t380; + void* _t382; + int _t339; + _t339 = JsonParser_Peek(p); + _t340 = (_t339 != 34); + if (!_t340) goto endif102; + { + p->error = "Expected string"; + return ""; + } + endif102:; + JsonParser_Advance(p); + StringBuilder sb; + StringBuilder _t341; + _t341 = StringBuilder_New(); + sb = _t341; + while103:; + if (!1) goto wend105; + { + int c; + int _t342; + _t342 = JsonParser_Peek(p); + c = _t342; + bool __or_tmp_4; + _t343 = (c == 0); + if (!_t343) goto else106; + *(bool*)&__or_tmp_4 = 1; + goto endif107; + else106:; + _t344 = (c == 34); + *(bool*)&__or_tmp_4 = _t344; + endif107:; + bool _t345; + _t345 = *(bool*)&__or_tmp_4; + if (!_t345) goto endif109; + { + goto wend105; + } + endif109:; + _t346 = (c == 92); + if (!_t346) goto else110; + { + JsonParser_Advance(p); + int esc; + int _t347; + _t347 = JsonParser_Peek(p); + esc = _t347; + _t348 = (esc == 0); + if (!_t348) goto endif113; + { + p->error = "Unterminated string escape"; + _t349 = &sb; + StringBuilder_Free(_t349); + return ""; + } + endif113:; + _t350 = (esc == 110); + if (!_t350) goto else114; + { + _t351 = &sb; + _t352 = (char)10; + StringBuilder_AppendChar(_t351, _t352); + } + goto endif115; + else114:; + _t353 = (esc == 116); + if (!_t353) goto else116; + { + _t354 = &sb; + _t355 = (char)9; + StringBuilder_AppendChar(_t354, _t355); + } + goto endif117; + else116:; + _t356 = (esc == 114); + if (!_t356) goto else118; + { + _t357 = &sb; + _t358 = (char)13; + StringBuilder_AppendChar(_t357, _t358); + } + goto endif119; + else118:; + _t359 = (esc == 98); + if (!_t359) goto else120; + { + _t360 = &sb; + _t361 = (char)8; + StringBuilder_AppendChar(_t360, _t361); + } + goto endif121; + else120:; + _t362 = (esc == 102); + if (!_t362) goto else122; + { + _t363 = &sb; + _t364 = (char)12; + StringBuilder_AppendChar(_t363, _t364); + } + goto endif123; + else122:; + _t365 = (esc == 34); + if (!_t365) goto else124; + { + _t366 = &sb; + _t367 = (char)34; + StringBuilder_AppendChar(_t366, _t367); + } + goto endif125; + else124:; + _t368 = (esc == 92); + if (!_t368) goto else126; + { + _t369 = &sb; + _t370 = (char)92; + StringBuilder_AppendChar(_t369, _t370); + } + goto endif127; + else126:; + { + _t371 = &sb; + _t372 = (char)92; + StringBuilder_AppendChar(_t371, _t372); + _t373 = &sb; + _t374 = (char)esc; + StringBuilder_AppendChar(_t373, _t374); + } + endif127:; + endif125:; + endif123:; + endif121:; + endif119:; + endif117:; + endif115:; + JsonParser_Advance(p); + } + goto endif111; + else110:; + { + _t375 = &sb; + _t376 = (char)c; + StringBuilder_AppendChar(_t375, _t376); + JsonParser_Advance(p); + } + endif111:; + } + goto while103; + wend105:; + int _t377; + _t377 = JsonParser_Peek(p); + _t378 = (_t377 != 34); + if (!_t378) goto endif129; + { + p->error = "Unterminated string"; + _t379 = &sb; + StringBuilder_Free(_t379); + return ""; + } + endif129:; + JsonParser_Advance(p); + const char* result; + _t380 = &sb; + const char* _t381; + _t381 = StringBuilder_Build(_t380); + result = _t381; + _t382 = &sb; + StringBuilder_Free(_t382); + return result; +} + +JsonValue JsonParser_ParseNumber(JsonParser* p) { + int _t385; + int _t387; + int _t388; + int _t391; + int _t393; + int _t394; + int _t398; + unsigned int start; + unsigned int _t383; + _t383 = p->pos; + start = _t383; + int c0; + int _t384; + _t384 = JsonParser_Peek(p); + c0 = _t384; + _t385 = (c0 == 45); + if (!_t385) goto endif131; + { + JsonParser_Advance(p); + } + endif131:; + while132:; + if (!1) goto wend134; + { + int c; + int _t386; + _t386 = JsonParser_Peek(p); + c = _t386; + bool __and_tmp_5; + _t387 = (c >= 48); + if (!_t387) goto else135; + _t388 = (c <= 57); + *(bool*)&__and_tmp_5 = _t388; + goto endif136; + else135:; + *(bool*)&__and_tmp_5 = 0; + endif136:; + bool _t389; + _t389 = *(bool*)&__and_tmp_5; + if (!_t389) goto else137; + { + JsonParser_Advance(p); + } + goto endif138; + else137:; + { + goto wend134; + } + endif138:; + } + goto while132; + wend134:; + int _t390; + _t390 = JsonParser_Peek(p); + _t391 = (_t390 == 46); + if (!_t391) goto endif140; + { + JsonParser_Advance(p); + while141:; + if (!1) goto wend143; + { + int c; + int _t392; + _t392 = JsonParser_Peek(p); + c = _t392; + bool __and_tmp_6; + _t393 = (c >= 48); + if (!_t393) goto else144; + _t394 = (c <= 57); + *(bool*)&__and_tmp_6 = _t394; + goto endif145; + else144:; + *(bool*)&__and_tmp_6 = 0; + endif145:; + bool _t395; + _t395 = *(bool*)&__and_tmp_6; + if (!_t395) goto else146; + { + JsonParser_Advance(p); + } + goto endif147; + else146:; + { + goto wend143; + } + endif147:; + } + goto while141; + wend143:; + } + endif140:; + const char* numStr; + const char* _t396; + _t396 = p->src; + unsigned int _t397; + _t397 = p->pos; + _t398 = _t397 - start; + const char* _t399; + _t399 = String_Slice(_t396, start, _t398); + numStr = _t399; + double n; + double _t400; + _t400 = String_ToFloat(numStr); + n = _t400; + JsonValue _t401; + _t401 = Json_Number(n); + return _t401; +} + +JsonValue JsonParser_ParseArray(JsonParser* p) { + int _t404; + int _t407; + void* _t409; + int _t411; + int _t412; + JsonParser_Advance(p); + JsonValue arr; + JsonValue _t402; + _t402 = Json_Array(); + arr = _t402; + JsonParser_SkipWhitespace(p); + int _t403; + _t403 = JsonParser_Peek(p); + _t404 = (_t403 == 93); + if (!_t404) goto endif149; + { + JsonParser_Advance(p); + return arr; + } + endif149:; + while150:; + if (!1) goto wend152; + { + JsonParser_SkipWhitespace(p); + JsonValue val; + JsonValue _t405; + _t405 = JsonParser_ParseValue(p); + val = _t405; + const char* _t406; + _t406 = p->error; + _t407 = (_t406 != ""); + if (!_t407) goto endif154; + { + JsonValue _t408; + _t408 = Json_Null(); + return _t408; + } + endif154:; + _t409 = &arr; + Json_ArrayPush(_t409, val); + JsonParser_SkipWhitespace(p); + int c; + int _t410; + _t410 = JsonParser_Peek(p); + c = _t410; + _t411 = (c == 93); + if (!_t411) goto endif156; + { + JsonParser_Advance(p); + return arr; + } + endif156:; + _t412 = (c == 44); + if (!_t412) goto else157; + { + JsonParser_Advance(p); + } + goto endif158; + else157:; + { + p->error = "Expected ',' or ']' in array"; + JsonValue _t413; + _t413 = Json_Null(); + return _t413; + } + endif158:; + } + goto while150; + wend152:; +} + +JsonValue JsonParser_ParseObject(JsonParser* p) { + int _t416; + int _t419; + int _t422; + int _t426; + void* _t428; + int _t430; + int _t431; + JsonParser_Advance(p); + JsonValue obj; + JsonValue _t414; + _t414 = Json_Object(); + obj = _t414; + JsonParser_SkipWhitespace(p); + int _t415; + _t415 = JsonParser_Peek(p); + _t416 = (_t415 == 125); + if (!_t416) goto endif160; + { + JsonParser_Advance(p); + return obj; + } + endif160:; + while161:; + if (!1) goto wend163; + { + JsonParser_SkipWhitespace(p); + const char* key; + const char* _t417; + _t417 = JsonParser_ParseString(p); + key = _t417; + const char* _t418; + _t418 = p->error; + _t419 = (_t418 != ""); + if (!_t419) goto endif165; + { + JsonValue _t420; + _t420 = Json_Null(); + return _t420; + } + endif165:; + JsonParser_SkipWhitespace(p); + int _t421; + _t421 = JsonParser_Peek(p); + _t422 = (_t421 != 58); + if (!_t422) goto endif167; + { + p->error = "Expected ':' after object key"; + JsonValue _t423; + _t423 = Json_Null(); + return _t423; + } + endif167:; + JsonParser_Advance(p); + JsonParser_SkipWhitespace(p); + JsonValue val; + JsonValue _t424; + _t424 = JsonParser_ParseValue(p); + val = _t424; + const char* _t425; + _t425 = p->error; + _t426 = (_t425 != ""); + if (!_t426) goto endif169; + { + JsonValue _t427; + _t427 = Json_Null(); + return _t427; + } + endif169:; + _t428 = &obj; + Json_ObjectSet(_t428, key, val); + JsonParser_SkipWhitespace(p); + int c; + int _t429; + _t429 = JsonParser_Peek(p); + c = _t429; + _t430 = (c == 125); + if (!_t430) goto endif171; + { + JsonParser_Advance(p); + return obj; + } + endif171:; + _t431 = (c == 44); + if (!_t431) goto else172; + { + JsonParser_Advance(p); + } + goto endif173; + else172:; + { + p->error = "Expected ',' or '}' in object"; + JsonValue _t432; + _t432 = Json_Null(); + return _t432; + } + endif173:; + } + goto while161; + wend163:; +} + +JsonValue JsonParser_ParseValue(JsonParser* p) { + int _t434; + int _t436; + int _t439; + int _t441; + int _t443; + int _t447; + int _t451; + int _t455; + int _t456; + int _t458; + JsonParser_SkipWhitespace(p); + int c; + int _t433; + _t433 = JsonParser_Peek(p); + c = _t433; + _t434 = (c == 0); + if (!_t434) goto endif175; + { + p->error = "Unexpected end of input"; + JsonValue _t435; + _t435 = Json_Null(); + return _t435; + } + endif175:; + _t436 = (c == 34); + if (!_t436) goto endif177; + { + const char* _t437; + _t437 = JsonParser_ParseString(p); + JsonValue _t438; + _t438 = Json_String(_t437); + return _t438; + } + endif177:; + _t439 = (c == 123); + if (!_t439) goto endif179; + { + JsonValue _t440; + _t440 = JsonParser_ParseObject(p); + return _t440; + } + endif179:; + _t441 = (c == 91); + if (!_t441) goto endif181; + { + JsonValue _t442; + _t442 = JsonParser_ParseArray(p); + return _t442; + } + endif181:; + _t443 = (c == 116); + if (!_t443) goto endif183; + { + bool _t444; + _t444 = JsonParser_Match(p, "true"); + if (!_t444) goto endif185; + { + JsonValue _t445; + _t445 = Json_Bool(1); + return _t445; + } + endif185:; + p->error = "Expected 'true'"; + JsonValue _t446; + _t446 = Json_Null(); + return _t446; + } + endif183:; + _t447 = (c == 102); + if (!_t447) goto endif187; + { + bool _t448; + _t448 = JsonParser_Match(p, "false"); + if (!_t448) goto endif189; + { + JsonValue _t449; + _t449 = Json_Bool(0); + return _t449; + } + endif189:; + p->error = "Expected 'false'"; + JsonValue _t450; + _t450 = Json_Null(); + return _t450; + } + endif187:; + _t451 = (c == 110); + if (!_t451) goto endif191; + { + bool _t452; + _t452 = JsonParser_Match(p, "null"); + if (!_t452) goto endif193; + { + JsonValue _t453; + _t453 = Json_Null(); + return _t453; + } + endif193:; + p->error = "Expected 'null'"; + JsonValue _t454; + _t454 = Json_Null(); + return _t454; + } + endif191:; + bool __or_tmp_7; + bool __and_tmp_8; + _t455 = (c >= 48); + if (!_t455) goto else194; + _t456 = (c <= 57); + *(bool*)&__and_tmp_8 = _t456; + goto endif195; + else194:; + *(bool*)&__and_tmp_8 = 0; + endif195:; + bool _t457; + _t457 = *(bool*)&__and_tmp_8; + if (!_t457) goto else196; + *(bool*)&__or_tmp_7 = 1; + goto endif197; + else196:; + _t458 = (c == 45); + *(bool*)&__or_tmp_7 = _t458; + endif197:; + bool _t459; + _t459 = *(bool*)&__or_tmp_7; + if (!_t459) goto endif199; + { + JsonValue _t460; + _t460 = JsonParser_ParseNumber(p); + return _t460; + } + endif199:; + p->error = "Unexpected character"; + JsonValue _t461; + _t461 = Json_Null(); + return _t461; +} + +JsonValue Json_Parse(const char* s) { + JsonParser _t463; + void* _t464; + void* _t466; + int _t468; + int _t471; + JsonParser p; + unsigned int _t462; + _t462 = String_Len(s); + _t463 = (JsonParser){.src = s, .pos = 0, .len = _t462, .error = ""}; + p = _t463; + JsonValue result; + _t464 = &p; + JsonValue _t465; + _t465 = JsonParser_ParseValue(_t464); + result = _t465; + _t466 = &p; + JsonParser_SkipWhitespace(_t466); + bool __and_tmp_9; + const char* _t467; + _t467 = p.error; + _t468 = (_t467 == ""); + if (!_t468) goto else200; + unsigned int _t469; + _t469 = p.pos; + unsigned int _t470; + _t470 = p.len; + _t471 = (_t469 != _t470); + *(bool*)&__and_tmp_9 = _t471; + goto endif201; + else200:; + *(bool*)&__and_tmp_9 = 0; + endif201:; + bool _t472; + _t472 = *(bool*)&__and_tmp_9; + if (!_t472) goto endif203; + { + p.error = "Trailing data after JSON value"; + JsonValue _t473; + _t473 = Json_Null(); + return _t473; + } + endif203:; + return result; +} + +void Json_StringifyImpl(StringBuilder* sb, JsonValue v) { + int _t475; + int _t477; + int _t480; + int _t483; + char _t484; + char _t486; + int _t488; + char _t489; + int _t491; + int _t492; + char _t493; + int _t496; + char _t497; + int _t499; + char _t500; + int _t502; + int _t503; + char _t504; + char _t505; + char _t508; + char _t509; + int _t512; + char _t513; + int _t474; + _t474 = v.tag; + _t475 = (_t474 == JsonTagNull); + if (!_t475) goto endif205; + { + StringBuilder_Append(sb, "null"); + return; + } + endif205:; + int _t476; + _t476 = v.tag; + _t477 = (_t476 == JsonTagBool); + if (!_t477) goto endif207; + { + bool _t478; + _t478 = v.boolVal; + if (!_t478) goto else208; + { + StringBuilder_Append(sb, "true"); + } + goto endif209; + else208:; + { + StringBuilder_Append(sb, "false"); + } + endif209:; + return; + } + endif207:; + int _t479; + _t479 = v.tag; + _t480 = (_t479 == JsonTagNumber); + if (!_t480) goto endif211; + { + double _t481; + _t481 = v.numVal; + StringBuilder_AppendFloat(sb, _t481); + return; + } + endif211:; + int _t482; + _t482 = v.tag; + _t483 = (_t482 == JsonTagString); + if (!_t483) goto endif213; + { + _t484 = (char)34; + StringBuilder_AppendChar(sb, _t484); + const char* _t485; + _t485 = v.strVal; + StringBuilder_Append(sb, _t485); + _t486 = (char)34; + StringBuilder_AppendChar(sb, _t486); + return; + } + endif213:; + int _t487; + _t487 = v.tag; + _t488 = (_t487 == JsonTagArray); + if (!_t488) goto endif215; + { + _t489 = (char)91; + StringBuilder_AppendChar(sb, _t489); + unsigned int i; + i = 0; + while216:; + unsigned int _t490; + _t490 = v.arrLen; + _t491 = (i < _t490); + if (!_t491) goto wend218; + { + _t492 = (i > 0); + if (!_t492) goto endif220; + { + _t493 = (char)44; + StringBuilder_AppendChar(sb, _t493); + } + endif220:; + JsonValue* _t494; + _t494 = v.arrData; + JsonValue _t495; + _t495 = _t494[i]; + Json_StringifyImpl(sb, _t495); + _t496 = i + 1; + i = _t496; + } + goto while216; + wend218:; + _t497 = (char)93; + StringBuilder_AppendChar(sb, _t497); + return; + } + endif215:; + int _t498; + _t498 = v.tag; + _t499 = (_t498 == JsonTagObject); + if (!_t499) goto endif222; + { + _t500 = (char)123; + StringBuilder_AppendChar(sb, _t500); + unsigned int i; + i = 0; + while223:; + unsigned int _t501; + _t501 = v.objLen; + _t502 = (i < _t501); + if (!_t502) goto wend225; + { + _t503 = (i > 0); + if (!_t503) goto endif227; + { + _t504 = (char)44; + StringBuilder_AppendChar(sb, _t504); + } + endif227:; + _t505 = (char)34; + StringBuilder_AppendChar(sb, _t505); + const char** _t506; + _t506 = v.objKeys; + const char* _t507; + _t507 = _t506[i]; + StringBuilder_Append(sb, _t507); + _t508 = (char)34; + StringBuilder_AppendChar(sb, _t508); + _t509 = (char)58; + StringBuilder_AppendChar(sb, _t509); + JsonValue* _t510; + _t510 = v.objValues; + JsonValue _t511; + _t511 = _t510[i]; + Json_StringifyImpl(sb, _t511); + _t512 = i + 1; + i = _t512; + } + goto while223; + wend225:; + _t513 = (char)125; + StringBuilder_AppendChar(sb, _t513); + return; + } + endif222:; +} + +const char* Json_Stringify(JsonValue v) { + void* _t515; + void* _t516; + StringBuilder sb; + StringBuilder _t514; + _t514 = StringBuilder_New(); + sb = _t514; + _t515 = &sb; + Json_StringifyImpl(_t515, v); + _t516 = &sb; + const char* _t517; + _t517 = StringBuilder_Build(_t516); + return _t517; +} + +unsigned int String_Len(const char* s) { + unsigned int _t518; + _t518 = bux_strlen(s); + return _t518; +} + +bool String_IsNull(const char* s) { + int _t520; + int _t519; + _t519 = bux_str_is_null(s); + _t520 = (_t519 != 0); + return _t520; +} + +bool String_Eq(const char* a, const char* b) { + int _t522; + int _t521; + _t521 = bux_strcmp(a, b); + _t522 = (_t521 == 0); + return _t522; +} + +const char* String_Concat(const char* a, const char* b) { + int _t525; + int _t526; + char* _t528; + unsigned int len_a; + unsigned int _t523; + _t523 = bux_strlen(a); + len_a = _t523; + unsigned int len_b; + unsigned int _t524; + _t524 = bux_strlen(b); + len_b = _t524; + unsigned int total; + _t525 = len_a + len_b; + _t526 = _t525 + 1; + total = _t526; + char* buf; + void* _t527; + _t527 = bux_alloc(total); + _t528 = (char*)_t527; + buf = _t528; + bux_strcpy(buf, a); + bux_strcat(buf, b); + return buf; +} + +const char* String_Copy(const char* s) { + int _t530; + char* _t532; + unsigned int len; + unsigned int _t529; + _t529 = bux_strlen(s); + len = _t529; + char* buf; + _t530 = len + 1; + void* _t531; + _t531 = bux_alloc(_t530); + _t532 = (char*)_t531; + buf = _t532; + bux_strcpy(buf, s); + return buf; +} + +bool String_StartsWith(const char* s, const char* prefix) { + int _t535; + int _t537; + unsigned int s_len; + unsigned int _t533; + _t533 = bux_strlen(s); + s_len = _t533; + unsigned int p_len; + unsigned int _t534; + _t534 = bux_strlen(prefix); + p_len = _t534; + _t535 = (p_len > s_len); + if (!_t535) goto endif229; + { + return 0; + } + endif229:; + int r; + int _t536; + _t536 = bux_strncmp(s, prefix, p_len); + r = _t536; + _t537 = (r == 0); + return _t537; +} + +bool String_EndsWith(const char* s, const char* suffix) { + int _t540; + int _t541; + int _t544; + unsigned int s_len; + unsigned int _t538; + _t538 = bux_strlen(s); + s_len = _t538; + unsigned int suf_len; + unsigned int _t539; + _t539 = bux_strlen(suffix); + suf_len = _t539; + _t540 = (suf_len > s_len); + if (!_t540) goto endif231; + { + return 0; + } + endif231:; + unsigned int start; + _t541 = s_len - suf_len; + start = _t541; + const char* tail; + const char* _t542; + _t542 = bux_str_slice(s, start, suf_len); + tail = _t542; + bool eq; + int _t543; + _t543 = bux_strcmp(tail, suffix); + _t544 = (_t543 == 0); + eq = _t544; + return eq; +} + +bool String_Contains(const char* s, const char* substr) { + int _t546; + int r; + int _t545; + _t545 = bux_str_contains(s, substr); + r = _t545; + _t546 = (r != 0); + return _t546; +} + +const char* String_Slice(const char* s, unsigned int start, unsigned int len) { + const char* _t547; + _t547 = bux_str_slice(s, start, len); + return _t547; +} + +const char* String_Trim(const char* s) { + const char* _t548; + _t548 = bux_str_trim(s); + return _t548; +} + +const char* String_TrimLeft(const char* s) { + const char* _t549; + _t549 = bux_str_trim_left(s); + return _t549; +} + +const char* String_TrimRight(const char* s) { + const char* _t550; + _t550 = bux_str_trim_right(s); + return _t550; +} + +const char* String_FromInt(int64_t n) { + const char* _t551; + _t551 = bux_int_to_str(n); + return _t551; +} + +int64_t String_ToInt(const char* s) { + int64_t _t552; + _t552 = bux_str_to_int(s); + return _t552; +} + +StringBuilder StringBuilder_New(void) { + StringBuilder _t554; + void* _t553; + _t553 = bux_sb_new(64); + _t554 = (StringBuilder){.handle = _t553}; + return _t554; +} + +StringBuilder StringBuilder_NewCap(unsigned int cap) { + StringBuilder _t556; + void* _t555; + _t555 = bux_sb_new(cap); + _t556 = (StringBuilder){.handle = _t555}; + return _t556; +} + +void StringBuilder_Append(StringBuilder* sb, const char* s) { + void* _t557; + _t557 = sb->handle; + bux_sb_append(_t557, s); +} + +void StringBuilder_AppendInt(StringBuilder* sb, int64_t n) { + void* _t558; + _t558 = sb->handle; + bux_sb_append_int(_t558, n); +} + +void StringBuilder_AppendFloat(StringBuilder* sb, double f) { + void* _t559; + _t559 = sb->handle; + bux_sb_append_float(_t559, f); +} + +void StringBuilder_AppendChar(StringBuilder* sb, char c) { + void* _t560; + _t560 = sb->handle; + bux_sb_append_char(_t560, c); +} + +const char* StringBuilder_Build(StringBuilder* sb) { + void* _t561; + _t561 = sb->handle; + const char* _t562; + _t562 = bux_sb_build(_t561); + return _t562; +} + +void StringBuilder_Free(StringBuilder* sb) { + void* _t563; + _t563 = sb->handle; + bux_sb_free(_t563); +} + +unsigned int String_SplitCount(const char* s, const char* delim) { + unsigned int _t564; + _t564 = bux_str_split_count(s, delim); + return _t564; +} + +const char* String_SplitPart(const char* s, const char* delim, unsigned int index) { + const char* _t565; + _t565 = bux_str_split_part(s, delim, index); + return _t565; +} + +const char* String_Join2(const char* a, const char* b, const char* sep) { + const char* _t566; + _t566 = bux_str_join2(a, b, sep); + return _t566; +} + +const char* String_Chars(const char* s, unsigned int index) { + const char* _t567; + _t567 = bux_str_slice(s, index, 1); + return _t567; +} + +const char* String_Find(const char* haystack, const char* needle) { + const char* _t568; + _t568 = bux_strstr(haystack, needle); + return _t568; +} + +unsigned int String_Offset(const char* pos, const char* base) { + unsigned int _t569; + _t569 = bux_str_offset(pos, base); + return _t569; +} + +const char* String_Replace(const char* s, const char* old, const char* new) { + int _t575; + int _t577; + int _t578; + const char* pos; + const char* _t570; + _t570 = bux_strstr(s, old); + pos = _t570; + bool _t571; + _t571 = String_IsNull(pos); + if (!_t571) goto endif233; + { + return s; + } + endif233:; + unsigned int oldLen; + unsigned int _t572; + _t572 = bux_strlen(old); + oldLen = _t572; + unsigned int prefixLen; + unsigned int _t573; + _t573 = String_Offset(pos, s); + prefixLen = _t573; + const char* prefix; + const char* _t574; + _t574 = bux_str_slice(s, 0, prefixLen); + prefix = _t574; + const char* suffix; + _t575 = prefixLen + oldLen; + unsigned int _t576; + _t576 = bux_strlen(s); + _t577 = _t576 - prefixLen; + _t578 = _t577 - oldLen; + const char* _t579; + _t579 = bux_str_slice(s, _t575, _t578); + suffix = _t579; + const char* temp; + const char* _t580; + _t580 = String_Concat(prefix, new); + temp = _t580; + const char* result; + const char* _t581; + _t581 = String_Concat(temp, suffix); + result = _t581; + return result; +} + +double String_ToFloat(const char* s) { + double _t582; + _t582 = bux_str_to_float(s); + return _t582; +} + +const char* String_FromBool(bool b) { + if (!b) goto endif235; + { + return "true"; + } + endif235:; + return "false"; +} + +const char* String_FromFloat(double f) { + const char* _t583; + _t583 = bux_float_to_string(f); + return _t583; +} + +const char* String_Format1(const char* pattern, const char* a0) { + const char* _t584; + _t584 = bux_str_format(pattern, a0, "", "", "", "", "", "", ""); + return _t584; +} + +const char* String_Format2(const char* pattern, const char* a0, const char* a1) { + const char* _t585; + _t585 = bux_str_format(pattern, a0, a1, "", "", "", "", "", ""); + return _t585; +} + +const char* String_Format3(const char* pattern, const char* a0, const char* a1, const char* a2) { + const char* _t586; + _t586 = bux_str_format(pattern, a0, a1, a2, "", "", "", "", ""); + return _t586; +} + +const char* Hash_Sha1(const char* data) { + int _t588; + int len; + unsigned int _t587; + _t587 = String_Len(data); + _t588 = (int)_t587; + len = _t588; + void* buf; + void* _t589; + _t589 = Alloc(20); + buf = _t589; + bux_sha1(data, len, buf); + const char* result; + const char* _t590; + _t590 = bux_bytes_to_hex(buf, 20); + result = _t590; + Free(buf); + return result; +} + +const char* Hash_Sha256(const char* data) { + int _t592; + int len; + unsigned int _t591; + _t591 = String_Len(data); + _t592 = (int)_t591; + len = _t592; + void* buf; + void* _t593; + _t593 = Alloc(32); + buf = _t593; + bux_sha256(data, len, buf); + const char* result; + const char* _t594; + _t594 = bux_bytes_to_hex(buf, 32); + result = _t594; + Free(buf); + return result; +} + +const char* Hash_Sha384(const char* data) { + int _t596; + int len; + unsigned int _t595; + _t595 = String_Len(data); + _t596 = (int)_t595; + len = _t596; + void* buf; + void* _t597; + _t597 = Alloc(48); + buf = _t597; + bux_sha384(data, len, buf); + const char* result; + const char* _t598; + _t598 = bux_bytes_to_hex(buf, 48); + result = _t598; + Free(buf); + return result; +} + +const char* Hash_Sha512(const char* data) { + int _t600; + int len; + unsigned int _t599; + _t599 = String_Len(data); + _t600 = (int)_t599; + len = _t600; + void* buf; + void* _t601; + _t601 = Alloc(64); + buf = _t601; + bux_sha512(data, len, buf); + const char* result; + const char* _t602; + _t602 = bux_bytes_to_hex(buf, 64); + result = _t602; + Free(buf); + return result; +} + +void Hash_Sha256Raw(const char* data, void* out) { + int _t604; + unsigned int _t603; + _t603 = String_Len(data); + _t604 = (int)_t603; + bux_sha256(data, _t604, out); +} + +void Hash_Sha384Raw(const char* data, void* out) { + int _t606; + unsigned int _t605; + _t605 = String_Len(data); + _t606 = (int)_t605; + bux_sha384(data, _t606, out); +} + +void Hash_Sha512Raw(const char* data, void* out) { + int _t608; + unsigned int _t607; + _t607 = String_Len(data); + _t608 = (int)_t607; + bux_sha512(data, _t608, out); +} + +int Hash_Sha1Size(void) { + return 20; +} + +int Hash_Sha256Size(void) { + return 32; +} + +int Hash_Sha384Size(void) { + return 48; +} + +int Hash_Sha512Size(void) { + return 64; +} + +const char* Base64_Encode(const char* s) { + int _t610; + unsigned int _t609; + _t609 = String_Len(s); + _t610 = (int)_t609; + const char* _t611; + _t611 = bux_base64_encode(s, _t610); + return _t611; +} + +const char* Base64_Decode(const char* s) { + int _t613; + void* _t614; + int outlen; + outlen = 0; + unsigned int _t612; + _t612 = String_Len(s); + _t613 = (int)_t612; + _t614 = &outlen; + const char* _t615; + _t615 = bux_base64_decode(s, _t613, _t614); + return _t615; +} + +const char* Base64URL_Encode(const char* s) { + int _t617; + unsigned int _t616; + _t616 = String_Len(s); + _t617 = (int)_t616; + const char* _t618; + _t618 = bux_base64url_encode(s, _t617); + return _t618; +} + +const char* Base64URL_Decode(const char* s) { + int _t620; + void* _t621; + int outlen; + outlen = 0; + unsigned int _t619; + _t619 = String_Len(s); + _t620 = (int)_t619; + _t621 = &outlen; + const char* _t622; + _t622 = bux_base64url_decode(s, _t620, _t621); + return _t622; +} + +const char* Hmac_Sha256(const char* key, const char* message) { + int _t624; + int _t626; + int kl; + unsigned int _t623; + _t623 = String_Len(key); + _t624 = (int)_t623; + kl = _t624; + int ml; + unsigned int _t625; + _t625 = String_Len(message); + _t626 = (int)_t625; + ml = _t626; + void* buf; + void* _t627; + _t627 = Alloc(32); + buf = _t627; + bux_hmac_sha256(key, kl, message, ml, buf); + const char* result; + const char* _t628; + _t628 = bux_bytes_to_hex(buf, 32); + result = _t628; + Free(buf); + return result; +} + +void Hmac_Sha256Raw(const char* key, const char* message, void* out) { + int _t630; + int _t632; + unsigned int _t629; + _t629 = String_Len(key); + _t630 = (int)_t629; + unsigned int _t631; + _t631 = String_Len(message); + _t632 = (int)_t631; + bux_hmac_sha256(key, _t630, message, _t632, out); +} + +const char* Hmac_Sha256Base64(const char* key, const char* message) { + int _t634; + int _t636; + const char* _t638; + int kl; + unsigned int _t633; + _t633 = String_Len(key); + _t634 = (int)_t633; + kl = _t634; + int ml; + unsigned int _t635; + _t635 = String_Len(message); + _t636 = (int)_t635; + ml = _t636; + void* buf; + void* _t637; + _t637 = Alloc(32); + buf = _t637; + bux_hmac_sha256(key, kl, message, ml, buf); + const char* result; + _t638 = (const char*)buf; + const char* _t639; + _t639 = bux_base64_encode(_t638, 32); + result = _t639; + Free(buf); + return result; +} + +const char* Hmac_Sha384(const char* key, const char* message) { + int _t641; + int _t643; + int kl; + unsigned int _t640; + _t640 = String_Len(key); + _t641 = (int)_t640; + kl = _t641; + int ml; + unsigned int _t642; + _t642 = String_Len(message); + _t643 = (int)_t642; + ml = _t643; + void* buf; + void* _t644; + _t644 = Alloc(48); + buf = _t644; + bux_hmac_sha384(key, kl, message, ml, buf); + const char* result; + const char* _t645; + _t645 = bux_bytes_to_hex(buf, 48); + result = _t645; + Free(buf); + return result; +} + +void Hmac_Sha384Raw(const char* key, const char* message, void* out) { + int _t647; + int _t649; + unsigned int _t646; + _t646 = String_Len(key); + _t647 = (int)_t646; + unsigned int _t648; + _t648 = String_Len(message); + _t649 = (int)_t648; + bux_hmac_sha384(key, _t647, message, _t649, out); +} + +const char* Hmac_Sha384Base64(const char* key, const char* message) { + int _t651; + int _t653; + const char* _t655; + int kl; + unsigned int _t650; + _t650 = String_Len(key); + _t651 = (int)_t650; + kl = _t651; + int ml; + unsigned int _t652; + _t652 = String_Len(message); + _t653 = (int)_t652; + ml = _t653; + void* buf; + void* _t654; + _t654 = Alloc(48); + buf = _t654; + bux_hmac_sha384(key, kl, message, ml, buf); + const char* result; + _t655 = (const char*)buf; + const char* _t656; + _t656 = bux_base64_encode(_t655, 48); + result = _t656; + Free(buf); + return result; +} + +const char* Hmac_Sha512(const char* key, const char* message) { + int _t658; + int _t660; + int kl; + unsigned int _t657; + _t657 = String_Len(key); + _t658 = (int)_t657; + kl = _t658; + int ml; + unsigned int _t659; + _t659 = String_Len(message); + _t660 = (int)_t659; + ml = _t660; + void* buf; + void* _t661; + _t661 = Alloc(64); + buf = _t661; + bux_hmac_sha512(key, kl, message, ml, buf); + const char* result; + const char* _t662; + _t662 = bux_bytes_to_hex(buf, 64); + result = _t662; + Free(buf); + return result; +} + +void Hmac_Sha512Raw(const char* key, const char* message, void* out) { + int _t664; + int _t666; + unsigned int _t663; + _t663 = String_Len(key); + _t664 = (int)_t663; + unsigned int _t665; + _t665 = String_Len(message); + _t666 = (int)_t665; + bux_hmac_sha512(key, _t664, message, _t666, out); +} + +const char* Hmac_Sha512Base64(const char* key, const char* message) { + int _t668; + int _t670; + const char* _t672; + int kl; + unsigned int _t667; + _t667 = String_Len(key); + _t668 = (int)_t667; + kl = _t668; + int ml; + unsigned int _t669; + _t669 = String_Len(message); + _t670 = (int)_t669; + ml = _t670; + void* buf; + void* _t671; + _t671 = Alloc(64); + buf = _t671; + bux_hmac_sha512(key, kl, message, ml, buf); + const char* result; + _t672 = (const char*)buf; + const char* _t673; + _t673 = bux_base64_encode(_t672, 64); + result = _t673; + Free(buf); + return result; +} + +const char* Random_Bytes(int n) { + int _t674; + unsigned int _t675; + int _t678; + const char* _t679; + _t674 = (n <= 0); + if (!_t674) goto endif237; + { + return ""; + } + endif237:; + void* buf; + _t675 = (unsigned int)n; + void* _t676; + _t676 = Alloc(_t675); + buf = _t676; + int _t677; + _t677 = bux_random_bytes(buf, n); + _t678 = (_t677 != 1); + if (!_t678) goto endif239; + { + Free(buf); + return ""; + } + endif239:; + _t679 = (const char*)buf; + return _t679; +} + +const char* Random_Hex(int n) { + int _t680; + unsigned int _t681; + int _t684; + _t680 = (n <= 0); + if (!_t680) goto endif241; + { + return ""; + } + endif241:; + void* buf; + _t681 = (unsigned int)n; + void* _t682; + _t682 = Alloc(_t681); + buf = _t682; + int _t683; + _t683 = bux_random_bytes(buf, n); + _t684 = (_t683 != 1); + if (!_t684) goto endif243; + { + Free(buf); + return ""; + } + endif243:; + const char* result; + const char* _t685; + _t685 = bux_bytes_to_hex(buf, n); + result = _t685; + Free(buf); + return result; +} + +const char* Random_Base64(int n) { + int _t686; + unsigned int _t687; + int _t690; + const char* _t691; + _t686 = (n <= 0); + if (!_t686) goto endif245; + { + return ""; + } + endif245:; + void* buf; + _t687 = (unsigned int)n; + void* _t688; + _t688 = Alloc(_t687); + buf = _t688; + int _t689; + _t689 = bux_random_bytes(buf, n); + _t690 = (_t689 != 1); + if (!_t690) goto endif247; + { + Free(buf); + return ""; + } + endif247:; + const char* result; + _t691 = (const char*)buf; + const char* _t692; + _t692 = bux_base64_encode(_t691, n); + result = _t692; + Free(buf); + return result; +} + +unsigned int Random_Uint32(void) { + int _t695; + unsigned int* _t696; + unsigned int _t697; + void* buf; + void* _t693; + _t693 = Alloc(4); + buf = _t693; + int _t694; + _t694 = bux_random_bytes(buf, 4); + _t695 = (_t694 != 1); + if (!_t695) goto endif249; + { + Free(buf); + return 0; + } + endif249:; + unsigned int* ptr; + _t696 = (unsigned int*)buf; + ptr = _t696; + unsigned int val; + _t697 = *ptr; + val = _t697; + Free(buf); + return val; +} + +const char* Aes_GenerateKey(void) { + unsigned int _t698; + int _t701; + const char* _t702; + void* buf; + _t698 = (unsigned int)AES_KEY_SIZE; + void* _t699; + _t699 = Alloc(_t698); + buf = _t699; + int _t700; + _t700 = bux_random_bytes(buf, AES_KEY_SIZE); + _t701 = (_t700 != 1); + if (!_t701) goto endif251; + { + Free(buf); + return ""; + } + endif251:; + _t702 = (const char*)buf; + return _t702; +} + +const char* Aes_GenerateIV(void) { + unsigned int _t703; + int _t706; + const char* _t707; + void* buf; + _t703 = (unsigned int)AES_IV_SIZE; + void* _t704; + _t704 = Alloc(_t703); + buf = _t704; + int _t705; + _t705 = bux_random_bytes(buf, AES_IV_SIZE); + _t706 = (_t705 != 1); + if (!_t706) goto endif253; + { + Free(buf); + return ""; + } + endif253:; + _t707 = (const char*)buf; + return _t707; +} + +const char* Aes_CbcEncrypt(const char* plain, const char* key, const char* iv) { + int _t709; + void* _t710; + int outlen; + outlen = 0; + unsigned int _t708; + _t708 = String_Len(plain); + _t709 = (int)_t708; + _t710 = &outlen; + const char* _t711; + _t711 = bux_aes_256_cbc_encrypt(plain, _t709, key, iv, _t710); + return _t711; +} + +const char* Aes_CbcDecrypt(const char* cipher, const char* key, const char* iv) { + int _t713; + void* _t714; + int outlen; + outlen = 0; + unsigned int _t712; + _t712 = String_Len(cipher); + _t713 = (int)_t712; + _t714 = &outlen; + const char* _t715; + _t715 = bux_aes_256_cbc_decrypt(cipher, _t713, key, iv, _t714); + return _t715; +} + +const char* Aes_GcmEncrypt(const char* plain, const char* key, const char* iv, void* tag) { + int _t717; + void* _t718; + int outlen; + outlen = 0; + unsigned int _t716; + _t716 = String_Len(plain); + _t717 = (int)_t716; + _t718 = &outlen; + const char* _t719; + _t719 = bux_aes_256_gcm_encrypt(plain, _t717, key, iv, tag, _t718); + return _t719; +} + +const char* Aes_GcmDecrypt(const char* cipher, const char* key, const char* iv, const char* tag) { + int _t721; + void* _t722; + int outlen; + outlen = 0; + unsigned int _t720; + _t720 = String_Len(cipher); + _t721 = (int)_t720; + _t722 = &outlen; + const char* _t723; + _t723 = bux_aes_256_gcm_decrypt(cipher, _t721, key, iv, tag, _t722); + return _t723; +} + +const char* Jwt_MakeHeader(JwtAlg alg) { + int _t724; + int _t725; + int _t726; + int _t727; + int _t728; + int _t729; + int _t730; + int _t731; + int _t732; + _t724 = (alg == JwtAlg_HS256); + if (!_t724) goto endif255; + { + return "{\"alg\":\"HS256\",\"typ\":\"JWT\"}"; + } + endif255:; + _t725 = (alg == JwtAlg_HS384); + if (!_t725) goto endif257; + { + return "{\"alg\":\"HS384\",\"typ\":\"JWT\"}"; + } + endif257:; + _t726 = (alg == JwtAlg_HS512); + if (!_t726) goto endif259; + { + return "{\"alg\":\"HS512\",\"typ\":\"JWT\"}"; + } + endif259:; + _t727 = (alg == JwtAlg_RS256); + if (!_t727) goto endif261; + { + return "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; + } + endif261:; + _t728 = (alg == JwtAlg_RS384); + if (!_t728) goto endif263; + { + return "{\"alg\":\"RS384\",\"typ\":\"JWT\"}"; + } + endif263:; + _t729 = (alg == JwtAlg_RS512); + if (!_t729) goto endif265; + { + return "{\"alg\":\"RS512\",\"typ\":\"JWT\"}"; + } + endif265:; + _t730 = (alg == JwtAlg_ES256); + if (!_t730) goto endif267; + { + return "{\"alg\":\"ES256\",\"typ\":\"JWT\"}"; + } + endif267:; + _t731 = (alg == JwtAlg_ES384); + if (!_t731) goto endif269; + { + return "{\"alg\":\"ES384\",\"typ\":\"JWT\"}"; + } + endif269:; + _t732 = (alg == JwtAlg_EdDSA); + if (!_t732) goto endif271; + { + return "{\"alg\":\"EdDSA\",\"typ\":\"JWT\"}"; + } + endif271:; + return "{\"alg\":\"none\",\"typ\":\"JWT\"}"; +} + +const char* Jwt_Sign(JwtAlg alg, const char* signingInput, const char* key) { + int _t733; + const char* _t735; + int _t737; + const char* _t739; + int _t741; + const char* _t743; + int _t745; + int _t748; + int _t750; + int _t753; + int _t755; + int _t758; + int _t760; + int _t763; + int _t765; + int _t768; + int _t770; + _t733 = (alg == JwtAlg_HS256); + if (!_t733) goto endif273; + { + void* buf; + void* _t734; + _t734 = Alloc(32); + buf = _t734; + Hmac_Sha256Raw(key, signingInput, buf); + const char* result; + _t735 = (const char*)buf; + const char* _t736; + _t736 = bux_base64_encode(_t735, 32); + result = _t736; + Free(buf); + return result; + } + endif273:; + _t737 = (alg == JwtAlg_HS384); + if (!_t737) goto endif275; + { + void* buf; + void* _t738; + _t738 = Alloc(48); + buf = _t738; + Hmac_Sha384Raw(key, signingInput, buf); + const char* result; + _t739 = (const char*)buf; + const char* _t740; + _t740 = bux_base64_encode(_t739, 48); + result = _t740; + Free(buf); + return result; + } + endif275:; + _t741 = (alg == JwtAlg_HS512); + if (!_t741) goto endif277; + { + void* buf; + void* _t742; + _t742 = Alloc(64); + buf = _t742; + Hmac_Sha512Raw(key, signingInput, buf); + const char* result; + _t743 = (const char*)buf; + const char* _t744; + _t744 = bux_base64_encode(_t743, 64); + result = _t744; + Free(buf); + return result; + } + endif277:; + _t745 = (alg == JwtAlg_RS256); + if (!_t745) goto endif279; + { + const char* raw; + const char* _t746; + _t746 = Rsa_SignSha256(key, signingInput); + raw = _t746; + unsigned int _t747; + _t747 = String_Len(raw); + _t748 = (int)_t747; + const char* _t749; + _t749 = bux_base64_encode(raw, _t748); + return _t749; + } + endif279:; + _t750 = (alg == JwtAlg_RS384); + if (!_t750) goto endif281; + { + const char* raw; + const char* _t751; + _t751 = Rsa_SignSha384(key, signingInput); + raw = _t751; + unsigned int _t752; + _t752 = String_Len(raw); + _t753 = (int)_t752; + const char* _t754; + _t754 = bux_base64_encode(raw, _t753); + return _t754; + } + endif281:; + _t755 = (alg == JwtAlg_RS512); + if (!_t755) goto endif283; + { + const char* raw; + const char* _t756; + _t756 = Rsa_SignSha512(key, signingInput); + raw = _t756; + unsigned int _t757; + _t757 = String_Len(raw); + _t758 = (int)_t757; + const char* _t759; + _t759 = bux_base64_encode(raw, _t758); + return _t759; + } + endif283:; + _t760 = (alg == JwtAlg_ES256); + if (!_t760) goto endif285; + { + const char* raw; + const char* _t761; + _t761 = Ecdsa_SignP256(key, signingInput); + raw = _t761; + unsigned int _t762; + _t762 = String_Len(raw); + _t763 = (int)_t762; + const char* _t764; + _t764 = bux_base64_encode(raw, _t763); + return _t764; + } + endif285:; + _t765 = (alg == JwtAlg_ES384); + if (!_t765) goto endif287; + { + const char* raw; + const char* _t766; + _t766 = Ecdsa_SignP384(key, signingInput); + raw = _t766; + unsigned int _t767; + _t767 = String_Len(raw); + _t768 = (int)_t767; + const char* _t769; + _t769 = bux_base64_encode(raw, _t768); + return _t769; + } + endif287:; + _t770 = (alg == JwtAlg_EdDSA); + if (!_t770) goto endif289; + { + const char* _t771; + _t771 = Ed25519_Sign(key, signingInput); + return _t771; + } + endif289:; + return ""; +} + +bool Jwt_Verify(JwtAlg alg, const char* signingInput, const char* signatureB64, const char* key) { + int _t772; + const char* _t774; + int _t777; + const char* _t779; + int _t782; + const char* _t784; + int _t787; + int _t789; + int _t791; + int _t793; + int _t795; + int _t797; + _t772 = (alg == JwtAlg_HS256); + if (!_t772) goto endif291; + { + void* expectBuf; + void* _t773; + _t773 = Alloc(32); + expectBuf = _t773; + Hmac_Sha256Raw(key, signingInput, expectBuf); + const char* expectB64; + _t774 = (const char*)expectBuf; + const char* _t775; + _t775 = bux_base64_encode(_t774, 32); + expectB64 = _t775; + Free(expectBuf); + bool _t776; + _t776 = String_Eq(expectB64, signatureB64); + return _t776; + } + endif291:; + _t777 = (alg == JwtAlg_HS384); + if (!_t777) goto endif293; + { + void* expectBuf; + void* _t778; + _t778 = Alloc(48); + expectBuf = _t778; + Hmac_Sha384Raw(key, signingInput, expectBuf); + const char* expectB64; + _t779 = (const char*)expectBuf; + const char* _t780; + _t780 = bux_base64_encode(_t779, 48); + expectB64 = _t780; + Free(expectBuf); + bool _t781; + _t781 = String_Eq(expectB64, signatureB64); + return _t781; + } + endif293:; + _t782 = (alg == JwtAlg_HS512); + if (!_t782) goto endif295; + { + void* expectBuf; + void* _t783; + _t783 = Alloc(64); + expectBuf = _t783; + Hmac_Sha512Raw(key, signingInput, expectBuf); + const char* expectB64; + _t784 = (const char*)expectBuf; + const char* _t785; + _t785 = bux_base64_encode(_t784, 64); + expectB64 = _t785; + Free(expectBuf); + bool _t786; + _t786 = String_Eq(expectB64, signatureB64); + return _t786; + } + endif295:; + _t787 = (alg == JwtAlg_RS256); + if (!_t787) goto endif297; + { + bool _t788; + _t788 = Rsa_VerifySha256(key, signingInput, signatureB64); + return _t788; + } + endif297:; + _t789 = (alg == JwtAlg_RS384); + if (!_t789) goto endif299; + { + bool _t790; + _t790 = Rsa_VerifySha384(key, signingInput, signatureB64); + return _t790; + } + endif299:; + _t791 = (alg == JwtAlg_RS512); + if (!_t791) goto endif301; + { + bool _t792; + _t792 = Rsa_VerifySha512(key, signingInput, signatureB64); + return _t792; + } + endif301:; + _t793 = (alg == JwtAlg_ES256); + if (!_t793) goto endif303; + { + bool _t794; + _t794 = Ecdsa_VerifyP256(key, signingInput, signatureB64); + return _t794; + } + endif303:; + _t795 = (alg == JwtAlg_ES384); + if (!_t795) goto endif305; + { + bool _t796; + _t796 = Ecdsa_VerifyP384(key, signingInput, signatureB64); + return _t796; + } + endif305:; + _t797 = (alg == JwtAlg_EdDSA); + if (!_t797) goto endif307; + { + bool _t798; + _t798 = Ed25519_Verify(key, signatureB64, signingInput); + return _t798; + } + endif307:; + return 0; +} + +const char* Jwt_Encode(const char* headerJson, const char* payloadJson, JwtAlg alg, const char* key) { + const char* headerB64; + const char* _t799; + _t799 = Base64URL_Encode(headerJson); + headerB64 = _t799; + const char* payloadB64; + const char* _t800; + _t800 = Base64URL_Encode(payloadJson); + payloadB64 = _t800; + const char* signingInput; + const char* _t801; + _t801 = String_Concat(headerB64, "."); + signingInput = _t801; + const char* signingInputFull; + const char* _t802; + _t802 = String_Concat(signingInput, payloadB64); + signingInputFull = _t802; + const char* sigB64; + const char* _t803; + _t803 = Jwt_Sign(alg, signingInputFull, key); + sigB64 = _t803; + const char* part1; + const char* _t804; + _t804 = String_Concat(signingInputFull, "."); + part1 = _t804; + const char* _t805; + _t805 = String_Concat(part1, sigB64); + return _t805; +} + +bool Jwt_Decode(const char* token, JwtAlg alg, const char* key, const char** headerOut, const char** payloadOut) { + int _t807; + int _t814; + unsigned int partCount; + unsigned int _t806; + _t806 = bux_str_split_count(token, "."); + partCount = _t806; + _t807 = (partCount != 3); + if (!_t807) goto endif309; + { + return 0; + } + endif309:; + const char* headerB64; + const char* _t808; + _t808 = bux_str_split_part(token, ".", 0); + headerB64 = _t808; + const char* payloadB64; + const char* _t809; + _t809 = bux_str_split_part(token, ".", 1); + payloadB64 = _t809; + const char* sigB64; + const char* _t810; + _t810 = bux_str_split_part(token, ".", 2); + sigB64 = _t810; + const char* input; + const char* _t811; + _t811 = String_Concat(headerB64, "."); + input = _t811; + const char* signingInput; + const char* _t812; + _t812 = String_Concat(input, payloadB64); + signingInput = _t812; + bool _t813; + _t813 = Jwt_Verify(alg, signingInput, sigB64, key); + _t814 = !_t813; + if (!_t814) goto endif311; + { + return 0; + } + endif311:; + const char* _t815; + _t815 = Base64URL_Decode(headerB64); + headerOut[0] = _t815; + const char* _t816; + _t816 = Base64URL_Decode(payloadB64); + payloadOut[0] = _t816; + return 1; +} + +const char* Jwt_EncodeHS256(const char* payloadJson, const char* secret) { + const char* header; + const char* _t817; + _t817 = Jwt_MakeHeader(JwtAlg_HS256); + header = _t817; + const char* _t818; + _t818 = Jwt_Encode(header, payloadJson, JwtAlg_HS256, secret); + return _t818; +} + +const char* Jwt_EncodeHS384(const char* payloadJson, const char* secret) { + const char* header; + const char* _t819; + _t819 = Jwt_MakeHeader(JwtAlg_HS384); + header = _t819; + const char* _t820; + _t820 = Jwt_Encode(header, payloadJson, JwtAlg_HS384, secret); + return _t820; +} + +const char* Jwt_EncodeHS512(const char* payloadJson, const char* secret) { + const char* header; + const char* _t821; + _t821 = Jwt_MakeHeader(JwtAlg_HS512); + header = _t821; + const char* _t822; + _t822 = Jwt_Encode(header, payloadJson, JwtAlg_HS512, secret); + return _t822; +} + +const char* Jwt_EncodeRS256(const char* payloadJson, const char* pemPrivateKey) { + const char* header; + const char* _t823; + _t823 = Jwt_MakeHeader(JwtAlg_RS256); + header = _t823; + const char* _t824; + _t824 = Jwt_Encode(header, payloadJson, JwtAlg_RS256, pemPrivateKey); + return _t824; +} + +const char* Jwt_EncodeES256(const char* payloadJson, const char* pemPrivateKey) { + const char* header; + const char* _t825; + _t825 = Jwt_MakeHeader(JwtAlg_ES256); + header = _t825; + const char* _t826; + _t826 = Jwt_Encode(header, payloadJson, JwtAlg_ES256, pemPrivateKey); + return _t826; +} + +const char* Jwt_EncodeEdDSA(const char* payloadJson, const char* rawPrivKey) { + const char* header; + const char* _t827; + _t827 = Jwt_MakeHeader(JwtAlg_EdDSA); + header = _t827; + const char* _t828; + _t828 = Jwt_Encode(header, payloadJson, JwtAlg_EdDSA, rawPrivKey); + return _t828; +} + +const char* Ecdsa_SignP256(const char* pemPrivateKey, const char* data) { + int _t830; + int _t832; + void* _t833; + int siglen; + siglen = 0; + unsigned int _t829; + _t829 = String_Len(pemPrivateKey); + _t830 = (int)_t829; + unsigned int _t831; + _t831 = String_Len(data); + _t832 = (int)_t831; + _t833 = &siglen; + const char* _t834; + _t834 = bux_ecdsa_sign_p256(pemPrivateKey, _t830, data, _t832, _t833); + return _t834; +} + +const char* Ecdsa_SignP256Base64(const char* pemPrivateKey, const char* data) { + int _t837; + const char* raw; + const char* _t835; + _t835 = Ecdsa_SignP256(pemPrivateKey, data); + raw = _t835; + unsigned int _t836; + _t836 = String_Len(raw); + _t837 = (int)_t836; + const char* _t838; + _t838 = bux_base64_encode(raw, _t837); + return _t838; +} + +bool Ecdsa_VerifyP256(const char* pemPublicKey, const char* data, const char* signature) { + int _t840; + int _t842; + int _t844; + int _t846; + int r; + unsigned int _t839; + _t839 = String_Len(pemPublicKey); + _t840 = (int)_t839; + unsigned int _t841; + _t841 = String_Len(data); + _t842 = (int)_t841; + unsigned int _t843; + _t843 = String_Len(signature); + _t844 = (int)_t843; + int _t845; + _t845 = bux_ecdsa_verify_p256(pemPublicKey, _t840, data, _t842, signature, _t844); + r = _t845; + _t846 = (r == 1); + return _t846; +} + +bool Ecdsa_VerifyP256Base64(const char* pemPublicKey, const char* data, const char* signatureB64) { + int _t848; + void* _t849; + int outlen; + outlen = 0; + const char* sig; + unsigned int _t847; + _t847 = String_Len(signatureB64); + _t848 = (int)_t847; + _t849 = &outlen; + const char* _t850; + _t850 = bux_base64_decode(signatureB64, _t848, _t849); + sig = _t850; + bool _t851; + _t851 = Ecdsa_VerifyP256(pemPublicKey, data, sig); + return _t851; +} + +const char* Ecdsa_SignP384(const char* pemPrivateKey, const char* data) { + int _t853; + int _t855; + void* _t856; + int siglen; + siglen = 0; + unsigned int _t852; + _t852 = String_Len(pemPrivateKey); + _t853 = (int)_t852; + unsigned int _t854; + _t854 = String_Len(data); + _t855 = (int)_t854; + _t856 = &siglen; + const char* _t857; + _t857 = bux_ecdsa_sign_p384(pemPrivateKey, _t853, data, _t855, _t856); + return _t857; +} + +const char* Ecdsa_SignP384Base64(const char* pemPrivateKey, const char* data) { + int _t860; + const char* raw; + const char* _t858; + _t858 = Ecdsa_SignP384(pemPrivateKey, data); + raw = _t858; + unsigned int _t859; + _t859 = String_Len(raw); + _t860 = (int)_t859; + const char* _t861; + _t861 = bux_base64_encode(raw, _t860); + return _t861; +} + +bool Ecdsa_VerifyP384(const char* pemPublicKey, const char* data, const char* signature) { + int _t863; + int _t865; + int _t867; + int _t869; + int r; + unsigned int _t862; + _t862 = String_Len(pemPublicKey); + _t863 = (int)_t862; + unsigned int _t864; + _t864 = String_Len(data); + _t865 = (int)_t864; + unsigned int _t866; + _t866 = String_Len(signature); + _t867 = (int)_t866; + int _t868; + _t868 = bux_ecdsa_verify_p384(pemPublicKey, _t863, data, _t865, signature, _t867); + r = _t868; + _t869 = (r == 1); + return _t869; +} + +bool Ecdsa_VerifyP384Base64(const char* pemPublicKey, const char* data, const char* signatureB64) { + int _t871; + void* _t872; + int outlen; + outlen = 0; + const char* sig; + unsigned int _t870; + _t870 = String_Len(signatureB64); + _t871 = (int)_t870; + _t872 = &outlen; + const char* _t873; + _t873 = bux_base64_decode(signatureB64, _t871, _t872); + sig = _t873; + bool _t874; + _t874 = Ecdsa_VerifyP384(pemPublicKey, data, sig); + return _t874; +} + +bool Ed25519_Keypair(void* pubKey, void* privKey) { + int _t876; + int r; + int _t875; + _t875 = bux_ed25519_keypair(pubKey, privKey); + r = _t875; + _t876 = (r == 1); + return _t876; +} + +const char* Ed25519_KeypairBase64(void) { + unsigned int _t877; + unsigned int _t879; + int _t882; + const char* _t883; + const char* _t885; + void* pubBuf; + _t877 = (unsigned int)ED25519_PUBKEY_SIZE; + void* _t878; + _t878 = Alloc(_t877); + pubBuf = _t878; + void* priv; + _t879 = (unsigned int)ED25519_PRIVKEY_SIZE; + void* _t880; + _t880 = Alloc(_t879); + priv = _t880; + int _t881; + _t881 = bux_ed25519_keypair(pubBuf, priv); + _t882 = (_t881 != 1); + if (!_t882) goto endif313; + { + Free(pubBuf); + Free(priv); + return ""; + } + endif313:; + const char* pubB64; + _t883 = (const char*)pubBuf; + const char* _t884; + _t884 = bux_base64_encode(_t883, ED25519_PUBKEY_SIZE); + pubB64 = _t884; + const char* privB64; + _t885 = (const char*)priv; + const char* _t886; + _t886 = bux_base64_encode(_t885, ED25519_PRIVKEY_SIZE); + privB64 = _t886; + Free(pubBuf); + Free(priv); + const char* pair; + const char* _t887; + _t887 = String_Concat(pubB64, ":"); + pair = _t887; + const char* _t888; + _t888 = String_Concat(pair, privB64); + return _t888; +} + +const char* Ed25519_Sign(const char* privKey, const char* data) { + unsigned int _t889; + int _t892; + int _t894; + const char* _t895; + void* sig; + _t889 = (unsigned int)ED25519_SIG_SIZE; + void* _t890; + _t890 = Alloc(_t889); + sig = _t890; + unsigned int _t891; + _t891 = String_Len(data); + _t892 = (int)_t891; + int _t893; + _t893 = bux_ed25519_sign(privKey, data, _t892, sig); + _t894 = (_t893 != 1); + if (!_t894) goto endif315; + { + Free(sig); + return ""; + } + endif315:; + _t895 = (const char*)sig; + return _t895; +} + +const char* Ed25519_SignBase64(const char* privKey, const char* data) { + int _t898; + const char* sig; + const char* _t896; + _t896 = Ed25519_Sign(privKey, data); + sig = _t896; + unsigned int _t897; + _t897 = String_Len(sig); + _t898 = (_t897 == 0); + if (!_t898) goto endif317; + { + return ""; + } + endif317:; + const char* _t899; + _t899 = bux_base64_encode(sig, ED25519_SIG_SIZE); + return _t899; +} + +bool Ed25519_Verify(const char* pubKey, const char* signature, const char* data) { + int _t901; + int _t903; + int r; + unsigned int _t900; + _t900 = String_Len(data); + _t901 = (int)_t900; + int _t902; + _t902 = bux_ed25519_verify(pubKey, signature, data, _t901); + r = _t902; + _t903 = (r == 1); + return _t903; +} + +bool Ed25519_VerifyBase64(const char* pubKey, const char* signatureB64, const char* data) { + int _t905; + void* _t906; + int _t908; + int outlen; + outlen = 0; + const char* sig; + unsigned int _t904; + _t904 = String_Len(signatureB64); + _t905 = (int)_t904; + _t906 = &outlen; + const char* _t907; + _t907 = bux_base64_decode(signatureB64, _t905, _t906); + sig = _t907; + _t908 = (outlen != ED25519_SIG_SIZE); + if (!_t908) goto endif319; + { + return 0; + } + endif319:; + bool _t909; + _t909 = Ed25519_Verify(pubKey, sig, data); + return _t909; +} + +const char* Rsa_SignSha256(const char* pemPrivateKey, const char* data) { + int _t911; + int _t913; + void* _t914; + int siglen; + siglen = 0; + unsigned int _t910; + _t910 = String_Len(pemPrivateKey); + _t911 = (int)_t910; + unsigned int _t912; + _t912 = String_Len(data); + _t913 = (int)_t912; + _t914 = &siglen; + const char* _t915; + _t915 = bux_rsa_sign_sha256(pemPrivateKey, _t911, data, _t913, _t914); + return _t915; +} + +const char* Rsa_SignSha384(const char* pemPrivateKey, const char* data) { + int _t917; + int _t919; + void* _t920; + int siglen; + siglen = 0; + unsigned int _t916; + _t916 = String_Len(pemPrivateKey); + _t917 = (int)_t916; + unsigned int _t918; + _t918 = String_Len(data); + _t919 = (int)_t918; + _t920 = &siglen; + const char* _t921; + _t921 = bux_rsa_sign_sha384(pemPrivateKey, _t917, data, _t919, _t920); + return _t921; +} + +const char* Rsa_SignSha512(const char* pemPrivateKey, const char* data) { + int _t923; + int _t925; + void* _t926; + int siglen; + siglen = 0; + unsigned int _t922; + _t922 = String_Len(pemPrivateKey); + _t923 = (int)_t922; + unsigned int _t924; + _t924 = String_Len(data); + _t925 = (int)_t924; + _t926 = &siglen; + const char* _t927; + _t927 = bux_rsa_sign_sha512(pemPrivateKey, _t923, data, _t925, _t926); + return _t927; +} + +const char* Rsa_SignSha256Base64(const char* pemPrivateKey, const char* data) { + int _t930; + const char* raw; + const char* _t928; + _t928 = Rsa_SignSha256(pemPrivateKey, data); + raw = _t928; + unsigned int _t929; + _t929 = String_Len(raw); + _t930 = (int)_t929; + const char* _t931; + _t931 = bux_base64_encode(raw, _t930); + return _t931; +} + +const char* Rsa_SignSha384Base64(const char* pemPrivateKey, const char* data) { + int _t934; + const char* raw; + const char* _t932; + _t932 = Rsa_SignSha384(pemPrivateKey, data); + raw = _t932; + unsigned int _t933; + _t933 = String_Len(raw); + _t934 = (int)_t933; + const char* _t935; + _t935 = bux_base64_encode(raw, _t934); + return _t935; +} + +const char* Rsa_SignSha512Base64(const char* pemPrivateKey, const char* data) { + int _t938; + const char* raw; + const char* _t936; + _t936 = Rsa_SignSha512(pemPrivateKey, data); + raw = _t936; + unsigned int _t937; + _t937 = String_Len(raw); + _t938 = (int)_t937; + const char* _t939; + _t939 = bux_base64_encode(raw, _t938); + return _t939; +} + +bool Rsa_VerifySha256(const char* pemPublicKey, const char* data, const char* signature) { + int _t941; + int _t943; + int _t945; + int _t947; + int r; + unsigned int _t940; + _t940 = String_Len(pemPublicKey); + _t941 = (int)_t940; + unsigned int _t942; + _t942 = String_Len(data); + _t943 = (int)_t942; + unsigned int _t944; + _t944 = String_Len(signature); + _t945 = (int)_t944; + int _t946; + _t946 = bux_rsa_verify_sha256(pemPublicKey, _t941, data, _t943, signature, _t945); + r = _t946; + _t947 = (r == 1); + return _t947; +} + +bool Rsa_VerifySha384(const char* pemPublicKey, const char* data, const char* signature) { + int _t949; + int _t951; + int _t953; + int _t955; + int r; + unsigned int _t948; + _t948 = String_Len(pemPublicKey); + _t949 = (int)_t948; + unsigned int _t950; + _t950 = String_Len(data); + _t951 = (int)_t950; + unsigned int _t952; + _t952 = String_Len(signature); + _t953 = (int)_t952; + int _t954; + _t954 = bux_rsa_verify_sha384(pemPublicKey, _t949, data, _t951, signature, _t953); + r = _t954; + _t955 = (r == 1); + return _t955; +} + +bool Rsa_VerifySha512(const char* pemPublicKey, const char* data, const char* signature) { + int _t957; + int _t959; + int _t961; + int _t963; + int r; + unsigned int _t956; + _t956 = String_Len(pemPublicKey); + _t957 = (int)_t956; + unsigned int _t958; + _t958 = String_Len(data); + _t959 = (int)_t958; + unsigned int _t960; + _t960 = String_Len(signature); + _t961 = (int)_t960; + int _t962; + _t962 = bux_rsa_verify_sha512(pemPublicKey, _t957, data, _t959, signature, _t961); + r = _t962; + _t963 = (r == 1); + return _t963; +} + +bool Rsa_VerifySha256Base64(const char* pemPublicKey, const char* data, const char* signatureB64) { + int _t965; + void* _t966; + int outlen; + outlen = 0; + const char* sig; + unsigned int _t964; + _t964 = String_Len(signatureB64); + _t965 = (int)_t964; + _t966 = &outlen; + const char* _t967; + _t967 = bux_base64_decode(signatureB64, _t965, _t966); + sig = _t967; + bool _t968; + _t968 = Rsa_VerifySha256(pemPublicKey, data, sig); + return _t968; +} + +bool Rsa_VerifySha384Base64(const char* pemPublicKey, const char* data, const char* signatureB64) { + int _t970; + void* _t971; + int outlen; + outlen = 0; + const char* sig; + unsigned int _t969; + _t969 = String_Len(signatureB64); + _t970 = (int)_t969; + _t971 = &outlen; + const char* _t972; + _t972 = bux_base64_decode(signatureB64, _t970, _t971); + sig = _t972; + bool _t973; + _t973 = Rsa_VerifySha384(pemPublicKey, data, sig); + return _t973; +} + +bool Rsa_VerifySha512Base64(const char* pemPublicKey, const char* data, const char* signatureB64) { + int _t975; + void* _t976; + int outlen; + outlen = 0; + const char* sig; + unsigned int _t974; + _t974 = String_Len(signatureB64); + _t975 = (int)_t974; + _t976 = &outlen; + const char* _t977; + _t977 = bux_base64_decode(signatureB64, _t975, _t976); + sig = _t977; + bool _t978; + _t978 = Rsa_VerifySha512(pemPublicKey, data, sig); + return _t978; +} + +int apply(int (*f)(int), int x) { + int _t979; + _t979 = f(x); + return _t979; +} + +int Main(void) { + int (*_t980)(int); + int _t983; + int (*adder)(int); + _t980 = &__closure_10; + adder = _t980; + int r1; + int _t981; + _t981 = adder(5); + r1 = _t981; + int r2; + int _t982; + _t982 = apply(adder, 3); + r2 = _t982; + _t983 = r1 + r2; + return _t983; +} + +int __closure_10(int a) { + int _t984; + _t984 = a + 10; + return _t984; +} + +/* C entry point wrapper */ +extern int g_argc; +extern char** g_argv; +int main(int argc, char** argv) { + g_argc = argc; + g_argv = argv; + return Main(); +} diff --git a/bootstrap/ast.nim b/bootstrap/ast.nim index 4e512bb..a3f3681 100644 --- a/bootstrap/ast.nim +++ b/bootstrap/ast.nim @@ -233,6 +233,9 @@ type exprClosureParams*: seq[Param] exprClosureBody*: Block exprClosureReturnType*: TypeExpr + captureCount*: int + captureNames*: seq[string] + captureTypeKinds*: seq[int] # --------------------------------------------------------------------------- # Statements diff --git a/bootstrap/c_backend.nim b/bootstrap/c_backend.nim index 7a0d4aa..36af74a 100644 --- a/bootstrap/c_backend.nim +++ b/bootstrap/c_backend.nim @@ -272,6 +272,10 @@ proc emitExpr(be: var CBackend, node: HirNode): string = let base = be.emitExpr(node.fieldPtrBase) return &"(&({base}.{node.fieldName}))" + of hFieldAccess: + let base = be.emitExpr(node.fieldAccessBase) + return &"({base}.{node.fieldAccessName})" + of hArrowField: let base = be.emitExpr(node.arrowFieldBase) return &"(&({base}->{node.arrowFieldName}))" @@ -476,6 +480,18 @@ proc emitStmt(be: var CBackend, node: HirNode) = be.emitLine(&"{expr};") proc emitFunc*(be: var CBackend, hfunc: HirFunc) = + # Emit env struct and global instance for closures with captures + if hfunc.captureNames.len > 0 and hfunc.envStructName != "": + be.emitLine(&"struct {hfunc.envStructName} {{") + inc be.indent + for i in 0 ..< hfunc.captureNames.len: + let capName = hfunc.captureNames[i] + let capType = if i < hfunc.captureTypes.len: typeToC(be, hfunc.captureTypes[i]) else: "int" + be.emitLine(&"{capType} {capName};") + dec be.indent + be.emitLine("};") + be.emitLine(&"static struct {hfunc.envStructName} {hfunc.envInstanceName};") + be.emitLine("") let retType = typeToC(be, hfunc.retType) var params: seq[string] = @[] for p in hfunc.params: diff --git a/bootstrap/hir.nim b/bootstrap/hir.nim index 79a73fc..f55884e 100644 --- a/bootstrap/hir.nim +++ b/bootstrap/hir.nim @@ -23,6 +23,7 @@ type hLoad hStore hFieldPtr + hFieldAccess hArrowField hIndexPtr hSliceIndex @@ -98,6 +99,9 @@ type of hFieldPtr: fieldPtrBase*: HirNode fieldName*: string + of hFieldAccess: + fieldAccessBase*: HirNode + fieldAccessName*: string of hArrowField: arrowFieldBase*: HirNode arrowFieldName*: string @@ -166,6 +170,11 @@ type retType*: Type body*: HirNode isPublic*: bool + # Closure capture metadata + captureNames*: seq[string] + captureTypes*: seq[Type] + envStructName*: string + envInstanceName*: string HirEnumVariant* = object name*: string @@ -219,6 +228,9 @@ proc hirAlloca*(name: string, typ: Type, loc: SourceLocation): HirNode = proc hirStore*(ptrNode, value: HirNode, loc: SourceLocation): HirNode = HirNode(kind: hStore, storePtr: ptrNode, storeValue: value, typ: makeVoid(), loc: loc) +proc hirAssign*(target, value: HirNode, loc: SourceLocation): HirNode = + HirNode(kind: hAssign, assignOp: tkAssign, assignTarget: target, assignValue: value, typ: makeVoid(), loc: loc) + proc hirLoad*(ptrNode: HirNode, typ: Type, loc: SourceLocation): HirNode = HirNode(kind: hLoad, loadPtr: ptrNode, typ: typ, loc: loc) diff --git a/bootstrap/hir_lower.nim b/bootstrap/hir_lower.nim index 6d6feee..8525aaf 100644 --- a/bootstrap/hir_lower.nim +++ b/bootstrap/hir_lower.nim @@ -22,6 +22,9 @@ type generatedFuncInsts*: Table[string, bool] # Track generated function instantiations extraFuncs*: seq[HirFunc] # Monomorphized generic methods varTypeExprs*: Table[string, TypeExpr] # Track variable names -> type expr for generic method inference + closureDepth*: int + currentClosureExpr*: Expr + envInstanceName*: string proc freshName(ctx: var LowerCtx): string = inc ctx.varCounter @@ -648,6 +651,13 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode = of ekIdent: let name = expr.exprIdent + # Capture rewriting: if inside closure and ident is captured + if ctx.closureDepth > 0 and ctx.currentClosureExpr != nil and ctx.envInstanceName != "": + let idx = ctx.currentClosureExpr.captureNames.find(name) + if idx >= 0: + let capType = if idx < ctx.currentClosureExpr.captureTypeKinds.len: Type(kind: TypeKind(ctx.currentClosureExpr.captureTypeKinds[idx])) else: makeInt() + let base = hirVar(ctx.envInstanceName, makeNamed(""), loc) + return HirNode(kind: hFieldAccess, fieldAccessName: name, fieldAccessBase: base, typ: capType, loc: loc) if ctx.importTable.hasKey(name): return hirVar(ctx.importTable[name], typ, loc) return hirVar(name, typ, loc) @@ -1202,6 +1212,22 @@ proc lowerStmt(ctx: var LowerCtx, stmt: Stmt): HirNode = if initHir != nil: let store = hirStore(varNode, initHir, loc) stmts.add(store) + # If init is a closure with captures, emit capture assignments + if stmt.stmtLetInit != nil and stmt.stmtLetInit.kind == ekClosure and stmt.stmtLetInit.captureCount > 0: + let closureIdx = ctx.varCounter - 1 + let envInst = "__closure_env_instance_" & $closureIdx + var capStmts: seq[HirNode] = @[] + for i in 0 ..< stmt.stmtLetInit.captureCount: + let capName = stmt.stmtLetInit.captureNames[i] + let capType = if i < stmt.stmtLetInit.captureTypeKinds.len: Type(kind: TypeKind(stmt.stmtLetInit.captureTypeKinds[i])) else: makeInt() + let base = hirVar(envInst, makeNamed(""), loc) + let field = HirNode(kind: hFieldAccess, fieldAccessName: capName, fieldAccessBase: base, typ: capType, loc: loc) + let val = hirVar(capName, capType, loc) + capStmts.add(hirAssign(field, val, loc)) + # Prepend capture assignments before the let + var allStmts = capStmts + allStmts.add(stmts) + return hirBlock(allStmts, nil, makeVoid(), loc) return hirBlock(stmts, nil, makeVoid(), loc) of skReturn: @@ -1491,6 +1517,13 @@ proc lowerClosureFunc(ctx: var LowerCtx, expr: Expr): HirFunc = let name = "__closure_" & $ctx.varCounter inc ctx.varCounter var f = HirFunc(name: name, isPublic: false) + # Copy capture metadata + if expr.captureCount > 0: + f.captureNames = expr.captureNames + for tk in expr.captureTypeKinds: + f.captureTypes.add(Type(kind: TypeKind(tk))) + f.envStructName = "__closure_env_" & $(ctx.varCounter - 1) + f.envInstanceName = "__closure_env_instance_" & $(ctx.varCounter - 1) # Params for p in expr.exprClosureParams: f.params.add((name: p.name, typ: if p.ptype != nil: ctx.resolveTypeExpr(p.ptype) else: makeUnknown())) @@ -1499,9 +1532,18 @@ proc lowerClosureFunc(ctx: var LowerCtx, expr: Expr): HirFunc = f.retType = ctx.resolveTypeExpr(expr.exprClosureReturnType) else: f.retType = makeVoid() - # Body + # Body with closure rewriting + let savedDepth = ctx.closureDepth + let savedExpr = ctx.currentClosureExpr + let savedEnv = ctx.envInstanceName + ctx.closureDepth = ctx.closureDepth + 1 + ctx.currentClosureExpr = expr + ctx.envInstanceName = f.envInstanceName if expr.exprClosureBody != nil: f.body = ctx.lowerBlock(expr.exprClosureBody) + ctx.closureDepth = savedDepth + ctx.currentClosureExpr = savedExpr + ctx.envInstanceName = savedEnv ctx.extraFuncs.add(f) return f diff --git a/bootstrap/lir_c_backend.nim b/bootstrap/lir_c_backend.nim index 2141cd9..77cbbfd 100644 --- a/bootstrap/lir_c_backend.nim +++ b/bootstrap/lir_c_backend.nim @@ -626,6 +626,20 @@ proc emitModule*(be: var LirCBackend, builder: LirBuilder, module: HirModule): s be.emitLine("};") be.emitLine("") + # Emit env structs for closures with captures + for f in module.funcs: + if f.captureNames.len > 0 and f.envStructName != "": + be.emitLine(&"struct {f.envStructName} {{") + be.indent += 1 + for i in 0 ..< f.captureNames.len: + let capName = f.captureNames[i] + let capType = if i < f.captureTypes.len: typeToCStr(f.captureTypes[i]) else: "int" + be.emitLine(&"{capType} {capName};") + be.indent -= 1 + be.emitLine("};") + be.emitLine(&"static struct {f.envStructName} {f.envInstanceName};") + be.emitLine("") + # Emit all LIR functions for f in builder.funcs: be.emitFunc(f, funcRetTypes, funcPtrTypes) diff --git a/bootstrap/lir_lower.nim b/bootstrap/lir_lower.nim index 515c355..713646b 100644 --- a/bootstrap/lir_lower.nim +++ b/bootstrap/lir_lower.nim @@ -345,6 +345,14 @@ proc lowerExpr(ctx: var LowerToLirCtx, node: HirNode): LirValue = b.emitRawC(&"{t.strVal} = (void*)&({lirValToC(base)}.{node.fieldName});") return t + of hFieldAccess: + let base = lowerExpr(ctx, node.fieldAccessBase) + let cType = hirTypeToC(ctx, node) + let t = b.freshTemp() + b.emitAlloca(t.strVal, cType) + b.emitRawC(&"{t.strVal} = {lirValToC(base)}.{node.fieldAccessName};") + return t + of hArrowField: let base = lowerExpr(ctx, node.arrowFieldBase) let t = b.freshTemp() @@ -549,6 +557,9 @@ proc buildLval(ctx: var LowerToLirCtx, n: HirNode): string = of hArrowField: let baseStr = buildLval(ctx, n.arrowFieldBase) return baseStr & "->" & n.arrowFieldName + of hFieldAccess: + let baseStr = buildLval(ctx, n.fieldAccessBase) + return baseStr & "." & n.fieldAccessName of hIndexPtr: let baseStr = buildLval(ctx, n.indexPtrBase) let idx = lowerExpr(ctx, n.indexPtrIndex) @@ -669,6 +680,9 @@ proc lowerStmt(ctx: var LowerToLirCtx, node: HirNode) = of hFieldPtr: let lval = buildLval(ctx, node.assignTarget) b.emitRawC(&"{lval} = {lirValToC(value)};") + of hFieldAccess: + let lval = buildLval(ctx, node.assignTarget) + b.emitRawC(&"{lval} = {lirValToC(value)};") of hArrowField: let lval = buildLval(ctx, node.assignTarget) b.emitRawC(&"{lval} = {lirValToC(value)};") diff --git a/bootstrap/scope.nim b/bootstrap/scope.nim index 5d5b387..cce98fa 100644 --- a/bootstrap/scope.nim +++ b/bootstrap/scope.nim @@ -43,4 +43,14 @@ proc lookup*(scope: Scope, name: string): Symbol = proc lookupLocal*(scope: Scope, name: string): Symbol = if scope.table.hasKey(name): return scope.table[name] + return nil + +proc lookupUpTo*(scope: Scope, name: string, limit: Scope): Symbol = + var cur = scope + while cur != nil: + if cur.table.hasKey(name): + return cur.table[name] + if cur == limit: + break + cur = cur.parent return nil \ No newline at end of file diff --git a/bootstrap/sema.nim b/bootstrap/sema.nim index 84ad050..d041a40 100644 --- a/bootstrap/sema.nim +++ b/bootstrap/sema.nim @@ -45,6 +45,9 @@ type currentFuncIsAsync*: bool ## true inside async func movedVars*: seq[string] ## variables moved in current checked function currentRetType*: Type ## return type of the function being checked + closureDepth*: int ## nesting depth inside closures + currentClosureExpr*: Expr ## current closure being analyzed + closureScope*: Scope ## scope at which the current closure was entered # --------------------------------------------------------------------------- # Helpers @@ -816,6 +819,14 @@ proc checkExpr(sema: var Sema, expr: Expr, scope: Scope): Type = return makeUnknown() if sym.typ == nil: return makeUnknown() + # Capture tracking + if sema.closureDepth > 0 and sema.currentClosureExpr != nil and sema.closureScope != nil: + let localSym = scope.lookupUpTo(expr.exprIdent, sema.closureScope) + if localSym == nil and sym.kind == skVar: + if expr.exprIdent notin sema.currentClosureExpr.captureNames: + sema.currentClosureExpr.captureNames.add(expr.exprIdent) + sema.currentClosureExpr.captureTypeKinds.add(sym.typ.kind.int) + sema.currentClosureExpr.captureCount = sema.currentClosureExpr.captureNames.len return sym.typ of ekSelf: let sym = scope.lookup("self") @@ -1340,7 +1351,16 @@ proc checkExpr(sema: var Sema, expr: Expr, scope: Scope): Type = return makeStr() of ekClosure: let savedRetType = sema.currentRetType + let savedClosureDepth = sema.closureDepth + let savedClosureExpr = sema.currentClosureExpr + let savedClosureScope = sema.closureScope let childScope = Scope(parent: scope) + sema.closureDepth = sema.closureDepth + 1 + sema.currentClosureExpr = expr + sema.closureScope = childScope + expr.captureCount = 0 + expr.captureNames = @[] + expr.captureTypeKinds = @[] sema.currentRetType = if expr.exprClosureReturnType != nil: sema.resolveType(expr.exprClosureReturnType) else: makeUnknown() # Register params for p in expr.exprClosureParams: @@ -1351,6 +1371,9 @@ proc checkExpr(sema: var Sema, expr: Expr, scope: Scope): Type = for stmt in expr.exprClosureBody.stmts: discard sema.checkStmt(stmt, childScope) sema.currentRetType = savedRetType + sema.closureDepth = savedClosureDepth + sema.currentClosureExpr = savedClosureExpr + sema.closureScope = savedClosureScope # Build function type var params: seq[Type] = @[] for p in expr.exprClosureParams: diff --git a/src/ast.bux b/src/ast.bux index cb1c092..d9a5114 100644 --- a/src/ast.bux +++ b/src/ast.bux @@ -142,6 +142,24 @@ struct Expr { structFieldCount: int, // Closure params (for ekClosure) closureParams: *Decl, + // Captures (for ekClosure) + captureCount: int, + captureName0: String, + captureName1: String, + captureName2: String, + captureName3: String, + captureName4: String, + captureName5: String, + captureName6: String, + captureName7: String, + captureType0: int, + captureType1: int, + captureType2: int, + captureType3: int, + captureType4: int, + captureType5: int, + captureType6: int, + captureType7: int, // Call arguments (linked list for multi-arg support) callArgs: *ExprList, callArgCount: int, diff --git a/src/c_backend.bux b/src/c_backend.bux index 732b71a..d396a0c 100644 --- a/src/c_backend.bux +++ b/src/c_backend.bux @@ -445,6 +445,14 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) { return; } + // Field access on value (direct dot): obj.field + if kind == hFieldAccess { + CBE_EmitExpr(cbe, node.child1); + StringBuilder_Append(&cbe.sb, "."); + StringBuilder_Append(&cbe.sb, node.strValue); + return; + } + // Field access: obj.field — use -> if base is pointer, else . if kind == hFieldPtr { CBE_EmitExpr(cbe, node.child1); @@ -1042,6 +1050,43 @@ func CBackend_Generate(mod: *HirModule) -> String { i = i + 1; continue; } + // Emit env struct and global instance for closures with captures + if mod.funcs[i].captureCount > 0 { + let envName: String = mod.funcs[i].envStructName; + let instName: String = mod.funcs[i].envInstanceName; + if !String_Eq(envName, "") { + // Emit struct definition + StringBuilder_Append(&cbe.sb, "struct "); + StringBuilder_Append(&cbe.sb, envName); + StringBuilder_Append(&cbe.sb, " {\n"); + var ci: int = 0; + while ci < mod.funcs[i].captureCount { + var capName: String = ""; + var capType: String = "int"; + if ci == 0 { capName = mod.funcs[i].captureName0; capType = CBackend_TypeToC(mod.funcs[i].captureType0); } + else if ci == 1 { capName = mod.funcs[i].captureName1; capType = CBackend_TypeToC(mod.funcs[i].captureType1); } + else if ci == 2 { capName = mod.funcs[i].captureName2; capType = CBackend_TypeToC(mod.funcs[i].captureType2); } + else if ci == 3 { capName = mod.funcs[i].captureName3; capType = CBackend_TypeToC(mod.funcs[i].captureType3); } + else if ci == 4 { capName = mod.funcs[i].captureName4; capType = CBackend_TypeToC(mod.funcs[i].captureType4); } + else if ci == 5 { capName = mod.funcs[i].captureName5; capType = CBackend_TypeToC(mod.funcs[i].captureType5); } + else if ci == 6 { capName = mod.funcs[i].captureName6; capType = CBackend_TypeToC(mod.funcs[i].captureType6); } + else if ci == 7 { capName = mod.funcs[i].captureName7; capType = CBackend_TypeToC(mod.funcs[i].captureType7); } + StringBuilder_Append(&cbe.sb, " "); + StringBuilder_Append(&cbe.sb, capType); + StringBuilder_Append(&cbe.sb, " "); + StringBuilder_Append(&cbe.sb, capName); + StringBuilder_Append(&cbe.sb, ";\n"); + ci = ci + 1; + } + StringBuilder_Append(&cbe.sb, "};\n"); + // Emit global instance + StringBuilder_Append(&cbe.sb, "static struct "); + StringBuilder_Append(&cbe.sb, envName); + StringBuilder_Append(&cbe.sb, " "); + StringBuilder_Append(&cbe.sb, instName); + StringBuilder_Append(&cbe.sb, ";\n\n"); + } + } CBE_EmitFuncDecl(cbe, &mod.funcs[i]); StringBuilder_Append(&cbe.sb, " {\n"); // Body diff --git a/src/hir.bux b/src/hir.bux index 9f9e3b9..75307b7 100644 --- a/src/hir.bux +++ b/src/hir.bux @@ -18,8 +18,9 @@ const hAlloca: int = 12; const hLoad: int = 13; const hStore: int = 14; const hFieldPtr: int = 15; -const hArrowField: int = 16; -const hIndexPtr: int = 17; +const hFieldAccess: int = 16; +const hArrowField: int = 17; +const hIndexPtr: int = 18; const hCall: int = 18; const hCallIndirect: int = 19; const hCast: int = 20; @@ -93,6 +94,26 @@ struct HirFunc { retTypeName: String; body: *HirNode; isPublic: bool; + // Closure capture metadata + captureCount: int; + captureName0: String; + captureName1: String; + captureName2: String; + captureName3: String; + captureName4: String; + captureName5: String; + captureName6: String; + captureName7: String; + captureType0: int; + captureType1: int; + captureType2: int; + captureType3: int; + captureType4: int; + captureType5: int; + captureType6: int; + captureType7: int; + envStructName: String; + envInstanceName: String; } // --------------------------------------------------------------------------- diff --git a/src/hir_lower.bux b/src/hir_lower.bux index 2c25ece..71b9ab1 100644 --- a/src/hir_lower.bux +++ b/src/hir_lower.bux @@ -15,6 +15,10 @@ struct LowerCtx { externCount: int, varCounter: int, tryCounter: int, + closureDepth: int, + currentClosureExpr: *Expr, + envInstanceName: String, + hm: *HirModule, } // --------------------------------------------------------------------------- @@ -50,6 +54,29 @@ func Lcx_ResolveTypeKindFromName(name: String) -> int { return tyNamed; } +func Lcx_TypeKindToName(kind: int) -> String { + if kind == tyVoid { return "void"; } + if kind == tyBool || kind == tyBool8 || kind == tyBool16 || kind == tyBool32 { return "bool"; } + if kind == tyChar8 { return "char"; } + if kind == tyChar16 { return "uint16"; } + if kind == tyChar32 { return "uint32"; } + if kind == tyStr { return "String"; } + if kind == tyInt8 { return "int8"; } + if kind == tyInt16 { return "int16"; } + if kind == tyInt32 { return "int32"; } + if kind == tyInt64 { return "int64"; } + if kind == tyInt { return "int"; } + if kind == tyUInt8 { return "uint8"; } + if kind == tyUInt16 { return "uint16"; } + if kind == tyUInt32 { return "uint32"; } + if kind == tyUInt64 { return "uint64"; } + if kind == tyUInt { return "uint"; } + if kind == tyFloat32 { return "float32"; } + if kind == tyFloat64 { return "float64"; } + if kind == tyPointer { return "void*"; } + return "int"; +} + func Lcx_ResolveTypeKind(te: *TypeExpr) -> int { if te == null as *TypeExpr { return tyUnknown; } @@ -122,6 +149,40 @@ func Lcx_LowerExpr(ctx: *LowerCtx, expr: *Expr) -> *HirNode { // Identifier → variable reference if kind == ekIdent { + // Capture rewriting: if inside closure body and this ident is captured, + // emit field access on env instance instead of bare variable + if ctx.closureDepth > 0 && ctx.currentClosureExpr != null as *Expr && !String_Eq(ctx.envInstanceName, "") { + let capCount: int = ctx.currentClosureExpr.captureCount; + var ci: int = 0; + var isCaptured: bool = false; + var capType: int = 0; + while ci < capCount { + var capName: String = ""; + if ci == 0 { capName = ctx.currentClosureExpr.captureName0; capType = ctx.currentClosureExpr.captureType0; } + else if ci == 1 { capName = ctx.currentClosureExpr.captureName1; capType = ctx.currentClosureExpr.captureType1; } + else if ci == 2 { capName = ctx.currentClosureExpr.captureName2; capType = ctx.currentClosureExpr.captureType2; } + else if ci == 3 { capName = ctx.currentClosureExpr.captureName3; capType = ctx.currentClosureExpr.captureType3; } + else if ci == 4 { capName = ctx.currentClosureExpr.captureName4; capType = ctx.currentClosureExpr.captureType4; } + else if ci == 5 { capName = ctx.currentClosureExpr.captureName5; capType = ctx.currentClosureExpr.captureType5; } + else if ci == 6 { capName = ctx.currentClosureExpr.captureName6; capType = ctx.currentClosureExpr.captureType6; } + else if ci == 7 { capName = ctx.currentClosureExpr.captureName7; capType = ctx.currentClosureExpr.captureType7; } + if String_Eq(capName, expr.strValue) { + isCaptured = true; + } + ci = ci + 1; + } + if isCaptured { + n.kind = hFieldAccess; + n.strValue = expr.strValue; + let baseNode: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + baseNode.kind = hVar; + baseNode.strValue = ctx.envInstanceName; + n.child1 = baseNode; + n.typeKind = capType; + n.typeName = Lcx_TypeKindToName(capType); + return n; + } + } n.kind = hVar; n.strValue = expr.strValue; let sym: Symbol = Scope_Lookup(ctx.scope, expr.strValue); @@ -500,10 +561,71 @@ func Lcx_LowerStmt(ctx: *LowerCtx, stmt: *Stmt) -> *HirNode { sym.decl = null as *Decl; discard Scope_Define(ctx.scope, sym); // store the init value - n.kind = hStore; - n.child1 = alloca; - n.child2 = init; - return n; + let storeNode: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + storeNode.kind = hStore; + storeNode.child1 = alloca; + storeNode.child2 = init; + + // If init is a closure with captures, emit capture assignments before the let + if stmt.child1 != null as *Expr && stmt.child1.kind == ekClosure && stmt.child1.captureCount > 0 { + let closureIdx: int = ctx.funcCount - 1; + let envInst: String = String_Concat("__closure_env_instance_", String_FromInt(closureIdx)); + // Build a block: capture assignments + let store + let blockNode: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + blockNode.kind = hBlock; + blockNode.line = line; + blockNode.column = col; + var firstStmt: *HirNode = null as *HirNode; + var lastStmt: *HirNode = null as *HirNode; + var ci: int = 0; + while ci < stmt.child1.captureCount { + var capName: String = ""; + if ci == 0 { capName = stmt.child1.captureName0; } + else if ci == 1 { capName = stmt.child1.captureName1; } + else if ci == 2 { capName = stmt.child1.captureName2; } + else if ci == 3 { capName = stmt.child1.captureName3; } + else if ci == 4 { capName = stmt.child1.captureName4; } + else if ci == 5 { capName = stmt.child1.captureName5; } + else if ci == 6 { capName = stmt.child1.captureName6; } + else if ci == 7 { capName = stmt.child1.captureName7; } + // Build: envInst.capName = capName; + let assignNode: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + assignNode.kind = hAssign; + assignNode.line = line; + assignNode.column = col; + let fieldNode: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + fieldNode.kind = hFieldAccess; + fieldNode.strValue = capName; + let baseNode: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + baseNode.kind = hVar; + baseNode.strValue = envInst; + fieldNode.child1 = baseNode; + let valNode: *HirNode = bux_alloc(sizeof(HirNode)) as *HirNode; + valNode.kind = hVar; + valNode.strValue = capName; + assignNode.child1 = fieldNode; + assignNode.child2 = valNode; + if firstStmt == null as *HirNode { + firstStmt = assignNode; + lastStmt = assignNode; + } else { + lastStmt.child3 = assignNode; + lastStmt = assignNode; + } + ci = ci + 1; + } + // Append the let store + if firstStmt == null as *HirNode { + firstStmt = storeNode; + lastStmt = storeNode; + } else { + lastStmt.child3 = storeNode; + lastStmt = storeNode; + } + blockNode.child1 = firstStmt; + return blockNode; + } + return storeNode; } // Return @@ -830,6 +952,37 @@ func Lcx_LowerClosureFunc(ctx: *LowerCtx, expr: *Expr) -> *HirFunc { f.retTypeKind = 0; } + // Copy capture metadata from AST + f.captureCount = expr.captureCount; + f.captureName0 = expr.captureName0; + f.captureName1 = expr.captureName1; + f.captureName2 = expr.captureName2; + f.captureName3 = expr.captureName3; + f.captureName4 = expr.captureName4; + f.captureName5 = expr.captureName5; + f.captureName6 = expr.captureName6; + f.captureName7 = expr.captureName7; + f.captureType0 = expr.captureType0; + f.captureType1 = expr.captureType1; + f.captureType2 = expr.captureType2; + f.captureType3 = expr.captureType3; + f.captureType4 = expr.captureType4; + f.captureType5 = expr.captureType5; + f.captureType6 = expr.captureType6; + f.captureType7 = expr.captureType7; + + // Generate env struct and instance names if there are captures + var envStructName: String = ""; + var envInstanceName: String = ""; + if f.captureCount > 0 { + envStructName = String_Concat("__closure_env_", numStr); + envInstanceName = String_Concat("__closure_env_instance_", numStr); + f.envStructName = envStructName; + f.envInstanceName = envInstanceName; + + // Env struct is emitted directly by C backend from func capture metadata + } + // Create function scope var funcScope: Scope = Scope_NewChild(ctx.scope); var pi: int = 0; @@ -868,13 +1021,22 @@ func Lcx_LowerClosureFunc(ctx: *LowerCtx, expr: *Expr) -> *HirFunc { } let prevScope: *Scope = ctx.scope; + let prevClosureDepth: int = ctx.closureDepth; + let prevClosureExpr: *Expr = ctx.currentClosureExpr; + let prevEnvInstanceName: String = ctx.envInstanceName; ctx.scope = &funcScope; + ctx.closureDepth = ctx.closureDepth + 1; + ctx.currentClosureExpr = expr; + ctx.envInstanceName = envInstanceName; if expr.refBlock != null as *Block { f.body = Lcx_LowerBlock(ctx, expr.refBlock, -1); } else { f.body = null as *HirNode; } ctx.scope = prevScope; + ctx.closureDepth = prevClosureDepth; + ctx.currentClosureExpr = prevClosureExpr; + ctx.envInstanceName = prevEnvInstanceName; // Add to module functions ctx.funcs[ctx.funcCount] = *f; @@ -906,6 +1068,7 @@ func HirLower_LowerModule(mod: *Module, sema: *Sema) -> *HirModule { hm.enums = bux_alloc(64 as uint * sizeof(HirEnum)) as *HirEnum; hm.constCount = 0; hm.consts = bux_alloc(512 as uint * sizeof(HirConst)) as *HirConst; + ctx.hm = hm; // First pass: count structs (to allocate field arrays later) // Second pass: actually collect them diff --git a/src/scope.bux b/src/scope.bux index d9a02b1..1ba1e84 100644 --- a/src/scope.bux +++ b/src/scope.bux @@ -89,6 +89,25 @@ func Scope_LookupLocal(scope: *Scope, name: String) -> Symbol { return empty; } +func Scope_LookupUpTo(scope: *Scope, name: String, limit: *Scope) -> Symbol { + var cur: *Scope = scope; + while cur != null as *Scope { + var i: int = 0; + while i < cur.count { + if String_Eq(cur.symbols[i].name, name) { + return cur.symbols[i]; + } + i = i + 1; + } + if cur == limit { + break; + } + cur = cur.parent; + } + var empty: Symbol = Symbol { kind: 0, name: "", typeKind: 0, typeName: "", refType: null as *TypeExpr, isMutable: false, isPublic: false, decl: null as *Decl }; + return empty; +} + func Scope_Free(scope: *Scope) { bux_free(scope.symbols as *void); } diff --git a/src/sema.bux b/src/sema.bux index 6b6c312..7d3e524 100644 --- a/src/sema.bux +++ b/src/sema.bux @@ -24,6 +24,9 @@ struct Sema { movedName5: String; movedName6: String; movedName7: String; + closureDepth: int; // nesting depth inside closures + currentClosureExpr: *Expr; // current closure being analyzed (for capture tracking) + closureScope: *Scope; // scope at which the current closure was entered } struct SemaDiag { @@ -337,6 +340,42 @@ func Sema_RemoveMoved(sema: *Sema, name: String) { } } +// --------------------------------------------------------------------------- +// Capture tracking for closures +// --------------------------------------------------------------------------- + +func Sema_AddCapture(closureExpr: *Expr, name: String, typeKind: int) { + if closureExpr == null as *Expr { return; } + // Check if already captured + var i: int = 0; + while i < closureExpr.captureCount { + var capName: String = ""; + if i == 0 { capName = closureExpr.captureName0; } + else if i == 1 { capName = closureExpr.captureName1; } + else if i == 2 { capName = closureExpr.captureName2; } + else if i == 3 { capName = closureExpr.captureName3; } + else if i == 4 { capName = closureExpr.captureName4; } + else if i == 5 { capName = closureExpr.captureName5; } + else if i == 6 { capName = closureExpr.captureName6; } + else if i == 7 { capName = closureExpr.captureName7; } + if String_Eq(capName, name) { return; } + i = i + 1; + } + // Add new capture (up to 8) + if closureExpr.captureCount < 8 { + let idx: int = closureExpr.captureCount; + if idx == 0 { closureExpr.captureName0 = name; closureExpr.captureType0 = typeKind; } + else if idx == 1 { closureExpr.captureName1 = name; closureExpr.captureType1 = typeKind; } + else if idx == 2 { closureExpr.captureName2 = name; closureExpr.captureType2 = typeKind; } + else if idx == 3 { closureExpr.captureName3 = name; closureExpr.captureType3 = typeKind; } + else if idx == 4 { closureExpr.captureName4 = name; closureExpr.captureType4 = typeKind; } + else if idx == 5 { closureExpr.captureName5 = name; closureExpr.captureType5 = typeKind; } + else if idx == 6 { closureExpr.captureName6 = name; closureExpr.captureType6 = typeKind; } + else if idx == 7 { closureExpr.captureName7 = name; closureExpr.captureType7 = typeKind; } + closureExpr.captureCount = closureExpr.captureCount + 1; + } +} + // --------------------------------------------------------------------------- // Expression type checking // --------------------------------------------------------------------------- @@ -379,6 +418,16 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int { te.typeName = sym.typeName; expr.refType = te; } + // Capture tracking: if inside closure and identifier is not local but from parent scope + if sema.closureDepth > 0 && sema.currentClosureExpr != null as *Expr && sema.closureScope != null as *Scope { + let localSym: Symbol = Scope_LookupUpTo(sema.scope, expr.strValue, sema.closureScope); + if localSym.kind == 0 && !String_Eq(localSym.name, expr.strValue) { + // Not local to closure scope — check if it's a variable from outer scope + if sym.kind == skVar { + Sema_AddCapture(sema.currentClosureExpr, expr.strValue, sym.typeKind); + } + } + } return sym.typeKind; } @@ -568,9 +617,18 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int { if kind == ekClosure { let savedRetType: int = sema.currentRetType; let savedScope: *Scope = sema.scope; + let savedClosureDepth: int = sema.closureDepth; + let savedClosureExpr: *Expr = sema.currentClosureExpr; + let savedClosureScope: *Scope = sema.closureScope; let childScope: Scope = Scope_NewChild(sema.scope); sema.scope = &childScope; + // Set up closure tracking + sema.closureDepth = sema.closureDepth + 1; + sema.currentClosureExpr = expr; + sema.closureScope = &childScope; + expr.captureCount = 0; + // Set return type from annotation, or unknown for inference var closureRetType: int = tyUnknown; if expr.refType != null as *TypeExpr { @@ -621,6 +679,9 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int { // Restore sema.scope = savedScope; sema.currentRetType = savedRetType; + sema.closureDepth = savedClosureDepth; + sema.currentClosureExpr = savedClosureExpr; + sema.closureScope = savedClosureScope; // Build function type expression for later use let funcType: *TypeExpr = bux_alloc(sizeof(TypeExpr)) as *TypeExpr;