Overview
Comment: | add automatic instance bindings with accessors |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
351bb17bed601aa2bdfff738377d62ed |
User & Date: | lexi on 2025-02-10 01:11:13 |
Other Links: | manifest | tags |
Context
2025-02-21
| ||
22:02 | add janet API bootstrapping infra (prim, core), begin building executor (vm.c), design class model, continue working on loading, add script instances, tidy up src organization, build janet to use godot malloc/free check-in: 91e02e35d5 user: lexi tags: trunk | |
2025-02-10
| ||
01:11 | add automatic instance bindings with accessors check-in: 351bb17bed user: lexi tags: trunk | |
2025-02-09
| ||
20:46 | initial commit check-in: 1cc0d76954 user: lexi tags: trunk | |
Changes
Modified gdjn.ct from [3da39adca5] to [af1bbb3860].
1 -%toc 2 1 #top gdjn 3 2 allow use of Godot 4 with a [^civ civilized] scripting language, viz. [>janet Janet]. 4 3 5 4 janet: https://janet-lang.org 6 5 godot: https://godotengine.org 6 + 7 +%toc 7 8 8 9 @civ { 9 10 to meet the bare minimum standards necessary to qualify as [!civilized] to my mind, a language must: 10 11 * support compilation, whether to bytecode or machine code (excludes gdscript) 11 12 * parse into an AST (excludes bash, php (or used to)) 12 13 * support AST-rewriting macros (excludes everything outside the lisp family except maybe rust) 13 14 * use real syntax, not whitespace-based kludges (excludes python, gdscript inter alia)
Modified src/janet-lang.gcd from [c0eeb85e80] to [c1b1ca0dcf].
172 172 }; 173 173 impl _set_path(string path, bool takeOver) { 174 174 if (takeOver) { 175 175 _t(string).dtor(&me -> path); 176 176 me -> path = path; 177 177 } else { 178 178 _t(string).dtor(&me -> path); 179 - _t(string).copy(&me -> path, (void const*[]) {&path}); 179 + /* _t(string).copy(&me -> path, (void const*[]) {&path}); */ 180 + me -> path = gdu_string_dup(&path); 180 181 } 181 182 }; 182 183 impl _get_base_script() -> ref Script { 183 184 return nullptr; 184 185 }; 185 186 impl _has_static_method(string-name method) -> bool { 186 187 return false; 187 188 }; 188 189 impl _is_tool() -> bool { return false; }; (* FIXME *) 190 + impl _get_global_name(string-name id) -> string-name { 191 + return gdu_sym_null(); 192 + }; 193 + impl _is_abstract() -> bool { 194 + return false; (* TODO abuse for non-class scripts? *) 195 + }; 196 + impl _get_instance_base_type() -> string-name { 197 + return _gdu_intern("Object"); 198 + }; 199 + impl _is_valid() -> bool { 200 + return true; 201 + }; 202 + impl _get_documentation() -> array[dictionary] { 203 + gd_array dox; 204 + _t(array).empty(&dox, nullptr); 205 + auto empty = gdu_sym_null(); 206 + _t(array).setTyped(&dox, 207 + GDEXTENSION_VARIANT_TYPE_DICTIONARY, &empty, &empty); 208 + _t(stringName).dtor(&empty); 209 + return dox; 210 + }; 189 211 }; 190 212 191 213 class JanetScriptText extends JanetScript { 192 214 var as string: src; 193 215 new { 194 216 _t(string).empty(&me -> src, nullptr); 195 217 }; 196 218 del { 197 219 _t(string).dtor(&me -> src); 198 220 }; 199 221 200 - impl _get_instance_base_type() -> string-name { 201 - return _gdu_intern("ScriptExtension"); 202 - }; 203 222 impl _has_source_code() -> bool { return true; }; 204 223 impl _get_source_code() -> string { 205 224 auto d = gdu_string_dup(&me -> src); 206 225 return d; 207 226 }; 208 227 impl _set_source_code(string s) { 209 228 _t(string).dtor(&me -> src); 210 229 _t(string).copy(&me -> src, (void const*[]) {&s}); 211 230 }; 231 + impl _reload(bool keepState) -> int (* Error *) { 232 + (* TODO *) 233 + return gd_Error_ok; 234 + }; 235 +}; 236 + 237 +import { 238 + typedef struct gdjn_janet_image { 239 + size_t sz; 240 + uint8_t* buf; 241 + } gdjn_janet_image; 212 242 }; 213 243 214 244 class JanetScriptImage extends JanetScript { 215 245 impl _has_source_code() -> bool { return false; }; 216 - var struct gdjn_class_JanetScript_image { 217 - size_t sz; 218 - uint8_t* buf; 219 - }: image; 220 - impl _get_instance_base_type() -> string-name { 221 - return _gdu_intern("ScriptExtension"); 246 + var gdjn_janet_image: image; 247 + new { 248 + me -> image = (gdjn_janet_image) {}; 249 + }; 250 + del { 251 + if (me -> image.buf != nullptr) _free(me -> image.buf); 252 + }; 253 + impl _reload(bool keepState) -> int (* Error *) { 254 + (* TODO *) 255 + return gd_Error_ok; 222 256 }; 223 257 };
Modified src/janet-rsrc.gcd from [0f238faa9a] to [ab1704aae3].
110 110 gd_refCounted_reference(fd); 111 111 112 112 if (_gdu_objIs(res, JanetScriptText)) { 113 113 auto asText = gdu_cast(res, "JanetScriptText"); 114 114 gd_string src = gd_script_getSourceCode(asText); 115 115 gd_fileAccess_storeString(fd, src); 116 116 _t(string).dtor(&src); 117 + auto data = gdjn_class_JanetScriptText_data(res); 117 118 } else if (_gdu_objIs(res, JanetScriptImage)) { 118 119 auto asImg = gdu_cast(res, "JanetScriptImage"); 120 + auto data = gdjn_class_JanetScriptImage_data(res); 119 121 }; 120 122 121 123 gd_fileAccess_close(fd); 122 124 _t(string).dtor(&path_mine); 123 125 gd_refCounted_unreference(fd); 124 126 gd_refCounted_unreference(res); 125 127 }; 126 128 };
Modified src/util.h from [9bc49409e2] to [70ed0e36b0].
37 37 return r; 38 38 } 39 39 40 40 static inline gd_stringName 41 41 gdu_intern (const char* str) { 42 42 return gdu_intern_sz(str, 0); 43 43 } 44 + 45 +static inline gd_stringName 46 +gdu_sym_null(void) { 47 + gd_stringName n; 48 + _t(stringName).empty(&n, nullptr); 49 + return n; 50 +} 51 + 52 +static inline gd_string 53 +gdu_str_null(void) { 54 + gd_string n; 55 + _t(string).empty(&n, nullptr); 56 + return n; 57 +} 44 58 45 59 static inline gd_string 46 60 gdu_str_sz (const char* str, const size_t sz) { 47 61 gd_string r = {}; 48 62 if (sz == 0) _t(string).newWithUtf8Chars(&r, str); 49 63 else _t(string).newWithUtf8CharsAndLen(&r, str, sz); 50 64 return r;
Modified tool/c-bind-gen.janet from [777733985b] to [eeaa9e3ddf].
176 176 register-extension-class-method 177 177 register-extension-class-virtual-method 178 178 get-method-bind 179 179 get-class-tag 180 180 [construct-object 2]]} 181 181 {:id object :binds [set-instance 182 182 set-instance-binding 183 + get-instance-binding 183 184 get-class-name 184 185 cast-to 185 186 has-script-method 186 187 call-script-method 187 188 method-bind-ptrcall 188 189 destroy 189 190 ]} ................................................................................ 553 554 (with-names ln 554 555 [["className" (:tall i)] 555 556 ["methodName" (:sulk m)]] 556 557 (fn [] 557 558 (ln (string 558 559 "auto ptr = t -> gd_classdb.getMethodBind(&className, &methodName, %d);\n" 559 560 "\tt -> %s.%s_ptr = ptr;\n" 560 - "\t"`printf("* bind method %s.%s (%%p)\n",ptr);` "\n" 561 + #"\t"`printf("* bind method %s.%s (%%p)\n",ptr);` "\n" 561 562 "\tassert(ptr != nullptr);") 562 563 (method :hash) 563 564 ctr-id (:name m) 564 565 (:name i) (:name m) 565 566 )))) 566 567 (add-ctors i (i :ctors)) 567 568 (add (api :decls) "} %s;" ctr-id))
Modified tool/class-compile.janet from [21ecd655b6] to [a0ecf192d6].
3 3 # 🄯 AGPLv3 4 4 # ? compiles a godot class definition to C source 5 5 # > janet tool/class-compile.janet <class> (loader|header) 6 6 7 7 (def *src-file* (gensym)) 8 8 9 9 (def parse-doc 10 - (do 11 - (def doc-parser (peg/compile '{ 10 + (do (def doc-parser (peg/compile '{ 12 11 :hs (+ " " "\t") 13 12 :- "-" 14 13 :open-line (* (? " ") (? '(some (if-not "\n" 1))) "\n") 15 14 :single-line (* (? " ") (? '(some (* (not :hs) 1))) (any :hs) -1) 16 15 :mid-line (+ (* (any :hs) :- (? " ") 17 16 (? '(some (if-not "\n" 1))) "\n") 18 17 (* (? '(some (if-not "\n" 1))) "\n")) ................................................................................ 19 18 :close-line (+ (* (any :hs) -1) 20 19 (* (any :hs) :- (? " ") 21 20 (? '(some (if-not (* (any :hs) -1) 1))) 22 21 (any :hs) -1)) 23 22 :main (+ (* :open-line (any :mid-line) :close-line) 24 23 :single-line 25 24 '(any 1)) # admit defeat 26 - })) 25 + })) 27 26 28 27 (fn parse-doc[str] 29 28 (peg/match doc-parser str)))) 30 29 31 30 (def syntaxes 32 31 (do (def quot-syntax 33 32 '(nth 1 (unref (* (<- (+ `"` `'`) :quo) ................................................................................ 786 785 (string "\t.has_return_value = " 787 786 (if (= :void (f :ret)) "false" "true") ",") 788 787 (string "\t.call_func = " invocant ",") 789 788 (string "\t.ptrcall_func = " invocant-ptr ",") 790 789 ] []) 791 790 ;ret-info 792 791 `};` 793 - (string `printf("binding method %s\n",` 792 + (comment (string `printf("binding method %s\n",` 794 793 (string/format "%q" fn-path) 795 - `);`) 794 + `);`)) 796 795 (string `_t(classdb).` 797 796 (case kind 798 797 :method "registerExtensionClassMethod" 799 798 :impl "registerExtensionClassVirtualMethod") 800 799 `(gdjn_ctx -> gd.lib, &s_className, &info);`))) 801 800 (array/concat @[] "{" ;(with-names [:s_className (class :id)] 802 801 ;(map |(bind $ :method) (class :methods)) ................................................................................ 862 861 ;(if (= :native (c :base-mode)) 863 862 (with-names ["superName" (c :base)] 864 863 "super = _t(classdb).constructObject(&superName);") 865 864 [(string/format "super = %s_create();" 866 865 id-base)]) 867 866 "return super;")) 868 867 868 + (def icb-null "(&(GDExtensionInstanceBindingCallbacks){})") 869 869 (array/push (unit :funcs) 870 870 (:dec <func-c> self-ref-t id-ctor [] 871 871 (string "typeof("id")* me = _alloc("id", 1);") 872 872 ;(with-names ["className" (c :id)] 873 873 (string/format "auto gdobj = %s();" 874 874 id-create) 875 - `printf("constructed super object %p\n", gdobj);` 875 + #`printf("constructed super object %p\n", gdobj);` 876 876 "_t(object).setInstance(gdobj, &className, me);" 877 + # register the instance as a binding so 878 + # that other classes can access it. this 879 + # is so dumb 880 + "_t(object).setInstanceBinding(" 881 + " gdobj, gdjn_ctx -> gd.lib, me," 882 + icb-null 883 + ");" 877 884 (string id-init "(me, gdobj);")) 878 885 "return me;")) 879 886 (push-event :dtor id-dtor :void 880 887 [[:void* :_data] 881 888 [:GDExtensionClassInstancePtr :_ptr_me]] 882 889 |[(string "typeof("id")* me = _ptr_me;") 883 890 ;$ 884 891 "_free(me);"]) 885 892 (def id-virt (class-prefix (c :cursor) (c :id) "virt")) 893 + (array/push (unit :funcs) 894 + (:dec* <func-c> [:inline :static] 895 + self-ref-t (string id "_data") 896 + [[:GDExtensionObjectPtr :self]] 897 + "return _t(object).getInstanceBinding(" 898 + " self, gdjn_ctx -> gd.lib," 899 + icb-null 900 + ");")) 886 901 887 902 (array/push (unit :funcs) (:dec- <func-c> :void* id-virt 888 903 [[:void* :data] 889 904 [:GDExtensionConstStringNamePtr :method] 890 905 [:uint32_t :hash]] 891 906 `bool res = false;` 892 907 ;(catseq [[name idx] :pairs (c :vtbl-map)] [