Baremetal Lisp interpreter and compiler for low-resource devices
Revisão | ace2af3ce3df84623f9fb29d568786088bea1ed0 (tree) |
---|---|
Hora | 2020-09-13 06:41:33 |
Autor | AlaskanEmily <emily@alas...> |
Commiter | AlaskanEmily |
Add partial type-hint checking for args in calls
@@ -135,8 +135,53 @@ static void sl_i_defun(struct SL_I_Runtime *rt, | ||
135 | 135 | sl_s_len_t arity; |
136 | 136 | void *old; |
137 | 137 | 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 | + } | |
140 | 185 | |
141 | 186 | /* Search for an existing function of this name. */ |
142 | 187 | i = sl_i_find_bind(rt, name); |
@@ -926,9 +971,11 @@ SL_S_FUNC(void) *SL_I_Call(struct SL_I_Runtime *rt, | ||
926 | 971 | const struct SL_I_Bind *bind, |
927 | 972 | const struct SL_S_List *args){ |
928 | 973 | |
929 | - sl_s_len_t i; | |
974 | + sl_s_len_t i, e; | |
975 | + int l; | |
930 | 976 | struct SL_I_Frame frame; |
931 | 977 | const struct SL_S_List *code; |
978 | + const struct SL_S_Atom *hint; | |
932 | 979 | void *value; |
933 | 980 | |
934 | 981 | if(bind->is_native){ |
@@ -945,7 +992,104 @@ SL_S_FUNC(void) *SL_I_Call(struct SL_I_Runtime *rt, | ||
945 | 992 | frame.num_defs = frame.cap_defs = bind->arity; |
946 | 993 | for(i = 0; i < bind->arity; i++){ |
947 | 994 | 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; | |
949 | 1093 | if(rt->pending_error){ |
950 | 1094 | do{ |
951 | 1095 | SL_S_DECREF(frame.defs[i].value); |
@@ -1,3 +1,5 @@ | ||
1 | 1 | |
2 | 2 | (defun foo (^char c) nil) |
3 | 3 | |
4 | +(foo 32) | |
5 | + |
@@ -0,0 +1,5 @@ | ||
1 | + | |
2 | +(defun foo (^char c) nil) | |
3 | + | |
4 | +(foo xyz) | |
5 | + |