• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Baremetal Lisp interpreter and compiler for low-resource devices


Commit MetaInfo

Revisãoace2af3ce3df84623f9fb29d568786088bea1ed0 (tree)
Hora2020-09-13 06:41:33
AutorAlaskanEmily <emily@alas...>
CommiterAlaskanEmily

Mensagem de Log

Add partial type-hint checking for args in calls

Mudança Sumário

Diff

--- a/sl_i.c
+++ b/sl_i.c
@@ -135,8 +135,53 @@ static void sl_i_defun(struct SL_I_Runtime *rt,
135135 sl_s_len_t arity;
136136 void *old;
137137 const struct SL_S_List *arg_pair, *iter;
138-
139- arity = SL_S_Length(args);
138+ const struct SL_S_Atom *atom;
139+
140+ arity = 0;
141+ iter = args;
142+ while(iter != SL_S_NIL){
143+ arg_pair = SL_S_PTR_FROM_TAG(iter->head);
144+ atom = SL_S_PTR_FROM_TAG(arg_pair->head);
145+ if(SL_I_LIKELY(SL_S_COMPARE_ATOMS(atom, &sl_x_nil)))
146+ goto type_hint_ok;
147+ /* Validate that we know what this type hint is. */
148+#define SL_I_TYPE_HINT_CHECK(X) \
149+ if(SL_S_COMPARE_ATOMS(atom, &sl_x_ ## X ## _hint)) \
150+ goto type_hint_ok;
151+ SL_X_INTEGRAL_TYPES(SL_I_TYPE_HINT_CHECK)
152+#undef SL_I_TYPE_HINT_CHECK
153+
154+#ifdef SL_S_ENABLE_POINTERS
155+# define SL_I_TYPE_PTR_HINT_CHECK(X) \
156+ if(SL_S_COMPARE_ATOMS(atom, &sl_x_ptr_ ## X ## _hint)) \
157+ goto type_hint_ok;
158+ SL_X_INTEGRAL_TYPES(SL_I_TYPE_PTR_HINT_CHECK)
159+# undef SL_I_TYPE_PTR_HINT_CHECK
160+#endif
161+ /* Not a builtin, check for a defrec. */
162+ for(i = 0; i < rt->num_recs; i++){
163+ if(SL_S_COMPARE_ATOMS(rt->recs[i].name, atom))
164+ goto type_hint_ok;
165+ }
166+
167+ /* Not OK! We don't know what this hint means. */
168+#define SL_I_HINT_ERROR "Unknown type "
169+ rt->pending_error =
170+ rt->error_free_ptr =
171+ SL_S_Malloc(sizeof(SL_I_HINT_ERROR) + atom->len);
172+ SL_S_MemCopy(((char*)(rt->pending_error)),
173+ SL_I_HINT_ERROR,
174+ sizeof(SL_I_HINT_ERROR) - 1);
175+ SL_S_MemCopy(((char*)(rt->pending_error)) + sizeof(SL_I_HINT_ERROR) - 1,
176+ atom->text,
177+ atom->len);
178+ ((char*)(rt->pending_error))[sizeof(SL_I_HINT_ERROR) + atom->len - 1] = '\0';
179+ return;
180+#undef SL_I_HINT_ERROR
181+type_hint_ok:
182+ arity++;
183+ iter = iter->tail;
184+ }
140185
141186 /* Search for an existing function of this name. */
142187 i = sl_i_find_bind(rt, name);
@@ -926,9 +971,11 @@ SL_S_FUNC(void) *SL_I_Call(struct SL_I_Runtime *rt,
926971 const struct SL_I_Bind *bind,
927972 const struct SL_S_List *args){
928973
929- sl_s_len_t i;
974+ sl_s_len_t i, e;
975+ int l;
930976 struct SL_I_Frame frame;
931977 const struct SL_S_List *code;
978+ const struct SL_S_Atom *hint;
932979 void *value;
933980
934981 if(bind->is_native){
@@ -945,7 +992,104 @@ SL_S_FUNC(void) *SL_I_Call(struct SL_I_Runtime *rt,
945992 frame.num_defs = frame.cap_defs = bind->arity;
946993 for(i = 0; i < bind->arity; i++){
947994 frame.defs[i].name = bind->args[i].name;
948- frame.defs[i].value = SL_I_Execute(rt, args->head);
995+ value = SL_I_Execute(rt, args->head);
996+ hint = bind->args[i].hint;
997+ if(!SL_S_COMPARE_ATOMS(hint, &sl_x_nil)){
998+ /* Validate the type. */
999+#define SL_I_TYPE_ERROR "Invalid argument type for func "
1000+#define SL_I_SET_TYPE_ERROR do{ \
1001+ rt->pending_error = \
1002+ rt->error_free_ptr = \
1003+ SL_S_Malloc(sizeof(SL_I_TYPE_ERROR) + bind->name->len); \
1004+ SL_S_MemCopy(((char*)(rt->pending_error)), \
1005+ SL_I_TYPE_ERROR, \
1006+ sizeof(SL_I_TYPE_ERROR) - 1); \
1007+ SL_S_MemCopy(((char*)(rt->pending_error)) + sizeof(SL_I_TYPE_ERROR) - 1, \
1008+ bind->name->text, \
1009+ bind->name->len); \
1010+ ((char*)(rt->pending_error))[ \
1011+ sizeof(SL_I_TYPE_ERROR) + bind->name->len - 1]; \
1012+ goto type_hint_done; \
1013+}while(0)
1014+
1015+#define SL_I_TEST_INTEGER do{ \
1016+ if((!SL_S_IS_ATOM(value)) || SL_X_IsInt(SL_S_PTR_FROM_TAG(value)) != 0){ \
1017+ SL_I_SET_TYPE_ERROR; \
1018+ } \
1019+ l = SL_X_ParseInt(value); \
1020+}while(0)
1021+
1022+#define SL_I_SET_UNSIGNED(SIZE) do{ \
1023+ if((l & ((1 << (SIZE))-1)) != l){ \
1024+ SL_S_DECREF(value); \
1025+ value = SL_S_IntToAtom(l & ((1 << (SIZE))-1), 10); \
1026+ } \
1027+}while(0)
1028+
1029+#define SL_I_INT_BITS (sizeof(int) << 3)
1030+#define SL_I_SET_SIGNED(SIZE) do{ \
1031+ if((l << (SL_I_INT_BITS - (SIZE))) >> (SL_I_INT_BITS - (SIZE)) != l) { \
1032+ SL_S_DECREF(value); \
1033+ value = SL_S_IntToAtom( \
1034+ (l << (SL_I_INT_BITS - (SIZE))) >> (SL_I_INT_BITS - (SIZE)), \
1035+ 10); \
1036+ } \
1037+}while(0)
1038+
1039+ if(SL_S_COMPARE_ATOMS(hint, &sl_x_atom_hint)){
1040+ if(!SL_S_IS_ATOM(value))
1041+ SL_I_SET_TYPE_ERROR;
1042+ }
1043+ else if(SL_S_COMPARE_ATOMS(hint, &sl_x_list_hint)){
1044+ if(!SL_S_IS_LIST(value))
1045+ SL_I_SET_TYPE_ERROR;
1046+ }
1047+ else if(SL_S_COMPARE_ATOMS(hint, &sl_x_u8_hint)){
1048+ SL_I_TEST_INTEGER;
1049+ SL_I_SET_UNSIGNED(8);
1050+ }
1051+ else if(SL_S_COMPARE_ATOMS(hint, &sl_x_s8_hint)){
1052+ SL_I_TEST_INTEGER;
1053+ SL_I_SET_SIGNED(8);
1054+ }
1055+ else if(SL_S_COMPARE_ATOMS(hint, &sl_x_u16_hint)){
1056+ SL_I_TEST_INTEGER;
1057+ SL_I_SET_UNSIGNED(16);
1058+ }
1059+ else if(SL_S_COMPARE_ATOMS(hint, &sl_x_s16_hint)){
1060+ SL_I_TEST_INTEGER;
1061+ SL_I_SET_SIGNED(16);
1062+ }
1063+ else if(SL_S_COMPARE_ATOMS(hint, &sl_x_u32_hint) ||
1064+ SL_S_COMPARE_ATOMS(hint, &sl_x_s32_hint) ||
1065+ SL_S_COMPARE_ATOMS(hint, &sl_x_char_hint)){
1066+
1067+ SL_I_TEST_INTEGER;
1068+ }
1069+ else if(hint->len >= 4 &&
1070+ SL_S_MemComp(hint->text, "^ptr", 4) == 0){
1071+
1072+ if(!SL_S_IS_NIL(value) || SL_S_IS_PTR(value))
1073+ SL_I_SET_TYPE_ERROR;
1074+ }
1075+ else{
1076+ /* Check for a record. */
1077+ for(e = 0; e < rt->num_recs; e++){
1078+ if(hint->len - 1 == rt->recs[e].name->len &&
1079+ SL_S_MemComp(hint->text + 1,
1080+ rt->recs[e].name->text,
1081+ hint->len - 1) == 0){
1082+ /* Done. */
1083+ if(!(SL_S_IS_NIL(value) || SL_S_IS_PTR(value)))
1084+ SL_I_SET_TYPE_ERROR;
1085+
1086+ goto type_hint_done;
1087+ }
1088+ }
1089+ }
1090+ }
1091+type_hint_done:
1092+ frame.defs[i].value = value;
9491093 if(rt->pending_error){
9501094 do{
9511095 SL_S_DECREF(frame.defs[i].value);
Binary files /dev/null and b/sli differ
--- a/tests/hint.lsp
+++ b/tests/hint.lsp
@@ -1,3 +1,5 @@
11
22 (defun foo (^char c) nil)
33
4+(foo 32)
5+
--- /dev/null
+++ b/tests/hint_bad2.lsp
@@ -0,0 +1,5 @@
1+
2+(defun foo (^char c) nil)
3+
4+(foo xyz)
5+