change memory model #1

Merged
trinity merged 9 commits from meta into main 2022-12-09 21:08:37 -07:00
10 changed files with 182 additions and 52 deletions

5
.gitignore vendored
View File

@ -1,2 +1,3 @@
bin bin/blang
bin/* build
build/*

View File

@ -7,10 +7,16 @@ all: $(TARGETS)
clean: clean:
$(RM) $(TARGETS) $(RM) $(TARGETS)
bin: build:
mkdir -p bin mkdir -p build
bin/blang: bin src/*.c build/blang.o: build src/blang.c src/blang.h
$(CC) $(CFLAGS) -o $@ src/*.c $(CC) -c -o $@ src/blang.c
build/ops.o: build src/blang.h src/ops.c src/ops.h
$(CC) -c -o $@ src/ops.c
bin/blang: build/blang.o build/ops.o
$(CC) $(CFLAGS) -o $@ build/*.o
.PHONY: all clean .PHONY: all clean

View File

@ -12,21 +12,22 @@ the bang language
Public domain. 2022 DTB. Public domain. 2022 DTB.
# Examples ## Examples
## true(1) ### true(1)
``` ```
^ ; initialize state to 0 ; initialize hand to 0
% ; store state (0) into *stack ^
; stack is destroyed, state becomes the final value of *stack
; when the stack is destroyed, the program exits with the value of state ; set the chart pointer to 0 - this destroys the chart
$ ; and the program exits with the value of the hand
*
``` ```
## Hello world: ### Hello world:
``` ```
; the <.> construct uses '<' to store the next value literally into state, ; the <.> construct uses '<' to literally 'palm' the next value
; does so, and uses '>' to output state literally ; (store into hand), does so, and uses '>' to 'toss' (output hand's value)
<H><e><l><l><o><,>< ><w><o><r><l><d><!>< <H><e><l><l><o><,>< ><w><o><r><l><d><!><
>^%$ >^*
``` ```

3
bin/blangfile Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
blang "$(cat "$@")"

View File

@ -0,0 +1,2 @@
<H><e><l><l><o><,>< ><w><o><r><l><d><!><
>^*

2
example/true.blang Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env blangfile
^*

View File

@ -1,42 +1,24 @@
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
static unsigned char get = 0; #include "blang.h"
static unsigned char _stack[4]; #include "ops.h"
static unsigned char *stack = _stack;
static unsigned char *state;
int main(){ int main(int argc, char **argv){
struct State s;
int c; int c;
while((c = getchar()) != EOF){ void (*op)(struct State *);
if(stack == (unsigned char *)0)
return (char)state; s.chart = *(argv+1);
if(get){ s.counter = s.chart;
state = (char *)c;
get = 0; for(s.counter = s.chart; ; ++s.counter){
continue; if(s.chart == (char *)0)
} return (int)s.hand;
switch(c){ if((op = Ops_lookup(*s.counter)) == NULL)
case ' ': return 127;
case '\n': else
case '\r': op(&s);
case '\t':
case '\v':
break;
case '!': state = stack; break;
case '$': stack = state; state = (char *)*_stack; break;
case '%': *stack = (char)state; break;
case '^': state = (char *)0; break;
case '+': ++state; break;
case '-': --state; break;
case '>': putchar((char)state); break;
case '<': get = 1; break;
case ':':
while((c = getchar()) != '\n')
if(c == EOF)
goto fin;
break;
} }
} }
fin: return 1;
}

17
src/blang.h Normal file
View File

@ -0,0 +1,17 @@
#if !defined _BLANG_H
# define _BLANG_H
# include <stdint.h>
/* This has to be big enough to hold a char * without degradation.
* Adjust to architecture/system/environment/etc. */
typedef uint64_t hand_t;
/* Holds *argv; will not change between environments. */
typedef char * chart_t;
struct State{
chart_t chart;
chart_t point;
chart_t counter;
hand_t hand;
};
#endif

112
src/ops.c Normal file
View File

@ -0,0 +1,112 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "blang.h"
/* no-op */
void Ops_bang(struct State *s){
return;
}
void Ops_percent(struct State *s){
*(s->chart) = s->hand;
}
void Ops_carat(struct State *s){
s->hand = 0;
}
void Ops_ampersand(struct State *s){
s->hand = (uint64_t)s->chart;
}
void Ops_splat(struct State *s){
s->chart = (char *)s->hand;
}
void Ops_plus(struct State *s){
++(s->hand);
}
void Ops_dash(struct State *s){
--(s->hand);
}
void Ops_lbrack(struct State *s){
s->point = s->counter;
}
void Ops_rbrack(struct State *s){
s->counter = s->point;
}
void Ops_left(struct State *s){
s->hand = *++s->counter;
}
void Ops_right(struct State *s){
putc((char)s->hand, stdout);
}
void Ops_what(struct State *s){
if(!s->hand)
++(s->counter);
}
void Ops_semi(struct State *s){
int c;
while(strchr("!\n", *++s->counter) == NULL);
}
void Ops_mirror(struct State *s){
s->hand = !s->hand;
}
void Ops_cross(struct State *s){
char *i;
i = s->chart;
s->chart = (char *)s->hand;
s->hand = (uint64_t)i;
}
const struct {
unsigned char name;
void (*f)(struct State *);
} OPS[] = {
{ '#', Ops_semi },
{ '%', Ops_percent },
{ '^', Ops_carat },
{ '&', Ops_ampersand },
{ '*', Ops_splat },
{ '+', Ops_plus },
{ '-', Ops_dash },
{ '{', Ops_lbrack },
{ '}', Ops_rbrack },
{ ';', Ops_semi },
{ '>', Ops_right },
{ '<', Ops_left },
{ '?', Ops_what },
{ 'v', Ops_mirror },
{ 'x', Ops_cross },
/* no-ops */
{ '!', Ops_bang },
{ ' ', Ops_bang },
{ '\n', Ops_bang },
{ '\r', Ops_bang },
{ '\t', Ops_bang },
{ '\v', Ops_bang }
};
/* Slower than a switch but you don't have to update it when you add new
* ops! */
void (*Ops_lookup(char op))(struct State *){
size_t i;
for(i = 0; i < (sizeof OPS)/(sizeof *OPS); ++i)
if(op == OPS[i].name)
return OPS[i].f;
return NULL;
}

4
src/ops.h Normal file
View File

@ -0,0 +1,4 @@
#if !defined _BLANG_OPS
# define _BLANG_OPS 1
void (*Ops_lookup(char op))(struct State *);
#endif