Merge remote-tracking branch 'upstream/main' into d6/subprocess-feb2024

This commit is contained in:
~d6 2024-02-26 22:39:39 -05:00
commit b9e953a490
5 changed files with 111 additions and 24 deletions

BIN
boot.rom Normal file

Binary file not shown.

79
etc/coverage.tal Normal file
View File

@ -0,0 +1,79 @@
( test file )
|0100 @program
#01 ?{ ( skip ) #ffff }
!{ ( skip ) #ffff }
{ ( skip ) #ffff } POP2r
( nested lambda )
{ { "hello 0a $1 } STH2r !print-str } STH2r JSR2
( function application )
{ 01 02 03 04 05 } STH2r { LIT "0 ADD #18 DEO #0a18 DEO JMP2r } STH2r foreach
( get lambda length )
{ "Dindeldums $1 } STH2r get-lambda-length <print-dec> #0a18 DEO
( allocated string )
;hello-word print-str
#800f DEO
BRK
(
@| test label inheritance )
@Object &x $1 &y $1
&get-x ( -- x )
,&x LDR
JMP2r
@Object/get-y ( -- y )
,&y LDR
JMP2r
@Object/get-both ( -- x y )
/get-x /get-y
JMP2r
( raw lambda length )
_{ 01 02 03 }
@get-lambda-length ( lambda* -- length* )
#0002 SUB2 LDA2
JMP2r
@print-str ( str* -- )
&while ( -- )
( send ) LDAk #18 DEO
( loop ) INC2 LDAk ?&while
POP2
JMP2r
@foreach ( arr* fn* -- )
STH2
DUP2
DUP2 #0002 SUB2 LDA2 ADD2
SWP2
&l
LDAk STH2kr JSR2
INC2 NEQ2k ?&l
POP2 POP2 POP2r
JMP2r
@<print-dec> ( short* -- )
#2710 [ LIT2r 00fb ]
&w ( -- )
DIV2k #000a DIV2k MUL2 SUB2 SWPr EQUk OVR STHkr EQU AND ?&>skip
DUP [ LIT "0 ] ADD #19 DEO
INCr &>skip
POP2 #000a DIV2 SWPr INCr STHkr ?&w
POP2r POP2 POP2 JMP2r
$20 @label2
@hello-word "Hello 20 "World! 0a $1

View File

@ -5,28 +5,26 @@ EMU_src=${CLI_src} src/devices/screen.c src/devices/controller.c src/devices/mou
RELEASE_flags=-DNDEBUG -O2 -g0 -s RELEASE_flags=-DNDEBUG -O2 -g0 -s
DEBUG_flags=-std=c89 -D_POSIX_C_SOURCE=199309L -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined DEBUG_flags=-std=c89 -D_POSIX_C_SOURCE=199309L -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined
.PHONY: all debug dest rom run test install uninstall format clean .PHONY: all debug dest run test install uninstall format clean
all: dest bin/uxnasm bin/uxncli bin/uxn11 all: dest bin/uxnasm bin/uxncli bin/uxn11
dest: dest:
@ mkdir -p bin @ mkdir -p bin
rom: run: all bin/uxnasm bin/uxncli bin/uxn11
@ ./bin/uxnasm etc/screen.bounds.tal bin/res.rom @ ./bin/uxn11
run: all bin/uxnasm bin/uxncli bin/uxn11 rom
@ ./bin/uxn11 bin/res.rom
test: bin/uxnasm bin/uxncli bin/uxn11 test: bin/uxnasm bin/uxncli bin/uxn11
@ ./bin/uxnasm && ./bin/uxncli && ./bin/uxn11 && ./bin/uxnasm -v && ./bin/uxncli -v && ./bin/uxn11 -v @ ./bin/uxnasm -v && ./bin/uxncli -v && ./bin/uxn11 -v
@ ./bin/uxnasm etc/opctest.tal bin/opctest.rom @ ./bin/uxnasm etc/opctest.tal bin/opctest.rom
@ ./bin/uxncli bin/opctest.rom @ ./bin/uxncli bin/opctest.rom
install: bin/uxnasm bin/uxncli bin/uxn11 install: all bin/uxnasm bin/uxncli bin/uxn11
@ cp bin/uxn11 bin/uxnasm bin/uxncli ~/bin/ @ cp bin/uxn11 bin/uxnasm bin/uxncli ~/bin/
uninstall: uninstall:
@ rm -f ~/bin/uxn11 ~/bin/uxnasm ~/bin/uxncli @ rm -f ~/bin/uxn11 ~/bin/uxnasm ~/bin/uxncli
format: format:
@ clang-format -i src/uxnasm.c src/uxncli.c src/uxn11.c src/devices/* @ clang-format -i src/uxnasm.c src/uxncli.c src/uxn11.c src/devices/*
clean: clean:
@ rm -f bin/uxnasm bin/uxncli bin/uxn11 bin/polycat.rom bin/polycat.rom.sym @ rm -fr bin
bin/uxnasm: src/uxnasm.c bin/uxnasm: src/uxnasm.c
@ cc ${RELEASE_flags} ${CFLAGS} src/uxnasm.c -o bin/uxnasm @ cc ${RELEASE_flags} ${CFLAGS} src/uxnasm.c -o bin/uxnasm

View File

@ -296,16 +296,14 @@ main(int argc, char **argv)
{ {
Uxn u = {0}; Uxn u = {0};
int i = 1; int i = 1;
if(i == argc) { char *rom;
fprintf(stdout, "usage: %s [-v] file.rom [args..]\n", argv[0]); if(i != argc && argv[i][0] == '-' && argv[i][1] == 'v') {
return 0; fprintf(stdout, "Uxn11 - Varvara Emulator, 22 Feb 2023.\n");
}
if(argv[i][0] == '-' && argv[i][1] == 'v') {
fprintf(stdout, "Uxn11 - Varvara Emulator, 14 Feb 2023.\n");
i++; i++;
} }
if(!system_boot(&u, (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), argv[i++])) { rom = i == argc ? "boot.rom" : argv[i++];
fprintf(stdout, "Could not boot.\n"); if(!system_boot(&u, (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), rom)) {
fprintf(stdout, "usage: %s [-v] file.rom [args..]\n", argv[0]);
return 0; return 0;
} }
if(!display_init()) { if(!display_init()) {

View File

@ -55,6 +55,8 @@ static char ops[][4] = {
"ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT" "ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT"
}; };
static char *runes = "|$@&,_.-;=!?#\"%~";
static int scmp(char *a, char *b, int len) { int i = 0; while(a[i] == b[i]) if(!a[i] || ++i >= len) return 1; return 0; } /* string compare */ static int scmp(char *a, char *b, int len) { int i = 0; while(a[i] == b[i]) if(!a[i] || ++i >= len) return 1; return 0; } /* string compare */
static int sihx(char *s) { int i = 0; char c; while((c = s[i++])) if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f')) return 0; return i > 1; } /* string is hexadecimal */ static int sihx(char *s) { int i = 0; char c; while((c = s[i++])) if(!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f')) return 0; return i > 1; } /* string is hexadecimal */
static int shex(char *s) { int n = 0, i = 0; char c; while((c = s[i++])) if(c >= '0' && c <= '9') n = n * 16 + (c - '0'); else if(c >= 'a' && c <= 'f') n = n * 16 + 10 + (c - 'a'); return n; } /* string to num */ static int shex(char *s) { int n = 0, i = 0; char c; while((c = s[i++])) if(c >= '0' && c <= '9') n = n * 16 + (c - '0'); else if(c >= 'a' && c <= 'f') n = n * 16 + 10 + (c - 'a'); return n; } /* string to num */
@ -156,6 +158,15 @@ makemacro(char *name, FILE *f)
return 1; return 1;
} }
static int
isrune(char c)
{
char cc, *r = runes;
while((cc = *r++))
if(c == cc) return 1;
return 0;
}
static int static int
makelabel(char *name) makelabel(char *name)
{ {
@ -166,6 +177,8 @@ makelabel(char *name)
return error("Label name is hex number", name); return error("Label name is hex number", name);
if(findopcode(name) || scmp(name, "BRK", 4) || !slen(name)) if(findopcode(name) || scmp(name, "BRK", 4) || !slen(name))
return error("Label name is invalid", name); return error("Label name is invalid", name);
if(isrune(name[0]))
return error("Label name is runic", name);
if(p.label_len == 0x400) if(p.label_len == 0x400)
return error("Labels limit exceeded", name); return error("Labels limit exceeded", name);
l = &p.labels[p.label_len++]; l = &p.labels[p.label_len++];
@ -195,7 +208,7 @@ makereference(char *scope, char *label, char rune, Uint16 addr)
if(label[0] == '{') { if(label[0] == '{') {
p.lambda_stack[p.lambda_ptr++] = p.lambda_count; p.lambda_stack[p.lambda_ptr++] = p.lambda_count;
scpy(makelambda(p.lambda_count++), r->name, 0x40); scpy(makelambda(p.lambda_count++), r->name, 0x40);
} else if(label[0] == '&') { } else if(label[0] == '&' || label[0] == '/') {
if(!sublabel(subw, scope, label + 1)) if(!sublabel(subw, scope, label + 1))
return error("Invalid sublabel", label); return error("Invalid sublabel", label);
scpy(subw, r->name, 0x40); scpy(subw, r->name, 0x40);
@ -320,7 +333,10 @@ parse(char *w, FILE *f)
case '@': /* label */ case '@': /* label */
if(!makelabel(w + 1)) if(!makelabel(w + 1))
return error("Invalid label", w); return error("Invalid label", w);
scpy(w + 1, p.scope, 0x40); i = 0;
while(w[i + 1] != '/' && i < 0x3e && (p.scope[i] = w[i + 1]))
i++;
p.scope[i] = '\0';
break; break;
case '&': /* sublabel */ case '&': /* sublabel */
if(!sublabel(subw, p.scope, w + 1) || !makelabel(subw)) if(!sublabel(subw, p.scope, w + 1) || !makelabel(subw))
@ -346,7 +362,6 @@ parse(char *w, FILE *f)
case '.': /* literal byte zero-page */ case '.': /* literal byte zero-page */
makereference(p.scope, w + 1, w[0], p.ptr + 1); makereference(p.scope, w + 1, w[0], p.ptr + 1);
return writelitbyte(0xff); return writelitbyte(0xff);
case ':':
case '=': /* raw short absolute */ case '=': /* raw short absolute */
makereference(p.scope, w + 1, w[0], p.ptr); makereference(p.scope, w + 1, w[0], p.ptr);
return writeshort(0xffff, 0); return writeshort(0xffff, 0);
@ -420,7 +435,6 @@ resolve(void)
p.data[r->addr] = l->addr & 0xff; p.data[r->addr] = l->addr & 0xff;
l->refs++; l->refs++;
break; break;
case ':':
case '=': case '=':
case ';': case ';':
if(!(l = findlabel(r->name))) if(!(l = findlabel(r->name)))
@ -501,14 +515,12 @@ main(int argc, char *argv[])
if(argc == 1) if(argc == 1)
return error("usage", "uxnasm [-v] input.tal output.rom"); return error("usage", "uxnasm [-v] input.tal output.rom");
if(argv[1][0] == '-' && argv[1][1] == 'v') if(argv[1][0] == '-' && argv[1][1] == 'v')
return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 27 Oct 2023.\n"); return !fprintf(stdout, "Uxnasm - Uxntal Assembler, 25 Feb 2024.\n");
if(!(src = fopen(argv[1], "r"))) if(!(src = fopen(argv[1], "r")))
return !error("Invalid input", argv[1]); return !error("Invalid input", argv[1]);
if(!assemble(src)) if(!assemble(src))
return !error("Assembly", "Failed to assemble rom."); return !error("Assembly", "Failed to assemble rom.");
if(scmp(argv[2], "-", 2)) if(!(dst = fopen(argv[2], "wb")))
dst = stdout;
else if(!(dst = fopen(argv[2], "wb")))
return !error("Invalid Output", argv[2]); return !error("Invalid Output", argv[2]);
if(p.length <= TRIM) if(p.length <= TRIM)
return !error("Assembly", "Output rom is empty."); return !error("Assembly", "Output rom is empty.");