Last active 2 weeks ago

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

compile.sh Raw Playground
1#!/usr/bin/env.sh
2
3echo "$1" | nova vm-compile.nv print.nv > program.h
4cc main.c
main.c Raw Playground
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)
7typedef unsigned int cell;
8
9typedef struct pair pair;
10struct pair {
11 cell first;
12 cell second;
13};
14
15typedef struct stack stack;
16struct stack {
17 cell data[STACK_SIZE];
18 pair top;
19};
20
21typedef struct core core;
22struct core {
23 stack stacks[STACK_COUNT];
24 cell stack;
25};
26
27cell empty(stack *stack) {
28 return stack->top.first == 0 && stack->top.second == 0;
29}
30
31cell full(stack *stack) {
32 return stack->top.first == STACK_SIZE && stack->top.second == SIZE_BITS(cell);
33}
34
35cell peek(stack *stack) {
36 if(stack == NULL) {
37 return 0;
38 }
39 return stack->data[stack->top.first] & 1;
40}
41
42cell 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
57void 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
71void 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
79void right(core *core) {
80 core->stack++;
81 if(core->stack == STACK_COUNT) {
82 core->stack = 0;
83 }
84}
85
86void left(core *core) {
87 if(core->stack == 0) {
88 core->stack = STACK_COUNT;
89 }
90 core->stack--;
91}
92
93void 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
116static core c;
117int main(void) {
118 #include "program.h"
119 DEBUG
120 return 0;
121}
print.nv Raw Playground
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 Raw Playground
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