最終更新 2 weeks ago

A compiler from a multi-bit-stack VM to C.

june's Avatar june revised this gist 2 weeks ago. Go to revision

No changes

june's Avatar june revised this gist 2 weeks ago. Go to revision

1 file changed, 1 insertion, 1 deletion

compile.sh

@@ -1,4 +1,4 @@
1 1 #!/usr/bin/env.sh
2 2
3 3 echo "$1" | nova vm-compile.nv print.nv > program.h
4 - gcc main.c
4 + cc main.c

june's Avatar june revised this gist 2 weeks ago. Go to revision

4 files changed, 212 insertions

compile.sh(file created)

@@ -0,0 +1,4 @@
1 + #!/usr/bin/env.sh
2 +
3 + echo "$1" | nova vm-compile.nv print.nv > program.h
4 + gcc main.c

main.c(file created)

@@ -0,0 +1,121 @@
1 + #include <limits.h>
2 + #include <stdio.h>
3 +
4 + #define STACK_SIZE 10
5 + #define STACK_COUNT 10
6 + #define SIZE_BITS(type) (sizeof(type) * CHAR_BIT)
7 + typedef unsigned int cell;
8 +
9 + typedef struct pair pair;
10 + struct pair {
11 + cell first;
12 + cell second;
13 + };
14 +
15 + typedef struct stack stack;
16 + struct stack {
17 + cell data[STACK_SIZE];
18 + pair top;
19 + };
20 +
21 + typedef struct core core;
22 + struct core {
23 + stack stacks[STACK_COUNT];
24 + cell stack;
25 + };
26 +
27 + cell empty(stack *stack) {
28 + return stack->top.first == 0 && stack->top.second == 0;
29 + }
30 +
31 + cell full(stack *stack) {
32 + return stack->top.first == STACK_SIZE && stack->top.second == SIZE_BITS(cell);
33 + }
34 +
35 + cell peek(stack *stack) {
36 + if(stack == NULL) {
37 + return 0;
38 + }
39 + return stack->data[stack->top.first] & 1;
40 + }
41 +
42 + cell pop(stack *stack) {
43 + cell bit = 0;
44 + if(stack == NULL || empty(stack)) {
45 + return 0;
46 + }
47 + bit = peek(stack);
48 + stack->data[stack->top.first] >>= 1;
49 + stack->top.second--;
50 + if(stack->top.second == 0 && stack->top.first != 0) {
51 + stack->top.second = SIZE_BITS(cell);
52 + stack->top.first--;
53 + }
54 + return bit;
55 + }
56 +
57 + void push(stack *stack, cell bit) {
58 + if(stack == NULL || full(stack)) {
59 + return;
60 + }
61 + stack->data[stack->top.first] <<= 1;
62 + stack->data[stack->top.first] |= bit;
63 + stack->top.second++;
64 + if(stack->top.second == SIZE_BITS(cell)) {
65 + stack->top.second = 0;
66 + stack->top.first++;
67 + }
68 + return;
69 + }
70 +
71 + void print_stack(stack *stack) {
72 + cell iterator = 0;
73 + while(iterator < stack->top.second) {
74 + printf("%d", (stack->data[stack->top.first] >> iterator) & 1);
75 + iterator++;
76 + }
77 + }
78 +
79 + void right(core *core) {
80 + core->stack++;
81 + if(core->stack == STACK_COUNT) {
82 + core->stack = 0;
83 + }
84 + }
85 +
86 + void left(core *core) {
87 + if(core->stack == 0) {
88 + core->stack = STACK_COUNT;
89 + }
90 + core->stack--;
91 + }
92 +
93 + void print_core(core *core) {
94 + cell iterator;
95 + for(iterator = 0; iterator < STACK_COUNT; iterator++) {
96 + if(!empty(&core->stacks[iterator])) {
97 + printf("%d(%d, %d): ", iterator, core->stacks[iterator].top.first, core->stacks[iterator].top.second);
98 + print_stack(&core->stacks[iterator]);
99 + if(iterator == core->stack) {
100 + putchar(" <");
101 + }
102 + putchar("\n");
103 + }
104 + }
105 + }
106 +
107 + #define BEGIN while(pop(&c.stacks[c.stack])) {
108 + #define END }
109 + #define LEFT left(&c);
110 + #define RIGHT right(&c);
111 + #define ZERO push(&c.stacks[c.stack], 0);
112 + #define ONE push(&c.stacks[c.stack], 1);
113 + #define HALT return 0;
114 + #define DEBUG print_core(&c);
115 +
116 + static core c;
117 + int main(void) {
118 + #include "program.h"
119 + DEBUG
120 + return 0;
121 + }

