/* Copyright 1989 GROUPE BULL -- See license conditions in file COPYRIGHT * Copyright 1989 Massachusetts Institute of Technology */ /**************************\ * * * WOOL_OBJECT: Namespace * * BODY * * * \**************************/ #include "EXTERN.h" #include #include #include "wool.h" #include "wl_atom.h" #include "wl_list.h" #include "wl_number.h" #include "wl_string.h" #include "INTERN.h" #include "wl_name.h" #define WLNAMESPACE_INITIAL_SIZE 3 /* initial size (in longs) */ #define DELETED (WOOL_OBJECT *) -1 /* slot is vacant */ #define NONE_DELETED -1 /* no slot is vacant */ int WLNamespace_search_deleted(); /* High level function callable from wool. Makes a new namespace. */ WOOL_Namespace WLNamespace_make() { WOOL_Namespace object = (WOOL_Namespace) Malloc(sizeof(struct _WOOL_Namespace)); bzero(object, sizeof(struct _WOOL_Namespace)); object -> type = WLNamespace; zrt_put(object); object -> first_deleted = NONE_DELETED; return object; } /* adding a namespace domain to a namespace. returns int of created namespace */ WOOL_OBJECT WLNamespace_add(namespace) WOOL_Namespace namespace; { int new_index; must_be_namespace(namespace, 0); if (!namespace -> number) /* non-empty namespaces */ increase_reference(namespace); /* must never disapear */ if (namespace -> first_deleted == NONE_DELETED) { new_index = namespace -> number++; namespace -> namespaces = (WOOL_OBJECT **) Realloc(namespace -> namespaces, namespace -> number * sizeof(WOOL_OBJECT *)); } else { new_index = namespace -> first_deleted; namespace -> first_deleted = WLNamespace_search_deleted(namespace, new_index); } if (namespace -> limit) namespace -> namespaces[new_index] = (WOOL_OBJECT *) Malloc(sizeof(WOOL_OBJECT) * namespace -> limit); else namespace -> namespaces[new_index] = 0; return (WOOL_OBJECT) WLNumber_make(new_index); } /* removing a namespace. * just puts a DELETED in the entry */ WOOL_OBJECT WLNamespace_remove(namespace, number) WOOL_Namespace namespace; WOOL_Number number; { int index; WOOL_OBJECT *p; must_be_namespace(namespace, 0); must_be_number(number, 1); index = number -> number; if (index < 0 || index >= namespace -> number) return NIL; for (p = namespace -> namespaces[index]; p < (namespace -> namespaces[index]) + namespace -> limit; p++) decrease_reference(*p); Free(namespace -> namespaces[index]); namespace -> namespaces[index] = DELETED; if (namespace -> first_deleted == NONE_DELETED || namespace -> first_deleted > index) namespace -> first_deleted = index; return NIL; } /* searches for first vacant spot */ int WLNamespace_search_deleted(namespace, index) WOOL_Namespace namespace; int index; { WOOL_OBJECT **p; for (p = namespace -> namespaces + index; p < namespace -> namespaces + namespace -> number; p++) { if (*p == DELETED) return p - namespace -> namespaces; } return NONE_DELETED; } /* adding a new name entry in a namespace * returns new index */ Num WLNamespace_add_name(namespace) WOOL_Namespace namespace; { int i; WOOL_OBJECT *p; if (namespace -> size >= namespace -> limit) { /* must realloc */ if (namespace -> limit) namespace -> limit = namespace -> limit * 2 + 1; else namespace -> limit = WLNAMESPACE_INITIAL_SIZE; for (i = 0; i < namespace -> number; i++) { namespace -> namespaces[i] = (WOOL_OBJECT *) Realloc( namespace -> namespaces[i], namespace -> limit * sizeof(WOOL_OBJECT)); for (p = (namespace -> namespaces[i]) + namespace -> size; p < (namespace -> namespaces[i]) + namespace -> limit; p++) increase_reference(*p = UNDEFINED_WOOL_VALUE); } } return (Num) namespace -> size++; } /* adding a name in a namespace * (defname 'name namespace [value]) ==> sets value in each namespace state * if no value given, and atom had a previous value, sets all name values * this value */ WOOL_OBJECT WLName_add(argc, argv) int argc; WOOL_OBJECT argv[]; { WOOL_OBJECT value; switch (argc) { case 2: value = 0; break; case 3: value = argv[2]; break; default: return wool_error(BAD_NUMBER_OF_ARGS, argc); } must_be_namespace(argv[1], 1); if (argv[0] -> type == WLAtom) { if (!value && ((WOOL_Atom) argv[0]) -> c_val) value = (WOOL_OBJECT) WLQuotedExpr_make(((WOOL_Atom) argv[0]) -> c_val); decrease_reference(((WOOL_Atom) argv[0]) -> c_val); argv[0] -> type = WLName; NameNamespace(((WOOL_Name) argv[0])) = ((WOOL_Namespace) argv[1]); ((WOOL_Name) argv[0]) -> index = WLNamespace_add_name((WOOL_Namespace) argv[1]); } else if (argv[0] -> type == WLName) { if (NameNamespace(((WOOL_Name) argv[0])) != ((WOOL_Namespace) argv[1])) { WLName_release_values(argv[0]); NameNamespace(((WOOL_Name) argv[0])) = ((WOOL_Namespace) argv[1]); ((WOOL_Name) argv[0]) -> index = WLNamespace_add_name((WOOL_Namespace) argv[1]); } else { return argv[0]; } } else bad_argument(argv[0], 0, "symbol"); if (value) { /* set to arg */ WLName_set_all(argv[1], argv[0], value); } return argv[0]; } /* manage active namespace * (set-current-namespace namespace current) * with current out-of-bounds (e.g -1) returning current one */ WOOL_OBJECT WLNamespace_set_current(namespace, index) WOOL_Namespace namespace; WOOL_Number index; { must_be_namespace(namespace, 0); must_be_number(index, 1); if (index -> number >= 0 && index -> number < namespace -> number) { namespace -> current = index -> number; if (namespace -> trigger) (*(namespace -> trigger))(index -> number); return (WOOL_OBJECT) index; } else { return (WOOL_OBJECT) WLNumber_make(namespace -> current); } } /* size of states in the namespace */ WOOL_OBJECT WLNamespace_size(namespace) WOOL_Namespace namespace; { must_be_namespace(namespace, 0); return (WOOL_OBJECT) WLNumber_make(namespace -> number); } /* namespace-of: * on a name returns namespace or NIL if global */ WOOL_OBJECT WLName_namespace(name) WOOL_Name name; { if (name -> type == WLAtom) return NIL; else if (name -> type == WLName) return (WOOL_OBJECT) NameNamespace(name); else return bad_argument(name, 0, "symbol"); } /* free all c_val values */ WLName_release_values(name) WOOL_Name name; { WOOL_Namespace namespace = NameNamespace(name); int i; for (i = 0; i < namespace -> number; i++) decrease_reference((namespace -> namespaces[i])[name -> index]); } WOOL_OBJECT WLName_unbind(name) WOOL_Name name; { WOOL_Namespace namespace = NameNamespace(name); decrease_reference((namespace -> namespaces[namespace -> current]) [name -> index]); (namespace -> namespaces[namespace -> current]) [name -> index] = UNDEFINED_WOOL_VALUE; return NIL; } /* namespace methods */ WOOL_OBJECT WLNamespace_print(obj) WOOL_Namespace obj; { wool_printf("{NAMESPACE 0x%x ", obj); wool_printf("(%d spaces", obj -> number); wool_printf(" of %d names)}", obj -> size); return (WOOL_OBJECT) obj; } WOOL_OBJECT WLNamespace_free(namespace) WOOL_Namespace namespace; { free(namespace); return NULL; } /* name methods */ /* * Evaluating an name returns the pointed slot */ WOOL_OBJECT WLName_eval(name) WOOL_Name name; { WOOL_Namespace namespace = NameNamespace(name); WOOL_OBJECT value; if ((value = ((namespace -> namespaces)[namespace -> current]) [name -> index]) != UNDEFINED_WOOL_VALUE) return value; else return wool_error(UNDEFINED_VARIABLE, name -> p_name); } WOOL_OBJECT * WLName_slot(name) WOOL_Name name; { WOOL_Namespace namespace = NameNamespace(name); return &(((namespace -> namespaces)[namespace -> current])[name -> index]); } WOOL_OBJECT WLName_silent_eval(name) WOOL_Name name; { WOOL_Namespace namespace = NameNamespace(name); return ((namespace -> namespaces)[namespace -> current]) [name -> index]; } WOOL_OBJECT WLName_set(name, value) WOOL_Name name; WOOL_OBJECT value; { WOOL_OBJECT new = WOOL_send(WOOL_eval, value, (value)); WOOL_Namespace namespace = NameNamespace(name); WOOL_OBJECT *value_ptr = &(((namespace -> namespaces) [namespace -> current])[name -> index]); decrease_reference(*value_ptr); increase_reference(*value_ptr = new); return new; } WOOL_OBJECT WLName_setq(name, value) WOOL_Name name; WOOL_OBJECT value; { WOOL_Namespace namespace = NameNamespace(name); WOOL_OBJECT *value_ptr = &(((namespace -> namespaces) [namespace -> current])[name -> index]); decrease_reference(*value_ptr); increase_reference(*value_ptr = value); return value; } /* like set but on all spaces */ WLName_set_all(namespace, name, value) WOOL_Namespace namespace; WOOL_Name name; WOOL_OBJECT value; { WOOL_OBJECT *value_ptr; int i, old_current = namespace -> current; if (namespace -> save_state) (*(namespace -> save_state)) (); for (i = 0; i < namespace -> number; i++) { value_ptr = &(((namespace -> namespaces)[i])[name -> index]); decrease_reference(*value_ptr); namespace -> current = i; if (namespace -> trigger) (*(namespace -> trigger)) (i); increase_reference(*value_ptr = WOOL_send(WOOL_eval, value, (value))); } namespace -> current = old_current; if (namespace -> trigger) (*(namespace -> trigger)) (old_current); if (namespace -> restore_state) (*(namespace -> restore_state)) (); } /* * WLName_execute: * executes the object in the C_val */ WOOL_OBJECT WLName_execute(name, list) WOOL_Name name; WOOL_List list; { WOOL_Namespace namespace = NameNamespace(name); WOOL_OBJECT value = ((namespace -> namespaces) [namespace -> current])[name -> index]; if (value != UNDEFINED_WOOL_VALUE && (value -> type != WLAtom)) { return WOOL_send(WOOL_execute, value, (value, list)); } else if (value && (value == NIL)) { return NIL; } else { return (wool_error(UNDEFINED_FUNCTION, name)); } }