commit caa7865

0uppy  ·  2026-09-09 21:19:54 +0000 UTC
parent d3753f8
cotton - remade the interpreter, cotton and main files (also updated the meson file and made the first neucot file woo :3)
9 files changed,  +257, -278
+4, -5
 1@@ -8,8 +8,6 @@ cotton originally started as a slightly modified CHIP8 emulator, then was repurp
 2 
 3 cotton is a passion hobby project being made solely by me, so, dont expect anything grandiose or of high quality - even then, suggestions and ideas are always welcome!! :D
 4 
 5-(*Inspired by Lua's internal engine's layout, not really the syntax itself)
 6-
 7 ## building cotton,
 8 
 9 ```
10@@ -37,6 +35,7 @@ this is cotton's mascot!! his name is ton!! he was drawn by me using old cotton'
11 
12 honestly i dont have alot to write here for the time being, mostly because im afraid to set high expectations that i can't achieve, however:
13 
14-* Repurpose the current code into my new idea for the project and run something []
15-* Update the current docs []
16-* One day figure out how to optionally compile cot files into uxntal files (might be too ambitious but one can dream, right :<) []
17+* Repurpose the current code into my new idea for the project and run something [X] (got a little base for tonight and it does work so wooo)
18+* Organise the codebase a bit bc i can see the interpreter getting quite full like on old cotton [ ]
19+* Update the current docs [ ]
20+* One day figure out how to optionally compile cot files into uxntal files (might be too ambitious but one can dream, right :<) [ ]
+0, -2
1@@ -1,2 +0,0 @@
2-print "test test this is a test" print
3-print "does cot render text okay again uhhh" print
+5, -0
1@@ -0,0 +1,5 @@
2+6 7 + .
3+
4+6 9 swap . .
5+
6+//im so funny aren't i 
+2, -3
 1@@ -1,5 +1,5 @@
 2 project('cotton', 'c',
 3-  version : '0.3',
 4+  version : '0.1',
 5   default_options : ['c_std=c99', 'warning_level=2'])
 6 
 7 sdl2 = dependency('sdl2')
 8@@ -7,8 +7,7 @@ sdl2 = dependency('sdl2')
 9 src_files = [
10   'src/main.c',
11   'src/cotton.c',
12-  'src/cottonwindow.c',
13   'src/interpreter.c',
14 ]
15 
16-executable('cotton', src_files, dependencies : sdl2)
17+executable('cotton', src_files)
+27, -8
 1@@ -1,17 +1,36 @@
 2 #include "cotton.h"
 3 #include <stdio.h>
 4-#include <stdlib.h>
 5-#include <string.h>
 6-#include <time.h>
 7 
 8 void cotton_init
 9-(Cotton *c)
10+(Cotton *c) 
11 {
12-    memset(c, 0, sizeof(Cotton));
13+    c->stack_p = 0;
14+    c->instruct_p = 0;
15+    c->mem_len = 0;
16 
17-    srand((unsigned int)time(NULL));
18+    for (int i = 0; i < VARS_SIZE; i++) {
19+        c->vars[i] = 0;
20+    }
21+}
22+
23+void push
24+(Cotton *c, int v) 
25+{
26+    if (c->stack_p >= STACK_SIZE) {
27+        fprintf(stderr, "cotton: stack overflow,., like the website,.., :<\n");
28+        return;
29+    }
30 
31-	c->stack_p = 0;
32+    c->stack[c->stack_p++] = v;
33+}
34+
35+int pop
36+(Cotton *c) 
37+{
38+    if (c->stack_p <= 0) {
39+        fprintf(stderr, "cotton: stack underflow :<\n");
40+        return 0;
41+    }
42 
43-    c->c_cottolette = COTTOLETTE[1];
44+    return c->stack[--c->stack_p];
45 }
+25, -48
 1@@ -1,62 +1,39 @@
 2 #ifndef COTTON_H
 3 #define COTTON_H
 4 
 5-#include <stdint.h>
 6-
 7-#define MEMORY_SIZE (64 * 1024)
 8-#define VIDEO_WIDTH 250
 9-#define VIDEO_HEIGHT 200
10-
11-#define COTTOLETTE_SIZE  8
12-
13-#define VARS 32 // i think this is enough,, not like cot programs can be that complex rn anyway :P
14-#define VAR_NAME_LEN 16
15-#define VAR_VAL_LEN 32
16-
17-static const uint32_t 
18-COTTOLETTE[COTTOLETTE_SIZE] = {
19-    0xFF1C1C1C, // 0 - blabla
20-    0xFFFAFAFA, // 1 - whie
21-    0xFFECE3FF, // 2 - lav
22-    0xFFE4D8FD, // 3 - wink
23-    0xFFD4C5F5, // 4 - sink
24-    0xFFA9A0CF, // 5 - wist
25-    0xFFFFFBDA, // 6 - yebow (random kid)
26-    0xFFD0F0C0  // 7 - geen (the (first) dude nobody invited)
27-};
28-
29-typedef struct
30-{
31-    char name[VAR_NAME_LEN];
32-    char value[VAR_VAL_LEN];
33-} CotVar;
34+#define OP_PUSH    0
35+#define OP_CALL    1
36+#define OP_KILL    2
37 
38-typedef struct
39-{
40-    uint8_t memory[MEMORY_SIZE];
41-    uint32_t video[VIDEO_WIDTH * VIDEO_HEIGHT];
42+#define STACK_SIZE 64
43+#define MEM_SIZE   1024
44+#define VARS_SIZE  64
45 
46-    // i cant come up with a better name that gets straight to the point than
47-    // "cursor" so ig it will stay this way for now,,
48-    int cursor_x;
49-    int cursor_y;
50+typedef struct Cotton Cotton;
51 
52-    uint32_t ticktock;
53-    uint32_t c_cottolette; // id write "current_cottolete" but that would be
54-                           // alot to type and im lazyyyyyyy bwaaaaaa
55+typedef struct {
56+    char *name;
57+    void (*code)(Cotton *c);
58+} Word;
59 
60-    CotVar vars[VARS];
61-	int var_count;
62+struct Cotton {
63+    int stack[STACK_SIZE];
64+    int stack_p;
65 
66-	int stack[32];
67-	int stack_p;
68+    int mem[MEM_SIZE];
69+    int instruct_p;
70+    int mem_len;
71 
72-} Cotton;
73+    int vars[VARS_SIZE];
74+};
75 
76 void cotton_init
77 (Cotton *c);
78-void cotton_store_var
79-(Cotton *cotton, const char *name, const char *value);
80 
81-#endif
82+void push
83+(Cotton *c, int v);
84 
85+int pop
86+(Cotton *c);
87+
88+#endif
+154, -208
  1@@ -1,273 +1,219 @@
  2-// i got to eventually clean up this file a bit i feel like its very janky but i suppose i can worry about that later - future dani here, it seems you ended up just remaking the entire file bc you thought remaking cot into a concatenated language was cooler, good job dani - future future dani here, thank you dani :D
  3-
  4+#include "cotton.h"
  5 #include "interpreter.h"
  6-#include "cottonwindow.h"
  7-#include "eiki.h"
  8-#include <SDL.h>
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <string.h>
 12 #include <ctype.h>
 13 
 14-#define MAX_LINE 256
 15-
 16-// da stack 
 17-static void push
 18-(Cotton *c, int v)
 19+static void word_add
 20+(Cotton *c)
 21 {
 22-    if (c->stack_p >= 64) {
 23-        fprintf(stderr, "cot: there has been a stack overflow :< (like the website badumptsss)\n");
 24-        return;
 25-    }
 26+    int b = pop(c);
 27+    int a = pop(c);
 28 
 29-    c->stack[c->stack_p++] = v;
 30+    push(c, a + b);
 31 }
 32 
 33-static int pop
 34+static void word_sub
 35 (Cotton *c)
 36 {
 37-    if (c->stack_p <= 0) {
 38-        fprintf(stderr, "cot: there has been a stack underflow :<\n");
 39-        return 0;
 40-    }
 41+    int b = pop(c);
 42+    int a = pop(c);
 43 
 44-    return c->stack[--c->stack_p];
 45+    push(c, a - b);
 46 }
 47 
 48-// da variable stuff
 49-static int find_var
 50-(Cotton *c, const char *name)
 51+static void word_mul
 52+(Cotton *c)
 53 {
 54-    for (int i = 0; i < c->var_count; i++) {
 55-        if (strcmp(c->vars[i].name, name) == 0) return i;
 56-    }
 57+    int b = pop(c);
 58+    int a = pop(c);
 59 
 60-    return -1;
 61+    push(c, a * b);
 62 }
 63 
 64-static void add_var
 65-(Cotton *c, const char *name)
 66+static void word_div
 67+(Cotton *c)
 68 {
 69-    if (c->var_count >= VARS) {
 70-        fprintf(stderr, "cot: too many variables\n");
 71+    int b = pop(c);
 72+    int a = pop(c);
 73+
 74+// Now i doubt anyone will really be dividing stuff by zero but you never know.., talk about le safety amirite.., heh 
 75+    if (b == 0) {
 76+        fprintf(stderr, "cotton: you cant divide by zero, you dummy :P\n");
 77         return;
 78     }
 79 
 80-    strncpy(c->vars[c->var_count].name, name, VAR_NAME_LEN - 1);
 81-    c->vars[c->var_count].name[VAR_NAME_LEN - 1] = '\0';
 82-    strcpy(c->vars[c->var_count].value, "0");
 83-    c->var_count++;
 84+    push(c, a / b);
 85 }
 86 
 87-// da graphics
 88-static void draw_pixel_c
 89-(Cotton *c, int x, int y)
 90+static void word_dot
 91+(Cotton *c)
 92 {
 93-   	if (x < 0 || x >= VIDEO_WIDTH || y < 0 || y >= VIDEO_HEIGHT) return;
 94-    c->video[y * VIDEO_WIDTH + x] = c->c_cottolette;
 95+    printf("%d\n", pop(c));
 96 }
 97 
 98-static void draw_char_c
 99-(Cotton *c, char ch, int x, int y)
100+// while forth does use ! and @, im quirky and #notlikeothergirls so im changing ! to -> bc i think it makes more sense :P
101+static void word_store
102+(Cotton *c)
103 {
104-    for (int row = 0; row < FONT_HEIGHT; row++) {
105-        uint8_t bits = EIKI_FONT[(uint8_t)ch][row];
106+    int slot = pop(c);
107+    int num = pop(c);
108 
109-        for (int col = 0; col < FONT_WIDTH; col++) {
110-            if (bits & (1 << col)) {
111-                draw_pixel_c(c, x + col, y + row);
112-            }
113-        }
114+    if (slot >= 0 && slot < VARS_SIZE) {
115+        c->vars[slot] = num;
116+    } else {
117+        fprintf(stderr, "cotton: tried to store somewhere that don't exist.,. its in the void now.., :<\n");
118     }
119 }
120 
121-// those who interpretate skull emoji skull emoji nahhhh get outttttttttt skull emoji door emoji
122-void cotton_interpret
123-(Cotton *c, CottonWindow *cw, FILE *file)
124+static void word_fetch
125+(Cotton *c)
126 {
127-    char line[MAX_LINE];
128-    if (!fgets(line, sizeof(line), file)) return;
129-    
130-    line[strcspn(line, "\r\n")] = 0;
131-    if (line[0] == '\0' || (line[0] == '/' && line[1] == '/')) return;
132-    
133-    char *tok = strtok(line, " ");
134-    
135-    while (tok) {
136+    int slot = pop(c);
137 
138-        int is_a_num = 1;
139-        for (int i = 0; tok[i]; i++) {
140-            if (!isdigit(tok[i]) && !(i == 0 && tok[i] == '-')) {
141-                is_a_num = 0;
142-                break;
143-            }
144-        }
145-        
146-        if (is_a_num) {
147-            push(c, atoi(tok));
148-        }
149-
150-		// those who do math..., math from the epic video gaem baldi's basics in education and learning,., you guys should play it its a good game i like baldi,. send me an email telling me your guys' PR on endless mode 
151-        else if (strcmp(tok, "+") == 0) {
152-            int b = pop(c), a = pop(c);
153-            push(c, a + b);
154-        }
155+    if (slot >= 0 && slot < VARS_SIZE) {
156+        push(c, c->vars[slot]);
157+    } else {
158+        fprintf(stderr, "cotton: tried to fetch from somewhere that don't exist,., :<\n");
159+    }
160+}
161 
162-        else if (strcmp(tok, "-") == 0) {
163-            int b = pop(c), a = pop(c);
164-            push(c, a - b);
165-        }
166+static void word_dup
167+(Cotton *c)
168+{
169+    int a = pop(c);
170 
171-        else if (strcmp(tok, "*") == 0) {
172-            int b = pop(c), a = pop(c);
173-            push(c, a * b);
174-        }
175+    push(c, a);
176+    push(c, a);
177+}
178 
179-        else if (strcmp(tok, "/") == 0) {
180-            int b = pop(c), a = pop(c);
181-            push(c, a / b);
182-        }
183+static void word_drop
184+(Cotton *c)
185+{
186+    pop(c);
187+}
188 
189-		// while forth does use ! and @, im quirky and #notlikeothergirls so im changing ! to -> bc i think it makes more sense :P
190-        else if (strcmp(tok, "->") == 0) {
191+static void word_swap
192+(Cotton *c)
193+{
194+    int b = pop(c);
195+    int a = pop(c);
196 
197-            int slot = pop(c);
198-			int num = pop(c);
199-			
200-			if (slot >= 0 && slot < c->var_count) {
201-                char buf[VAR_VAL_LEN];
202-                sprintf(buf, "%d", num);
203-                strncpy(c->vars[slot].value, buf, VAR_VAL_LEN - 1);
204-			} 	
205+    push(c, b);
206+    push(c, a);
207+}
208 
209-			else {
210-                fprintf(stderr, "cot: tried to store somewhere that don't exist.,. its in the void now.., :<\n");
211-            }
212-        }
213+static void word_equal
214+(Cotton *c)
215+{
216+    int b = pop(c);
217+    int a = pop(c);
218 
219-        else if (strcmp(tok, "@") == 0) {
220-            int slot = pop(c);
221+    push(c, a == b ? 1 : 0);
222+}
223 
224-        if (slot >= 0 && slot < c->var_count) {
225-                push(c, atoi(c->vars[slot].value));
226-            } 
227+static void word_lssr
228+(Cotton *c)
229+{
230+    int b = pop(c);
231+    int a = pop(c);
232 
233-        else {
234-        	fprintf(stderr, "cot: tried to fetch from somewhere that don't exist,., :<\n");
235-       	}
236+    push(c, a < b ? 1 : 0);
237+}
238 
239-        }
240+static void word_grtr
241+(Cotton *c)
242+{
243+    int b = pop(c);
244+    int a = pop(c);
245 
246-        else if (strcmp(tok, ".") == 0) {
247-            printf("%d", pop(c));
248-            fflush(stdout);
249-        }
250+    push(c, a > b ? 1 : 0);
251+}
252 
253-        else if (strcmp(tok, "var") == 0) {
254-            tok = strtok(NULL, " ");
255-            if (tok) add_var(c, tok);
256-        }
257+// should be enough for tonight.,., i shall be borrowing more from forth, forth is awesome, i love you forth, i forth <3 :3
258+static Word builtins[] = {
259+    {"+", word_add},
260+    {"-", word_sub},
261+    {"*", word_mul},
262+    {"/", word_div},
263+    {".", word_dot},
264+    {"->", word_store},
265+    {"@", word_fetch},
266+    {"dup", word_dup},
267+    {"drop", word_drop},
268+    {"swap", word_swap},
269+    {"=", word_equal},
270+    {"<", word_lssr},
271+    {">", word_grtr},
272+    {NULL, NULL}
273+};
274+
275+void cotton_compile
276+(Cotton *c, char *line)
277+{
278+    line[strcspn(line, "\r\n")] = 0;
279+    if (line[0] == '\0' || (line[0] == '/' && line[1] == '/')) return;
280 
281-        else if (strcmp(tok, "pixel") == 0) {
282-            int y = pop(c);
283-            int x = pop(c);
284-            draw_pixel_c(c, x, y);
285-            cottonwindow_update(cw, c->video, sizeof(c->video[0]) * VIDEO_WIDTH);
286-        }
287+    char *tok = strtok(line, " ");
288 
289-        else if (strcmp(tok, "color") == 0) {
290-            int slot = pop(c);
291-            if (slot >= 0 && slot < COTTOLETTE_SIZE)
292-                c->c_cottolette = COTTOLETTE[slot];
293+    while (tok) {
294+        if (c->mem_len >= MEM_SIZE - 2) {
295+            fprintf(stderr, "cotton: memory is full,., can't compile anymore :<\n");
296+            return;
297         }
298 
299-        else if (strcmp(tok, "clear") == 0) {
300-            for (int i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT; i++) 
301-                c->video[i] = 0;
302-            c->cursor_x = 0;
303-            c->cursor_y = 0;
304-            cottonwindow_update(cw, c->video, sizeof(c->video[0]) * VIDEO_WIDTH);
305+        int is_num = 1;
306+        for (int i = 0; tok[i]; i++) {
307+            if (!isdigit(tok[i]) && !(i == 0 && tok[i] == '-')) {
308+                is_num = 0;
309+                break;
310+            }
311         }
312 
313-		// the great wall of colors
314-        else if (strcmp(tok, "blabla") == 0) push(c, 0);
315-        else if (strcmp(tok, "whie") == 0) push(c, 1);
316-        else if (strcmp(tok, "lav") == 0) push(c, 2);
317-        else if (strcmp(tok, "wink") == 0) push(c, 3);
318-        else if (strcmp(tok, "sink") == 0) push(c, 4);
319-        else if (strcmp(tok, "wist") == 0) push(c, 5);
320-        else if (strcmp(tok, "yebow") == 0) push(c, 6);
321-        else if (strcmp(tok, "geen") == 0) push(c, 7);
322-
323-        else if (strcmp(tok, "print") == 0) {
324-            char *str = strtok(NULL, "");
325-            
326-            if (str) {
327-                while (*str == ' ') str++;
328-                
329-                int nl = 0;
330-                char *nl_at = strstr(str, " /n");
331-
332-            if (nl_at) {
333-                    *nl_at = '\0';
334-                    nl = 1;
335-                }
336-                
337-                if (str[0] == '"') {
338-                    str++;
339-                    char *end = strrchr(str, '"');
340-                    if (end) *end = '\0';
341-                }
342-                
343-                printf("%s", str);
344-                if (nl) printf("\n");
345-                fflush(stdout);
346-                
347-                for (int i = 0; str[i]; i++) {
348-                    if (str[i] == '\n') {
349-                        c->cursor_x = 0;
350-                        c->cursor_y += FONT_HEIGHT + 4;
351-                        continue;
352-                    }
353-
354-            		draw_char_c(c, str[i], c->cursor_x, c->cursor_y);
355-                    c->cursor_x += FONT_WIDTH + 2;
356-
357-                    if (c->cursor_x + FONT_WIDTH >= VIDEO_WIDTH) {
358-                        c->cursor_x = 0;
359-                        c->cursor_y += FONT_HEIGHT + 4;
360-                    }
361-                }
362+        if (is_num) {
363+            c->mem[c->mem_len++] = OP_PUSH;
364+            c->mem[c->mem_len++] = atoi(tok);
365+        } 
366 
367-                if (nl) {
368-                    c->cursor_x = 0;
369-                    c->cursor_y += FONT_HEIGHT + 4;
370+        else {
371+            int found = 0;
372+            for (int i = 0; builtins[i].name != NULL; i++) {
373+                if (strcmp(tok, builtins[i].name) == 0) {
374+                    c->mem[c->mem_len++] = OP_CALL;
375+                    c->mem[c->mem_len++] = i;
376+                    found = 1;
377+                    break;
378                 }
379+            }
380 
381-                cottonwindow_update(cw, c->video, sizeof(c->video[0]) * VIDEO_WIDTH);
382+            if (!found) {
383+                fprintf(stderr, "cotton: cotton doesn't know what \"%s\" means,., :<\n", tok);
384             }
385-            break;
386-        }
387-        
388-        else if (strcmp(tok, "wait") == 0) {
389-            c->ticktock = SDL_GetTicks() + pop(c);
390         }
391+        tok = strtok(NULL, " ");
392+    }
393+}
394 
395-        else if (strcmp(tok, "kill") == 0) {
396-            exit(0);
397+void cotton_run
398+(Cotton *c)
399+{
400+    c->instruct_p = 0;
401+
402+    while (c->instruct_p < c->mem_len) {
403+        int op = c->mem[c->instruct_p++];
404+
405+        if (op == OP_PUSH) {
406+            push(c, c->mem[c->instruct_p++]);
407         }
408 
409-        else {
410-            int slot = find_var(c, tok);
411-            if (slot >= 0) {
412-                push(c, slot);
413-            }
414+        else if (op == OP_CALL) {
415+            int idx = c->mem[c->instruct_p++];
416+            builtins[idx].code(c);
417+        }
418 
419-            else {
420-                fprintf(stderr, "cot: cotton doesn't know what \"%s\" means, maybe type that out again? :<", tok);
421-            }
422+        else if (op == OP_KILL) {
423+            break;
424         }
425-        
426-        tok = strtok(NULL, " ");
427     }
428 }
+5, -4
 1@@ -2,10 +2,11 @@
 2 #define INTERPRETER_H
 3 
 4 #include "cotton.h"
 5-#include "cottonwindow.h"
 6-#include <stdio.h>
 7 
 8-void cotton_interpret
 9-(Cotton *cotton, CottonWindow *cw, FILE *file);
10+void cotton_compile
11+(Cotton *c, char *line);
12+
13+void cotton_run
14+(Cotton *c);
15 
16 #endif
+35, -0
 1@@ -0,0 +1,35 @@
 2+#include "cotton.h"
 3+#include "interpreter.h"
 4+#include <stdio.h>
 5+
 6+int main
 7+(int argc, char **argv)
 8+{
 9+    if (argc < 2) {
10+        fprintf(stderr, "cotton: cotton couldn't find any .cot files to run :P\n");
11+        return 1;
12+    }
13+
14+    FILE *f = fopen(argv[1], "r");
15+
16+    if (!f) {
17+        fprintf(stderr, "cotton: couldn't open \"%s\", is this even a file.,.? :<\n", argv[1]);
18+        return 1;
19+    }
20+
21+    Cotton c;
22+    cotton_init(&c);
23+
24+    char line[256];
25+    while (fgets(line, sizeof(line), f)) {
26+        cotton_compile(&c, line);
27+    }
28+
29+    fclose(f);
30+
31+    c.mem[c.mem_len++] = OP_KILL;
32+
33+    cotton_run(&c);
34+
35+    return 0;
36+}