print.nv(file created)

@@ -0,0 +1,56 @@
1 + |:: print? :string: '%d'| :: print a number
2 + |:: print? :string: '%b'| :: print a number :base: 2
3 + |:: print? :string: '%x'| :: print a number :base: 16
4 + |:: print? :string: '%s'| :: print a string
5 + |:: print? :string: '{}'| :: print an argument
6 + |:: print? :string: '\n'| :string: 10
7 + |:: print? :string: '\t'| :string: 9
8 + |:: print? :string: '\r'| :string: 13
9 + |:: print? :string: '\0'| :string: 0
10 + |:: print? :string: $ | :@stdio: write $
11 + |:: print :string: |
12 + |:: print |
13 +
14 + |:: print an argument :arguments: string| :: print a string
15 + |:: print an argument :arguments: number| :: print a number
16 + |:: print an argument :arguments: |
17 + |:: print an argument :arguments: $ | :: error -- unknown argument type $
18 +
19 + |:: print a number|
20 + :: convert an argument to a string
21 + :: print an argument
22 +
23 + |:: print a string? :arguments: $|:@stdio: write $
24 + |:: print a string :arguments: |
25 + |:: print a string |
26 +
27 + |:: convert an argument to a string :arguments: 0|
28 + :arguments: string :arguments:
29 + '0'
30 + :arguments:
31 + |:: convert an argument to a string :arguments: $|
32 + :: break $ into digits
33 + :: make those digits printable
34 + :: push a separator to the arguments stack
35 + :: move those digits to the arguments stack
36 + :: set the argument type to string
37 +
38 + |:: break 0 into digits :base: $|
39 + |:: break $number into digits :@rpn.stack: ($next $digit)|
40 + :digits: $digit
41 + :: break $next into digits
42 + |:: break $number into digits? :base: $base?|
43 + :@rpn: ($number $base % $number $base /)
44 + |:: break $number into digits?|
45 + :base: 10
46 +
47 + |:: make those digits printable? :@rpn.stack: $| :printable digits: $
48 + |:: make those digits printable? :digits: $| :@rpn: ($ 48 +)
49 + |:: make those digits printable |
50 +
51 + |:: push a separator to the arguments stack| :arguments:
52 +
53 + |:: move those digits to the arguments stack? :printable digits: $| :arguments: $
54 + |:: move those digits to the arguments stack |
55 +
56 + |:: set the argument type to $| :arguments: $

vm-compile.nv(file created)

@@ -0,0 +1,31 @@
1 + |:: read a character :@stdio: read|
2 + :end of file:
3 + |:: read a character :@stdio: $x|
4 + :buffer: $x
5 + |:: read a character?|
6 + :@stdio: read
7 +
8 + |:: reverse? :buffer: $x|
9 + :text: $x
10 + |:: reverse|
11 +
12 + |:: read :end of file|
13 + :: reverse
14 + |:: read?|
15 + :: read a character
16 +
17 + |:: parse? :text: ">1<[>[0]<"| :: print :string: " if(pop(&c.stacks[c.stack])) {\n"
18 + |:: parse? :text: ">0<0]>[<" | :: print :string: " } else {\n"
19 + |:: parse? :text: ">0]<" | :: print :string: " }\n"
20 +
21 + |:: parse? :text: '0'| :: print :string: " ZERO\n"
22 + |:: parse? :text: '1'| :: print :string: " ONE\n"
23 + |:: parse? :text: '['| :: print :string: " BEGIN\n"
24 + |:: parse? :text: ']'| :: print :string: " END\n"
25 + |:: parse? :text: '<'| :: print :string: " LEFT\n"
26 + |:: parse? :text: '>'| :: print :string: " RIGHT\n"
27 + |:: parse? :text: '@'| :: print :string: " HALT\n"
28 + |:: parse? :text: '?'| :: print :string: " DEBUG\n"
29 + |:: parse? :text: $x |
30 +
31 + ||:: read :: parse
Newer Older