From a22f9919f0bbe6c56378e41d9942d10c915100e8 Mon Sep 17 00:00:00 2001 From: Martin Dorazil Date: Mon, 14 Sep 2020 00:09:57 +0200 Subject: [PATCH] Minor fixes --- _gendocs.sh | 30 +++--- _ideas.bl | 21 ++++ lib/bl/api/std/string.bl | 220 +++++++++++++++++++++++++++++++++++++-- src/mir.c | 77 ++++++++++---- 4 files changed, 308 insertions(+), 40 deletions(-) diff --git a/_gendocs.sh b/_gendocs.sh index ad4c9c481..d983796e0 100755 --- a/_gendocs.sh +++ b/_gendocs.sh @@ -2,15 +2,16 @@ WDIR=$(pwd) echo Running in ${WDIR} mkdir -p docs -mkdir -p docs/API +mkdir -p docs/api # build cd lib/bl/api/build echo echo Process $(pwd) bdg *.bl -mkdir -p ${WDIR}/docs/API/build -mv *.md ${WDIR}/docs/API/build +mkdir -p ${WDIR}/docs/api/build +rm ${WDIR}/docs/api/build/*.md +mv *.md ${WDIR}/docs/api/build cd ${WDIR} # STD @@ -18,8 +19,9 @@ cd lib/bl/api/std echo echo Process $(pwd) bdg *.bl -mkdir -p ${WDIR}/docs/API/std -mv *.md ${WDIR}/docs/API/std +mkdir -p ${WDIR}/docs/api/std +rm ${WDIR}/docs/api/std/*.md +mv *.md ${WDIR}/docs/api/std cd ${WDIR} # Builtin @@ -27,8 +29,9 @@ cd lib/bl/api echo echo Process $(pwd) bdg *.bl -mkdir -p ${WDIR}/docs/API/builtin -mv *.md ${WDIR}/docs/API/builtin +mkdir -p ${WDIR}/docs/api/builtin +rm ${WDIR}/docs/api/builtin/*.md +mv *.md ${WDIR}/docs/api/builtin cd ${WDIR} # OS @@ -36,11 +39,12 @@ cd lib/bl/api/os echo echo Process $(pwd) bdg docs.txt -mkdir -p ${WDIR}/docs/API/os -mv *.md ${WDIR}/docs/API/os +mkdir -p ${WDIR}/docs/api/os +rm ${WDIR}/docs/api/os/*.md +mv *.md ${WDIR}/docs/api/os cd ${WDIR} -# Examples +# examples cd examples echo echo Process $(pwd) @@ -50,14 +54,14 @@ for f in *.bl do echo "Processing $f file..." OUT_FILE="_tmp/$f.md" - #echo "# $f" >> $OUT_FILE + echo "#" ${f#*_} >> $OUT_FILE echo '```c' >> $OUT_FILE cat $f >> $OUT_FILE echo '```' >> $OUT_FILE cat $WDIR/_disqus.html >> $OUT_FILE done -mkdir -p ${WDIR}/docs/Examples -mv _tmp/*.md ${WDIR}/docs/Examples +mkdir -p ${WDIR}/docs/examples +mv _tmp/*.md ${WDIR}/docs/examples rm -r -f _tmp cd ${WDIR} diff --git a/_ideas.bl b/_ideas.bl index ad0f26649..96c198106 100644 --- a/_ideas.bl +++ b/_ideas.bl @@ -33,3 +33,24 @@ memcpy :: fn (dest: *u8, src: *u8, len: s64) void #intrinsic "memcpy"; // comtime function call #comptime foo(); + + + +// Function tags +my_command :: fn (buf: *Buffer, args: ...string) bool +#tags COMMAND +#meta "This is my cool command!" +{ + return true; +} + +main :: fn () s32 { + fns :: tagged_functions(); // []Any + loop i := 0; i < fns.len; i += 1 { + f :: fns[i]; + if f.type_info.tag & COMMAND { + print("%\n", f.type_info.meta) + } + } + return 0; +} \ No newline at end of file diff --git a/lib/bl/api/std/string.bl b/lib/bl/api/std/string.bl index 886e2a41b..8132bc762 100644 --- a/lib/bl/api/std/string.bl +++ b/lib/bl/api/std/string.bl @@ -32,7 +32,8 @@ string_empty :: {:string: 0}; /*! # string_new - Initialize new dynamic string. Created string is guaranteed to be zero terminated. + Overloaded function creating new dynamic string instance. Created string is +guaranteed to be zero terminated. !!! WARNING Every new string must be deleted by `string_delete` call. @@ -534,10 +535,80 @@ string_split_by_first :: fn (str: string, delimiter: u8, lhs: *string, rhs: *str return true; } -// @DOC +/*! +# string_insert + Overloaded function inserting one character or other string at desired position. + +## Declaration +```c +fn (str: *string, index: s32, v: u8) bool #inline +``` +## Description + Insert one character into `str` at `index` and return `true` when character was inserted. + +!!! NOTE + The input `str` can be reallocated when `index` is equal to input string `len` and more + space is needed. + +## Arguments + * `str` + Valid pointer to input string. + * `index` + Position in the string, could be equal to input string `len`. + * `v` + Character to be inserted. + +## Result + Returns `true` when character was inserted. + +--- + +## Declaration +```c +fn (str: *string, index: s32, v: string) bool +``` +## Description + Insert other string into `str` at `index` and return `true` when string was inserted. + +!!! NOTE + The input `str` can be reallocated when `index` is equal to input string `len` and + more space is needed. + +!!! NOTE + Function does nothing (return `false`) when `v` string is empty. + +## Arguments + * `str` + Valid pointer to input string. + * `index` + Position in the string, could be equal to input string `len`. + * `v` + String to be inserted. + +## Result + Returns `true` when string was inserted. +*/ string_insert :: fn { _string_insert; u8_insert; }; -// @DOC +/*! +# string_erase +## Declaration +```c +string_erase :: fn (str: *string, index: s32) bool +``` +## Description + Erase one character at `index` position and return true when character +was erased. The '`index` value is checked to fit in string bounds. + +## Arguments + * `str` + Pointer to string. + * `index` + Index position in string to be erased. + +## Result + True when index points to valid position in string. +*/ string_erase :: fn (str: *string, index: s32) bool { if str.len == 0 { return false; } if index >= str.len { return false; } @@ -550,7 +621,31 @@ string_erase :: fn (str: *string, index: s32) bool { return true; } -// @DOC +/*! +# string_split_by +## Declaration +```c +string_split_by :: fn (str: string, delimiter: u8) []string +``` +## Description + Split the `str` input string by delimiter and return new slice containing +all found sub-strings. + +!!! WARNING + String slice should be terminated by `slice_terminate` call. + +!!! NOTE + Slice elements just points into original string and should not be terminated. + +## Arguments + * `str` + String. + * `delimiter` + Delimiter character. + +## Result + String slice. +*/ string_split_by :: fn (str: string, delimiter: u8) []string { count :: string_count(str, delimiter) + 1; ret: []string; @@ -568,7 +663,24 @@ string_split_by :: fn (str: string, delimiter: u8) []string { return ret; } -// @DOC +/*! +# string_count +## Declaration +```c +string_count :: fn (str: string, c: u8) s32 +``` +## Description + Counts desired character occurrence in the input string. + +## Arguments + * `str` + Input string. + * `c` + Character. + +## Result + Count of character occurrence. +*/ string_count :: fn (str: string, c: u8) s32 { count := 0; loop i := 0; i < str.len; i += 1 { @@ -577,7 +689,19 @@ string_count :: fn (str: string, c: u8) s32 { return count; } -// @DOC +/*! +# string_to_lower +## Declaration +```c +string_to_lower :: fn (str: string) +``` +## Description + Converts input string to lower case. + +## Arguments + * `str` + Input string. +*/ string_to_lower :: fn (str: string) { c_tolower :: fn (c: s32) s32 #extern "tolower"; loop i := 0; i < str.len; i += 1 { @@ -585,7 +709,19 @@ string_to_lower :: fn (str: string) { } } -// @DOC +/*! +# string_to_upper +## Declaration +```c +string_to_upper :: fn (str: string) +``` +## Description + Converts input string to upper case. + +## Arguments + * `str` + Input string. +*/ string_to_upper :: fn (str: string) { c_toupper :: fn (c: s32) s32 #extern "toupper"; loop i := 0; i < str.len; i += 1 { @@ -630,7 +766,22 @@ string_replace_all :: fn (str: *string, c: u8, with := '\0') s32 { return replaced; } -// @DOC +/*! +# string_hash +## Declaration +```c +string_hash :: fn (str: string) u32 +``` +## Description + Calculates string `u32` hash. + +## Arguments + * `str` + Input string. + +## Result + String hash. +*/ string_hash :: fn (str: string) u32 { hash : u32 = 5381; loop i := 0; i < str.len; i += 1 { @@ -640,8 +791,60 @@ string_hash :: fn (str: string) u32 { return hash; } +/*! +# string_is_null +## Declaration +```c +string_is_null :: fn (s: string) bool #inline +``` +## Description + Helper inline function returning `true` when string is null. In such case string +`len` cound be any value. + +## Arguments + * `str` + Input string. + +## Result + True when string `ptr` is null. +*/ string_is_null :: fn (s: string) bool #inline { return s.ptr == null; } + +/*! +# string_is_empty +## Declaration +```c +string_is_empty :: fn (s: string) bool #inline +``` +## Description + Helper inline function returning `true` when string is empty. In such case string +`ptr` cound be any pointer. + +## Arguments + * `str` + Input string. + +## Result + True when string `len` is 0. +*/ string_is_empty :: fn (s: string) bool #inline { return s.len == 0; } + +/*! +# string_is_null_or_empty +## Declaration +```c +string_is_null_or_empty :: fn (s: string) bool #inline +``` +## Description + Helper inline function returning `true` when string is empty and null. + +## Arguments + * `str` + Input string. + +## Result + True when string `len` is 0 and `ptr` is null. +*/ string_is_null_or_empty :: fn (s: string) bool #inline { return s.ptr == null || s.len == 0; } // Some legacy C string libc apis. @@ -780,6 +983,7 @@ u8_insert :: fn (str: *string, index: s32, v: u8) bool #inline { } _string_insert :: fn (str: *string, index: s32, v: string) bool { + if !str { panic("Input string is null!"); } if v.len == 0 { return false; } if index > str.len { return false; } if index == str.len { // appending diff --git a/src/mir.c b/src/mir.c index 94d0a0045..cb32b4207 100644 --- a/src/mir.c +++ b/src/mir.c @@ -258,6 +258,10 @@ static ID *lookup_builtins_any(Context *cnt); static ID *lookup_builtins_test_cases(Context *cnt); static ID *lookup_builtins_code_loc(Context *cnt); +// Lookup member in composit structure type. Searching also in base types. When 'out_base_type' is +// set to base member type if entry was found in parent. +static ScopeEntry *lookup_composit_member(MirType *type, ID *rid, MirType **out_base_type); + // Provide global bool constant into the assembly. static MirInstr *add_global_bool(Context *cnt, ID *id, bool is_mutable, bool v); @@ -1280,7 +1284,7 @@ static INLINE bool is_to_any_needed(Context *cnt, MirInstr *src, MirType *dest_t void type_init_id(Context *cnt, MirType *type) { - //*********************************************************************************************/ +//*********************************************************************************************/ #define GEN_ID_STRUCT \ if (type->user_id) { \ tstring_append(tmp, type->user_id->str); \ @@ -1300,7 +1304,6 @@ void type_init_id(Context *cnt, MirType *type) \ tstring_append(tmp, "}"); \ //*********************************************************************************************/ - BL_ASSERT(type && "Invalid type pointer!"); TString *tmp = &cnt->tmp_sh; tstring_clear(tmp); @@ -1591,7 +1594,7 @@ MirFn *lookup_builtin_fn(Context *cnt, MirBuiltinIdKind kind) ID *lookup_builtins_rtti(Context *cnt) { - //*********************************************************************************************/ +//*********************************************************************************************/ #define LOOKUP_TYPE(N, K) \ if (!cnt->builtin_types->t_Type##N) { \ cnt->builtin_types->t_Type##N = lookup_builtin_type(cnt, MIR_BUILTIN_ID_TYPE_##K); \ @@ -1600,7 +1603,6 @@ ID *lookup_builtins_rtti(Context *cnt) } \ } \ //*********************************************************************************************/ - if (cnt->builtin_types->is_rtti_ready) return NULL; LOOKUP_TYPE(Kind, KIND); LOOKUP_TYPE(Info, INFO); @@ -1678,6 +1680,24 @@ ID *lookup_builtins_code_loc(Context *cnt) return NULL; } +ScopeEntry *lookup_composit_member(MirType *type, ID *rid, MirType **out_base_type) +{ + BL_ASSERT(type); + BL_ASSERT(mir_is_composit_type(type) && "Expected composit type!"); + + Scope * scope = type->data.strct.scope; + ScopeEntry *found = NULL; + while (true) { + found = scope_lookup(scope, rid, false, true, NULL); + if (found) break; + scope = get_base_type_scope(type); + type = get_base_type(type); + if (!scope) break; + } + if (out_base_type) *out_base_type = type; + return found; +} + MirInstr *add_global_bool(Context *cnt, ID *id, bool is_mutable, bool v) { Scope *scope = cnt->assembly->gscope; @@ -4535,19 +4555,9 @@ AnalyzeResult analyze_instr_member_ptr(Context *cnt, MirInstrMemberPtr *member_p ANALYZE_INSTR_RQ(member_ptr->target_ptr); } - Scope * scope = target_type->data.strct.scope; ID * rid = &ast_member_ident->data.ident.id; - ScopeEntry *found = NULL; MirType * type = target_type; - - while (true) { - found = scope_lookup(scope, rid, false, true, NULL); - if (found) break; - - scope = get_base_type_scope(type); - type = get_base_type(type); - if (!scope) break; - } + ScopeEntry *found = lookup_composit_member(target_type, rid, &type); // Check if member was found in base type's scope. if (found && found->parent_scope != target_type->data.strct.scope) { @@ -6017,7 +6027,7 @@ AnalyzeResult analyze_instr_type_ptr(Context *cnt, MirInstrTypePtr *type_ptr) AnalyzeResult analyze_instr_binop(Context *cnt, MirInstrBinop *binop) { - //*********************************************************************************************/ +//*********************************************************************************************/ #define is_valid(_type, _op) \ (((_type)->kind == MIR_TYPE_INT) || ((_type)->kind == MIR_TYPE_NULL) || \ ((_type)->kind == MIR_TYPE_REAL) || ((_type)->kind == MIR_TYPE_PTR) || \ @@ -7194,7 +7204,7 @@ static INLINE MirInstr *analyze_try_get_next(MirInstr *instr) void analyze(Context *cnt) { - //*********************************************************************************************/ +//*********************************************************************************************/ #if BL_DEBUG && VERBOSE_ANALYZE #define LOG_ANALYZE_PASSED printf("Analyze: [ " PASSED " ] %16s\n", mir_instr_name(ip)); #define LOG_ANALYZE_FAILED printf("Analyze: [ " FAILED " ] %16s\n", mir_instr_name(ip)); @@ -7305,7 +7315,36 @@ void analyze_report_unresolved(Context *cnt) TARRAY_FOREACH(MirInstr *, wq, instr) { BL_ASSERT(instr); - + switch (instr->kind) { +#if 0 // Should not happen + case MIR_INSTR_MEMBER_PTR: { + MirInstrMemberPtr *mp = (MirInstrMemberPtr *)instr; + MirType * target_type = mp->target_ptr->value.type; + if (!target_type) break; + target_type = mir_deref_type(target_type); + if (target_type->kind != MIR_TYPE_PTR) break; + target_type = mir_deref_type(target_type); + if (mir_is_composit_type(target_type)) { + if (!target_type->data.strct.scope) break; + if (lookup_composit_member(target_type, &mp->member_ident->data.ident.id, NULL)) { + continue; + } + } + break; + } +#endif + case MIR_INSTR_DECL_REF: { + MirInstrDeclRef *ref = (MirInstrDeclRef *)instr; + if (!ref->scope) break; + if (!ref->rid) break; + if (scope_lookup(ref->scope, ref->rid, true, false, NULL)) { + continue; + } + break; + } + default: + break; + } builder_msg(BUILDER_MSG_ERROR, ERR_UNKNOWN_SYMBOL, instr->node->location, @@ -9442,7 +9481,7 @@ const char *mir_instr_name(const MirInstr *instr) // public static void _type_to_str(char *buf, usize len, const MirType *type, bool prefer_name) { - //*********************************************************************************************/ +//*********************************************************************************************/ #define append_buf(buf, len, str) \ { \ const usize filled = strlen(buf); \