Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active May 19, 2019 02:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/d9b408bd15311785a2a5d83b4a646af5 to your computer and use it in GitHub Desktop.
Save JoshCheek/d9b408bd15311785a2a5d83b4a646af5 to your computer and use it in GitHub Desktop.
Writing Ruby Like C (fun video of the process here: https://vimeo.com/336921852)
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list {
char* data;
struct list* successor;
} List;
enum ACTIONS {
ACTION_PUSH_STRING = 1,
ACTION_POP_STRING = 2,
ACTION_QUIT = 3
};
// ---- list functions -----
List* list_new() {
return NULL;
}
List* list_push(List* list, void* data) {
List* head = malloc(sizeof(List)); // this can technically fail
head->data = data;
head->successor = list;
return head;
}
void* list_data(List* list) {
return list ? list->data : NULL;
}
// Note that we do not manage the list's data.
// Caller is responsible for ensuring it has been freed.
List* list_pop(List* list) {
if(!list) return NULL;
List* successor = list->successor;
free(list);
return successor;
}
// ----- I/O functions -----
#define BUFFER_MEMSIZE 1000
char BUFFER[BUFFER_MEMSIZE];
void clear_screen(FILE* outstream) {
fprintf(outstream, "\e[H\e[2J");
}
void newline(FILE* outstream) {
fprintf(outstream, "\n");
}
void list_print(List* list, FILE* outstream) {
fprintf(outstream, "----- Begin List -----\n");
for(int i = 0; list; ++i) {
fprintf(outstream, "%d: %s\n", i, list->data);
list = list->successor;
}
fprintf(outstream, "----- End List -----\n");
}
// summary: buffer = $stdin.gets.chomp
size_t read_line_into_buffer(FILE* instream) {
fgets(BUFFER, BUFFER_MEMSIZE, instream);
size_t len = strnlen(BUFFER, BUFFER_MEMSIZE);
while(len && '\n' == BUFFER[len-1])
--len;
BUFFER[len] = 0;
return len;
}
int prompt_action(FILE* instream, FILE* outstream) {
fprintf(outstream, "Whatcha wanna do?!\n");
fprintf(outstream, "1. push a string\n");
fprintf(outstream, "2. pop\n");
fprintf(outstream, "3. quit\n");
fprintf(outstream, "> ");
size_t len = read_line_into_buffer(instream);
if(len == 1) {
int action = BUFFER[0] - '0';
if(action == 1 || action == 2 || action == 3)
return action;
}
fprintf(outstream, "Invalid choice: %s\n", BUFFER);
return prompt_action(instream, outstream);
}
char* prompt_string(FILE* instream, FILE* outstream) {
fprintf(outstream, "Enter a string to store:\n");
fprintf(outstream, "> ");
size_t len = read_line_into_buffer(instream);
char* str = malloc(sizeof(char)*len);
memcpy(str, BUFFER, len);
return str;
}
int main(int argc, char** argv) {
List* list = list_new();
FILE* instream = stdin;
FILE* outstream = stdout;
while(true) {
clear_screen(outstream);
list_print(list, outstream);
newline(outstream);
int action = prompt_action(instream, outstream);
switch (action) {
case ACTION_PUSH_STRING: {
char* str = prompt_string(instream, outstream);
list = list_push(list, str);
break;
} case ACTION_POP_STRING: {
char* str = list_data(list);
list = list_pop(list);
fprintf(outstream, "String Popped: %s\n", str);
free(str);
break;
} case ACTION_QUIT: {
fprintf(outstream, "Cheers!\n");
return 0;
} default: {
fprintf(outstream, "ERR: action = %d", action);
return 1;
}
}
}
}
List = Struct.new(
:data,
:successor
);
module ACTIONS
PUSH_STRING = 1;
POP_STRING = 2;
QUIT = 3;
end;
# ---- list functions -----
def list_new()
return nil;
end
def list_push(list, data)
head = List.new;
head.data = data;
head.successor = list;
return head;
end
def list_data(list)
return list ? list.data : nil;
end
def list_pop(list)
return nil if(!list);
return list.successor;
end
# ----- I/O functions -----
def clear_screen(outstream)
outstream.printf("\e[H\e[2J");
end
def newline(outstream)
outstream.printf("\n");
end
def list_print(list, outstream)
outstream.printf("----- Begin List -----\n");
for i in (0..Float::INFINITY)
break unless list
outstream.printf("%d: %s\n", i, list.data);
list = list.successor;
end
outstream.printf("----- End List -----\n");
end
def read_line(instream)
str = instream.gets;
str.chomp!;
return str;
end
def prompt_action(instream, outstream)
outstream.printf("Whatcha wanna do?!\n");
outstream.printf("1. push a string\n");
outstream.printf("2. pop\n");
outstream.printf("3. quit\n");
outstream.printf("> ");
line = read_line(instream);
if (line.length == 1)
action = line[0].ord - '0'.ord;
if (action == 1 || action == 2 || action == 3)
return action;
end
end
outstream.printf("Invalid choice: %s\n", line);
return prompt_action(instream, outstream);
end
def prompt_string(instream, outstream)
outstream.printf("Enter a string to store:\n");
outstream.printf("> ");
return read_line(instream);
end
def main(argc, argv)
list = list_new();
instream = $stdin;
outstream = $stdout;
while(true)
clear_screen(outstream);
list_print(list, outstream);
newline(outstream);
action = prompt_action(instream, outstream);
case action
when ACTIONS::PUSH_STRING;
str = prompt_string(instream, outstream);
list = list_push(list, str);
when ACTIONS::POP_STRING;
str = list_data(list);
list = list_pop(list);
outstream.printf("String Popped: %s\n", str);
when ACTIONS::QUIT;
outstream.printf("Cheers!\n");
return 0;
else
outstream.printf("ERR: action = %d", action);
return 1;
end
end
end
exit main(ARGV.size, ARGV);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment