generic pointers generic data structures
play

Generic Pointers Generic Data Structures 1 /************ - PowerPoint PPT Presentation

Generic Pointers Generic Data Structures 1 /************ Implementation ***********/ Stacks typedef struct list_node list; struct list_node { string data; list* next; }; We defined stacks of strings typedef struct stack_header stack;


  1. Generic Pointers

  2. Generic Data Structures 1

  3. /************ Implementation ***********/ Stacks typedef struct list_node list; struct list_node { string data; list* next; };  We defined stacks of strings typedef struct stack_header stack; …  But, /**************** Interface ****************/ o the code for stacks of ints would be // typedef ______* stack_t; identical except for string changed to int bool stack_empty(stack_t S) /*@requires S != NULL; @*/ ; o the code for stacks of any type would be stack_t stack_new() identical except for string changed to this /*@ensures \result != NULL; @*/ type /*@ensures stack_empty(\result); @*/ ; void push(stack_t S, string x) o … /*@requires S != NULL; @*/ /*@ensures !stack_empty(S); @*/ ; string pop(stack_t S) /*@requires S != NULL; @*/ /*@requires !stack_empty(S); @*/ ; 2

  4. /************ Implementation ***********/ Stacks typedef struct list_node list; struct list_node { string data; list* next; };  Each time we need a stack for a new typedef struct stack_header stack; element type, we need to make a copy … of the stack library /**************** Interface ****************/ // typedef ______* stack_t;  This is bad o It’s easy to make a mistake bool stack_empty(stack_t S) /*@requires S != NULL; @*/ ; o We need to come up with new names stack_t stack_new()  int_stack_t, int_stack_empty , … /*@ensures \result != NULL; @*/ /*@ensures stack_empty(\result); @*/ ;  int_list, int_list_node, is_int_segment , … o If we discover a bug, we need to fix it in void push(stack_t S, string x) /*@requires S != NULL; @*/ every copy of the library /*@ensures !stack_empty(S); @*/ ;  same if we discover a better implementation string pop(stack_t S) /*@requires S != NULL; @*/ /*@requires !stack_empty(S); @*/ ;  For a large application, this quickly becomes unmanageable 3

  5. Generic Data Structures  Stacks are intrinsecally generic data structures o They work the same way no matter the type of their elements o They do not modify elements  they only store them in the data structure and give them back  We would like to implement them as a generic library o a single stack implementation that can be used for elements of any type  without copying it over and over  without a proliferation of function and type names o if we find a bug, there is one place where to fix it  if we are told of a better implementation, there is one file to change 4

  6. /************ Client Interface ***********/ // typedef ______ elem; Generic Stacks -- Take 1 /************ Implementation ***********/ typedef struct list_node list; struct list_node { elem data;  Here’s an idea: list* next; o use a generic type name elem in the library }; o let the client define what elem is typedef struct stack_header stack; … /**************** Interface ****************/  We note the type elem is to be defined // typedef ______* stack_t; by the client in the client interface bool stack_empty(stack_t S) /*@requires S != NULL; @*/ ;  The client needs to define what elem stack_t stack_new() actually is in the client definition code /*@ensures \result != NULL; @*/ /*@ensures stack_empty(\result); @*/ ; void push(stack_t S, elem x) /*@requires S != NULL; @*/ /*@ensures !stack_empty(S); @*/ ; elem pop(stack_t S) /******** Client definitions ********/ /*@requires S != NULL; @*/ /*@requires !stack_empty(S); @*/ ; typedef string elem; 5

  7. /************ Client Interface ***********/ // typedef ______ elem; Generic Stacks -- Take 1 /************ Implementation ***********/ typedef struct list_node list; struct list_node { elem data; Pros: list* next; };  A single library for any kind of stack typedef struct stack_header stack; … o If the client needs a stack of ints in a /**************** Interface ****************/ different application,  simply define elem as int // typedef ______* stack_t; bool stack_empty(stack_t S) /*@requires S != NULL; @*/ ; o If another application stack_t stack_new() requires a different /*@ensures \result != NULL; @*/ /*@ensures stack_empty(\result); @*/ ; stack type, just define elem appropriately void push(stack_t S, elem x) /*@requires S != NULL; @*/ /*@ensures !stack_empty(S); @*/ ; elem pop(stack_t S) /******** Client definitions ********/ /*@requires S != NULL; @*/ /*@requires !stack_empty(S); @*/ ; typedef int elem; 6

  8. /************ Client Interface ***********/ // typedef ______ elem; Generic Stacks -- Take 1 /************ Implementation ***********/ typedef struct list_node list; struct list_node { elem data; Cons: list* next; };  Client application has to be split into typedef struct stack_header stack; two files … /***** Client definitions *****/  Client definition file /**************** Interface ****************/ typedef string elem; This is mildly // typedef ______* stack_t;  Rest of the client application /* Client application */ annoying bool stack_empty(stack_t S) int main() { /*@requires S != NULL; @*/ ; … push … pop … o because } stack_t stack_new()  the library needs elem to be defined /*@ensures \result != NULL; @*/ /*@ensures stack_empty(\result); @*/ ;  This must occur before the library  the client application needs the types and void push(stack_t S, elem x) /*@requires S != NULL; @*/ functions provided by the library to be defined /*@ensures !stack_empty(S); @*/ ;  This must occur after the library elem pop(stack_t S) /*@requires S != NULL; @*/ /*@requires !stack_empty(S); @*/ ; 7

  9. /************ Client Interface ***********/ // typedef ______ elem; Generic Stacks -- Take 1 /************ Implementation ***********/ typedef struct list_node list; struct list_node { elem data; list* next; /***** Client definitions *****/ }; Client definitions file client-stack.c0 typedef string elem; typedef struct stack_header stack; … /* Client application */ App. /**************** Interface ****************/ int main() { file main.c0 … push … pop … // typedef ______* stack_t; } bool stack_empty(stack_t S) Linux Terminal /*@requires S != NULL; @*/ ; # cc0 -d client-stack.c0 stack.c0 main.c0 stack_t stack_new() /*@ensures \result != NULL; @*/ /*@ensures stack_empty(\result); @*/ ; Library void push(stack_t S, elem x) file stack.c0 /*@requires S != NULL; @*/ /*@ensures !stack_empty(S); @*/ ;  This forces an unnatural compilation elem pop(stack_t S) pattern /*@requires S != NULL; @*/ /*@requires !stack_empty(S); @*/ ; This is mildly annoying 8

  10. /************ Client Interface ***********/ // typedef ______ elem; Generic Stacks -- Take 1 /************ Implementation ***********/ typedef struct list_node list; struct list_node { elem data; Cons: list* next; };  Client application can contain at most typedef struct stack_header stack; one type of stacks … /**************** Interface ****************/ o no way to have both a stack of strings and // typedef ______* stack_t; a stack of ints in the same application This is a big deal  but we can have multiple stacks of ints bool stack_empty(stack_t S) /*@requires S != NULL; @*/ ; o because there can be only one definition stack_t stack_new() /*@ensures \result != NULL; @*/ for elem /*@ensures stack_empty(\result); @*/ ; void push(stack_t S, elem x) /***** Client definitions *****/ ? /*@requires S != NULL; @*/ /*@ensures !stack_empty(S); @*/ ; typedef string elem; typedef int elem; The compiler won’t elem pop(stack_t S) know which elem /*@requires S != NULL; @*/ to use when /*@requires !stack_empty(S); @*/ ; Compilation error! 9

  11. /************ Client Interface ***********/ // typedef ______ elem; Generic Stacks -- Take 1 /************ Implementation ***********/ typedef struct list_node list; struct list_node { elem data; Summary list* next; }; typedef struct stack_header stack;  Pros: … o A single library for any kind of stacks /**************** Interface ****************/ // typedef ______* stack_t; This is mildly annoying  Cons: bool stack_empty(stack_t S) /*@requires S != NULL; @*/ ; o Client application is split into two files stack_t stack_new()  Unnatural compilation pattern /*@ensures \result != NULL; @*/ /*@ensures stack_empty(\result); @*/ ; o Client application can contain at most one void push(stack_t S, elem x) /*@requires S != NULL; @*/ type of stacks /*@ensures !stack_empty(S); @*/ ; elem pop(stack_t S) /*@requires S != NULL; @*/ This is a /*@requires !stack_empty(S); @*/ ; big deal 10

  12. Can we do Better?  Not in C0 …  … but the language C1 extends C0 with a mechanism to address these issues 11

  13. C1 12

  14. The language C1  C1 is an extension of C0 o Every C0 program is a C1 program  C1 provides two additional mechanisms o Generic pointers o Function pointers Both help with genericity  Right now, we will only examine generic pointers 13

  15. Running C1 Programs  C1 programs are compiled with cc0 o but C1-only constructs are only allowed in files with a .c1 extension  C0-only code can appear in files with either a .c0 or a .c1 extension  Example Linux Terminal # cc0 -d uba.c0 stack.c1 main.c1 File written File with File that may (or may not) purely in C0 C1 code contain C1 constructs  The coin interpreter does not currently support C1 constructs o no way to experiment with them in coin 14

  16. Generic Pointers 15

Recommend


More recommend