void destroy_result(lily_value *v) { close_result(v); lily_free(v->value.generic); }
void lily_free_options(lily_options *o) { lily_free(o); }
static void free_lily_main(lily_function_val *fv) { lily_free(fv->reg_info); lily_free(fv->code); lily_free(fv); }
/* scan_seed_arg This takes a seed that defines a signature and creates the appropriate sig for it. This is able to handle complex signatures nested inside of each other. */ static lily_sig *scan_seed_arg(lily_symtab *symtab, const int *arg_ids, int *pos, int *ok) { lily_sig *ret; int arg_id = arg_ids[*pos]; int seed_pos = *pos + 1; *ok = 1; if (arg_id == -1) ret = NULL; else { lily_class *arg_class = lily_class_by_id(symtab, arg_id); if (arg_class->sig) ret = arg_class->sig; else { lily_sig *complex_sig = lily_try_sig_for_class(symtab, arg_class); lily_sig **siglist; int siglist_size; int flags = 0; if (arg_id == SYM_CLASS_TEMPLATE) { if (complex_sig) complex_sig->template_pos = arg_ids[seed_pos]; else *ok = 0; seed_pos++; siglist = NULL; siglist_size = 0; } else { if (arg_class->template_count == -1) { /* -1 means it takes a specified number of values. */ siglist_size = arg_ids[seed_pos]; seed_pos++; /* Function needs flags in case the thing is varargs. */ if (arg_id == SYM_CLASS_FUNCTION) { flags = arg_ids[seed_pos]; seed_pos++; } } else { siglist_size = arg_class->template_count; flags = 0; } siglist = lily_malloc(siglist_size * sizeof(lily_sig *)); if (siglist) { int i; for (i = 0;i < siglist_size;i++) { siglist[i] = scan_seed_arg(symtab, arg_ids, &seed_pos, ok); if (*ok == 0) break; } if (*ok == 0) { /* This isn't tied to anything, so free it. Inner args have already been ensured, so don't touch them. */ lily_free(siglist); siglist = NULL; *ok = 0; } } else *ok = 0; } if (*ok == 1 && complex_sig != NULL) { complex_sig->siglist = siglist; complex_sig->siglist_size = siglist_size; complex_sig->flags = flags; complex_sig = lily_ensure_unique_sig(symtab, complex_sig); ret = complex_sig; } else ret = NULL; } } *pos = seed_pos; return ret; }
/* lily_ensure_unique_sig This looks through the symtab's current signatures to see if any describe the same thing as the given signature. * If a match is not found, the input_sig is returned. * If a match is found, input_sig is destroyed and removed from symtab's sig chain. The matching signature is returned. Because of this, the return of this function must NEVER be ignored, unless no var is currently using input_sig. As the name suggests, this ensures that each signature describes a unique thing. It is expected that inner signatures will be ensured before outer signatures are: a list[list[list[list[integer]]]] first checking that list[integer] is unique, then list[list[integer]] is unique, and so on. Because of this, it is not necessary to do deep comparisons. Additionally, signatures can be compared by pointer, and a deep matching function is no longer necessary. */ lily_sig *lily_ensure_unique_sig(lily_symtab *symtab, lily_sig *input_sig) { lily_sig *iter_sig = symtab->root_sig; lily_sig *previous_sig = NULL; int match = 0; /* This just means that input_sig was the last signature created. */ if (iter_sig == input_sig) iter_sig = iter_sig->next; while (iter_sig) { if (iter_sig->cls == input_sig->cls) { if (iter_sig->siglist != NULL && iter_sig->siglist_size == input_sig->siglist_size && iter_sig != input_sig) { int i; match = 1; for (i = 0;i < iter_sig->siglist_size;i++) { if (iter_sig->siglist[i] != input_sig->siglist[i]) { match = 0; break; } } if (match == 1) break; } } if (iter_sig->next == input_sig) previous_sig = iter_sig; iter_sig = iter_sig->next; } finalize_sig(input_sig); if (match) { /* Remove input_sig from the symtab's sig chain. */ if (symtab->root_sig == input_sig) /* It is the root, so just advance the root. */ symtab->root_sig = symtab->root_sig->next; else { /* Make the sig before it link to the node after it. This is theoretically safe because the chain goes from recent to least recent. So this should find the input signature before it finds one that equals it (and set previous_sig to something valid). */ previous_sig->next = input_sig->next; } /* This is either NULL or something that only this sig uses. Don't free what's inside of the siglist though, since that's other signatures still in the chain. */ lily_free(input_sig->siglist); lily_free(input_sig); input_sig = iter_sig; } return input_sig; }