change memory model #1
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
bin
|
bin/blang
|
||||||
bin/*
|
build
|
||||||
|
build/*
|
||||||
|
14
Makefile
14
Makefile
@ -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
|
||||||
|
23
README.md
23
README.md
@ -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
3
bin/blangfile
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
blang "$(cat "$@")"
|
2
example/hello_world.blang
Normal file
2
example/hello_world.blang
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<H><e><l><l><o><,>< ><w><o><r><l><d><!><
|
||||||
|
>^*
|
2
example/true.blang
Normal file
2
example/true.blang
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env blangfile
|
||||||
|
^*
|
52
src/blang.c
52
src/blang.c
@ -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
17
src/blang.h
Normal 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
112
src/ops.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user