commit d8380d2

0uppy  ·  2026-09-11 21:30:15 +0000 UTC
parent 9b2652e
cotton - cot now has strings + i also updated the loop at the end of the interpreter
5 files changed,  +195, -76
+1, -1
1@@ -29,7 +29,7 @@ as stated in the docs, since cotton still hasn't reached a stable release + know
2 
3 honestly i dont have a whole lot to put here for the time being as im afraid to set up goals too high for myself and end up not being able to achieve them, but, for now:
4 
5-* Figure out what i wanna do with the syntax (kinda experimental atm [ ]
6+* Figure out what i wanna do with the syntax (kinda experimental atm) [ ]
7 * Add more features to cot as it is somewhat barebones as of now [ ]
8 * Split(?) `interpreter.c` so as to keep everything tidy and organised [ ]
9 * HOPEFULLY and EVENTUALLY one day, some time soon(TM) figure out how to compile cot to uxntal [ ]
+16, -12
 1@@ -13,35 +13,39 @@ programming language
 2 cot's development is being made side by side with cotton's development, as such, one keeps
 3 the other in mind
 4 
 5-cotton has two types of keywords: builtins and immediates
 6+cot has two types of keywords: builtins and immediates
 7 
 8 .Bl -tag -width "Immediates"
 9 .It Builtins
10-Words that are executed at runtime that directly manipulate the data stack or the memory (such as +, -, dup, swap, ->, @, etc.).
11+Words that are executed at runtime that directly manipulate the data stack or the memory (such as +, -, dup, swap, ->, @, etc.)
12 .It Immediates
13-Words processed at compile time to handle control flow and the program's structure (such as if, else, end, etc.).
14+Words processed at compile time to handle control flow and the program's structure (such as if, else, end, etc.)
15 .El
16 
17 .Sh WORDS
18 .Bl -tag -width "-> (slot)"
19 .It Ic + , - , * , /
20-Pops two values, performs arithmetic, and pushes the result.
21+Pops two values, performs arithmetic, and pushes the result
22 .It Ic dup
23-Duplicates the top value on the stack.
24+Duplicates the top value on the stack
25 .It Ic swap
26-Swaps the top two values on the stack.
27+Swaps the top two values on the stack
28 .It Ic drop
29-Discards/drops the top value on the stack.
30+Discards/drops the top value on the stack
31 .It Ic ->
32-Pops a value and a slot index, then stores the value in that same variable slot.
33+Pops a value and a slot index, then stores the value in that same variable slot
34 .It Ic @
35-Pops a slot index and pushes the stored value back onto the stack.
36+Pops a slot index and pushes the stored value back onto the stack
37+.It Ic .n
38+Prints a number
39+.It Ic .s
40+Prints a string
41 .It Ic ? if
42-Pops a value, if it's not zero, then it executes the block after it.
43+Pops a value, if it's not zero, then it executes the block after it
44 .It Ic else
45-Executes if the prior if evaluated to zero.
46+Executes if the prior if evaluated to zero
47 .It Ic end
48-Closes an if or else block.
49+Closes an if or else block
50 .El
51 
52 NOTE: some of the commands above are subject to change given that cot(ton) has yet to reach it's first stable release - even then, any update to any command will be doccumented here and i will also do my best to not break the whole syntax every update ;w;
+1, -0
1@@ -0,0 +1 @@
2+"hallo from neu cot" .s
+1, -0
1@@ -6,6 +6,7 @@
2 #define OP_KILL        2
3 #define OP_JMP         3
4 #define OP_FJMP        4
5+#define OP_PUSH_STR	   5
6 
7 #define STACK_SIZE     64
8 #define JMP_STACK_SIZE 32
+176, -63
  1@@ -11,7 +11,7 @@ ooooo get off your ass dani ooooo go work ooooo dani you're a bum oooooo oooooo
  2 static void word_add
  3 (Cotton *c)
  4 {
  5-    int b = pop(c);
  6+	int b = pop(c);
  7     int a = pop(c);
  8 
  9     push(c, a + b);
 10@@ -43,6 +43,7 @@ static void word_div
 11 
 12     // Now, i doubt anyone will really be dividing stuff by zero but you never know.., talk about le safety amirite.., heh 
 13     if (b == 0) {
 14+
 15         fprintf(stderr, "cotton: you cant divide by zero, you dummy :P\n");
 16         return;
 17     }
 18@@ -50,10 +51,25 @@ static void word_div
 19     push(c, a / b);
 20 }
 21 
 22-static void word_dot
 23+static void word_dotnum
 24 (Cotton *c)
 25 {
 26-    printf("%d\n", pop(c));
 27+	printf("%d\n", pop(c));
 28+}
 29+
 30+static void word_dotstr
 31+(Cotton *c)
 32+{ 
 33+    int ptr = pop(c);
 34+
 35+    while (c->mem[ptr] != '\0') {
 36+
 37+        printf("%c", c->mem[ptr]);
 38+
 39+        ptr++;
 40+    }
 41+
 42+	printf("\n");
 43 }
 44 
 45 // while forth does use ! and @, im quirky and #notlikeothergirls so im changing ! to -> bc i think it makes more sense :P
 46@@ -64,10 +80,12 @@ static void word_store
 47     int num = pop(c);
 48 
 49     if (slot >= 0 && slot < VARS_SIZE) {
 50+
 51         c->vars[slot] = num;
 52     } 
 53 
 54     else {
 55+
 56         fprintf(stderr, "cotton: i tried to store somewhere that don't exist,, its in the void now.., :(\n");
 57     }
 58 }
 59@@ -78,10 +96,12 @@ static void word_fetch
 60     int slot = pop(c);
 61 
 62     if (slot >= 0 && slot < VARS_SIZE) {
 63-        push(c, c->vars[slot]);
 64+
 65+ 		push(c, c->vars[slot]);
 66     } 
 67 
 68     else {
 69+
 70         fprintf(stderr, "cotton: i tried to fetch from somewhere that seemingly don't exist,, erm.,.\n");
 71     }
 72 }
 73@@ -143,7 +163,8 @@ static Word builtins[] = {
 74     {"-", word_sub},
 75     {"*", word_mul},
 76     {"/", word_div},
 77-    {".", word_dot},
 78+    {".n", word_dotnum},
 79+	{".s", word_dotstr}, 
 80     {"->", word_store},
 81     {"@", word_fetch},
 82     {"dup", word_dup},
 83@@ -162,6 +183,7 @@ static void word_if
 84 (Cotton *c)
 85 {
 86     if (c->jmp_stack_p >= JMP_STACK_SIZE) {
 87+
 88         fprintf(stderr, "cotton: there are too many nested ifs, calm down!! D:\n");
 89         return;
 90     }
 91@@ -175,6 +197,7 @@ static void word_else
 92 (Cotton *c)
 93 {
 94     if (c->jmp_stack_p <= 0) {
 95+
 96         fprintf(stderr, "cotton: i found an else without an if,., where'd that come from??\n");
 97         return;
 98     }
 99@@ -192,6 +215,7 @@ static void word_end
100 (Cotton *c)
101 {
102     if (c->jmp_stack_p <= 0) {
103+
104         fprintf(stderr, "cotton: i found an end without an if,., where'd that come from??\n");
105         return;
106     }
107@@ -210,80 +234,147 @@ static Word immediates[] = {
108 /* Another comment just so i can separate the immediates from the compiler and runtime functions blehhhhhh
109 words words words words more words SO many words OH MY GOD THERE ARE SO MANY WORDS WORDS WORDS WORDS AAAAAA*/
110 
111+// i feel like the compiler's a bit messy atm but i suppose this is yet another thing i shall revise when i eventually split the interpreter :P
112 void cotton_compile
113 (Cotton *c, char *line)
114 {
115     line[strcspn(line, "\r\n")] = 0;
116     if (line[0] == '\0' || (line[0] == '/' && line[1] == '/')) return;
117 
118-    char *tok = strtok(line, " ");
119+// this part of the compiling process is just for cotton to find strings 
120+
121+    int i = 0;
122+
123+    while (line[i] != '\0') {
124 
125-    while (tok) {
126-        
127         if (c->mem_len >= MEM_SIZE - 2) {
128-            fprintf(stderr, "cotton: i ran out of memory,., can't compile anymore :<\n");
129+
130+        	fprintf(stderr, "cotton: i have ran out of memory,., can't compile anymore :<\n");
131             return;
132         }
133 
134-        /* This is subjective to change but i thought that using ? for conditionals so stuff reads out as
135-        "is this happening? if so, then, blah blah blah" was a good idea, atleast sounded good in my head :P*/
136+        if (line[i] == ' ') {
137 
138-        if (strcmp(tok, "?") == 0) {
139-        // oh yeah, also, this doesn't really do anything, its just here to make if statements look nicer x3 
140+            i++;
141         }
142 
143-        else {            
144+        else if (line[i] == '"') {
145+            
146+            int string_start = i + 1;
147 
148-            int found_immediate = 0;
149+            for (i = string_start; line[i] != '\0'; i++) {
150+
151+                if (line[i] == '"') {
152+
153+                    line[i] = '\0';
154 
155-            for (int i = 0; immediates[i].name != NULL; i++) {
156-                
157-                if (strcmp(tok, immediates[i].name) == 0) {
158-                    immediates[i].code(c);
159-                    found_immediate = 1;
160                     break;
161                 }
162+
163+                else if (line[i] == '\0') {
164+
165+                    fprintf(stderr, "cotton: you forgot to close a string.,. i cant compile the file until you fix it :P");
166+                    return;
167+                }
168+
169             }
170 
171-            if (!found_immediate) {
172-                
173-                int is_num = 1;
174-                
175-                for (int i = 0; tok[i]; i++) {
176-                    
177-                    if (!isdigit(tok[i]) && !(i == 0 && tok[i] == '-')) {
178-                        is_num = 0;
179+            c->mem[c->mem_len++] = OP_PUSH_STR;
180+
181+            for (int j = string_start; line[j] != '\0'; j++) {
182+
183+                c->mem[c->mem_len++] = line[j];
184+            }
185+
186+			c->mem[c->mem_len++] = '\0';
187+                        
188+            i++;
189+        }
190+
191+
192+// now it resumes to it's usual "reading words character by character" behaviour :P
193+
194+        else {
195+            
196+            int tok_start = i;
197+            
198+            while (line[i] != ' ' && line[i] != '\0') {
199+
200+                i++;
201+            }
202+            
203+            // Here i just terminate the token temporarily
204+            char temp = line[i];
205+            line[i] = '\0';
206+            
207+            char *tok = line + tok_start;
208+
209+            /* This is subjective to change but i thought that using ? for conditionals so stuff reads out as
210+            "is this happening? if so, then, blah blah blah" was a good idea, atleast sounded good in my head :P*/
211+
212+            if (strcmp(tok, "?") == 0) {
213+            // oh yeah, also, this doesn't really do anything, its just here to make if statements look nicer x3 
214+            }
215+
216+            else {            
217+
218+                int found_immediate = 0;
219+
220+                for (int j = 0; immediates[j].name != NULL; j++) {
221+
222+                    if (strcmp(tok, immediates[j].name) == 0) {
223+
224+                        immediates[j].code(c);
225+                        found_immediate = 1;
226                         break;
227                     }
228                 }
229 
230-                if (is_num) {
231-                    c->mem[c->mem_len++] = OP_PUSH;
232-                    c->mem[c->mem_len++] = atoi(tok);
233-                } 
234-
235-                else {
236+                if (!found_immediate) {
237                     
238-                    int found = 0;
239-
240-                    for (int i = 0; builtins[i].name != NULL; i++) {
241+                    int is_num = 1;
242+                    
243+                    for (int j = 0; tok[j]; j++) {
244                         
245-                        if (strcmp(tok, builtins[i].name) == 0) {
246-                            c->mem[c->mem_len++] = OP_CALL;
247-                            c->mem[c->mem_len++] = i;
248-                            found = 1;
249+                        if (!isdigit(tok[j]) && !(j == 0 && tok[j] == '-')) {
250+
251+                            is_num = 0;
252                             break;
253                         }
254                     }
255 
256-                    if (!found) {
257-                        fprintf(stderr, "cotton: sorry, i don't know what \"%s\" means :(\n", tok);
258+                    if (is_num) {
259+
260+                        c->mem[c->mem_len++] = OP_PUSH;
261+                        c->mem[c->mem_len++] = atoi(tok);
262+                    } 
263+
264+                    else {
265+                        
266+                        int found = 0;
267+
268+                        for (int j = 0; builtins[j].name != NULL; j++) {
269+                            
270+                            if (strcmp(tok, builtins[j].name) == 0) {
271+
272+                                c->mem[c->mem_len++] = OP_CALL;
273+                                c->mem[c->mem_len++] = j;
274+                                found = 1;
275+                                break;
276+                            }
277+                        }
278+
279+                        if (!found) {
280+
281+                            fprintf(stderr, "cotton: sorry, i don't know what \"%s\" means :(\n", tok);
282+                        }
283                     }
284                 }
285             }
286-        }
287 
288-        tok = strtok(NULL, " ");
289+			// now i just add this back so that the outer loop doesn't get kirkified broken heart emoji 
290+            line[i] = temp;
291+        }
292     }
293 }
294 
295@@ -295,32 +386,54 @@ void cotton_run
296     while (c->instruct_p < c->mem_len) {
297         
298         int op = c->mem[c->instruct_p++];
299-        
300-        if (op == OP_PUSH) {
301-            push(c, c->mem[c->instruct_p++]);
302-        }
303 
304-        else if (op == OP_CALL) { 
305+        switch (op) {
306 
307-            int idx = c->mem[c->instruct_p++];
308-            builtins[idx].code(c);
309-        }
310+            case OP_PUSH:
311+                push(c, c->mem[c->instruct_p++]);
312 
313-        else if (op == OP_JMP) {
314-            c->instruct_p = c->mem[c->instruct_p];
315-        }
316+                break;
317+
318+            case OP_CALL: {
319+                int id = c->mem[c->instruct_p++];
320+                builtins[id].code(c);
321 
322-        else if (op == OP_FJMP) {
323+                break;
324+            }
325 
326-            int target = c->mem[c->instruct_p++];
327+            case OP_JMP: {
328+                c->instruct_p = c->mem[c->instruct_p];
329 
330-            if (pop(c) == 0) {
331-                c->instruct_p = target;
332+                break;
333             }
334-        }
335 
336-        else if (op == OP_KILL) {
337-            break;
338+            case OP_FJMP: {
339+
340+                int target = c->mem[c->instruct_p++];
341+
342+                if (pop(c) == 0) {
343+                    c->instruct_p = target;
344+                }
345+
346+                break;
347+            }
348+
349+            case OP_PUSH_STR:
350+
351+             	push(c, c->instruct_p);
352+
353+                while (c->mem[c->instruct_p] != '\0') {
354+                    c->instruct_p++;
355+                }
356+                
357+                c->instruct_p++;
358+
359+                break;
360+
361+            case OP_KILL:
362+                
363+                return;
364+
365         }
366     }
367 }