~pixelherodev/zyg

1862a2f466099857916fa9e9009edd9e6af01df5 — Noam Preil 5 months ago 7914dac
Bring in tune with c3lib
11 files changed, 93 insertions(+), 106 deletions(-)

M Makefile
M context.h
M driver.c
M lexer.c
M lexer.h
M parser.c
M parser.h
M queue.c
M sema.c
M test.bash -rw-r--r-- => -rwxr-xr-x
M test/broken
M Makefile => Makefile +1 -1
@@ 10,7 10,7 @@ zyg: driver.o parser.o lexer.o queue.o sema.o lib/z80e/cpu.o lib/z80e/log.o lib/
../lib/libc3.a: ../lib/*.c ../lib/codegen/*.c ../lib/sema/*.c
	$(MAKE) -C ../lib

driver.o lib/z80e/cpu.o lib/z80e/log.o lib/z80e/registers.o: EXTRA_CFLAGS := -Wno-pedantic
parser.o: EXTRA_CFLAGS := -Wno-sign-compare

%.o: %.c *.h
	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -DMACHINE=$(shell uname -m) -c $< -o $@

M context.h => context.h +1 -1
@@ 1,6 1,6 @@
struct pathed_tire{
	char *path;
	struct c3tree *tree;
	c3ctx *tree;
};

struct context {

M driver.c => driver.c +10 -12
@@ 16,6 16,11 @@
#include <fcntl.h>
#endif

#include "c3/tags.h"
#include "c3/c3.h"
#include "c3/util.h"
#include "c3/stb.h"

#include "lib/z80e/cpu.h"

#include "package.h"


@@ 23,11 28,6 @@
#include "parser.h"
#include "queue.h"

#include "c3/tags.h"
#include "c3/tree.h"
#include "c3/util.h"
#include "c3/stb.h"

struct context zyg_ctx;

static void


@@ 153,9 153,9 @@ context_validate(void)
	}
}

int codegen_z80(struct c3tree tree, FILE *);
int codegen_c(struct c3tree tree, FILE *);
int codegen_arm64(struct c3tree tree, FILE *);
int codegen_z80(c3ctx tree, FILE *);
int codegen_c(c3ctx tree, FILE *);
int codegen_arm64(c3ctx tree, FILE *);

static void
context_free(void)


@@ 335,7 335,8 @@ tests(void)
	if(f == NULL)
		FATAL_EXIT("Failed to open test binary", 0);
	cpu->memory = calloc(65536, 1);
	if(fread(&((char*)cpu->memory)[0x20], 1, 65536 - 0x20, f) < 0)
	fread(&((char*)cpu->memory)[0x20], 1, 65536 - 0x20, f);
	if(ferror(f))
		FATAL_EXIT("failed to read test binary", 0);
	fclose(f);
	cpu->read_byte = cpu_read;


@@ 386,9 387,6 @@ main(int argc, char **argv)
		printf("%s\nAnalysed:\n%s\n", eqn, eqn);
		for(size_t i = 0; i < stb_sb_count(zyg_ctx.trees); i += 1){
	    		c3dump(*zyg_ctx.trees[i].tree);
				printf("\n");
				c3nodedump(*zyg_ctx.trees[i].tree, zyg_ctx.trees[i].tree->graphs.deps, 1, 1);
				printf("\nNote: the call graph is not dumped at present, as infinite recursion is not yet detected\n");
		}
	}
	if(zyg_ctx.tests)

M lexer.c => lexer.c +3 -3
@@ 8,7 8,7 @@
#include <limits.h>

#include "c3/tags.h"
#include "c3/tree.h"
#include "c3/c3.h"
#include "c3/util.h"
#include "c3/stb.h"



@@ 23,7 23,7 @@ static struct {
		char *buf;
		char *path;
	} file;
	struct c3tree tree;
	c3ctx tree;
	struct {
		char *ptr;
		uint32_t len;


@@ 336,7 336,7 @@ lexer_append(void)
//	if(ctx.token.tag != C3_WHILE && ctx.token.tag != C3_RBRACE && ctx.token.tag != C3_TRUE && ctx.token.tag != C3_LBRACE && ctx.token.tag != C3_LPAREN && ctx.token.tag != C3_RPAREN){
	if(ctx.token.tag == C3_IDENT || ctx.token.tag == C3_LITERAL_STRING || ctx.token.tag == C3_LINT){
		handle = c3intern(&ctx.tree, ctx.token.ptr, ctx.token.len);
		if(handle == -1)
		if(handle == UINT32_MAX)
			OOM();
	}
	if(!stb_sb_push_u32(&ctx.tokens.strings, handle) || !stb_sb_push_u8(&ctx.tokens.tags, ctx.token.tag))

M lexer.h => lexer.h +1 -1
@@ 7,7 7,7 @@ struct zygtokens{

struct zyglexed{
	struct zygtokens tokens;
	struct c3tree tree;
	c3ctx tree;
}

zyg_lex(char *path);

M parser.c => parser.c +28 -42
@@ 6,7 6,7 @@
#include <stdio.h>

#include "c3/tags.h"
#include "c3/tree.h"
#include "c3/c3.h"
#include "c3/util.h"
#include "c3/stb.h"



@@ 28,13 28,12 @@
static struct {
	// The current index into the zig file's tokens
	size_t i;
	struct c3tree tree;
	c3ctx tree;
	struct zygtokens tokens;
	char *path;
	// This stores several lists for accelerated deduplication
	struct {
		uint32_t *values;
		uint32_t *types;
		uint32_t *ints;
		uint32_t *strs;
		uint32_t *idents;


@@ 55,23 54,21 @@ static uint32_t p_var_decl(void);
static void
parser_init(char *path)
{
	struct zyglexed lexed = zyg_lex(path);
	ctx.path = path;
	ctx.accel.types = NULL;
	ctx.tree = lexed.tree;
	ctx.tokens = lexed.tokens;
	ctx.accel.values = NULL;
	ctx.accel.ints = NULL;
	ctx.accel.strs = NULL;
	ctx.accel.idents = NULL;
	ctx.accel.misc = NULL;
	struct zyglexed lexed = zyg_lex(path);
	ctx.tree = lexed.tree;
	ctx.tokens = lexed.tokens;
	ctx.accel.token_count = stb_sb_count(ctx.tokens.tags);
}

static void
parser_cleanup(void)
{
	stb_sb_free(ctx.accel.types);
	stb_sb_free(ctx.accel.values);
	stb_sb_free(ctx.accel.ints);
	stb_sb_free(ctx.accel.strs);


@@ 240,7 237,7 @@ p_return(void)
{
	uint32_t operand;
	if(parser_is(1, C3_SCOLON))
		operand = parser_dedup_node_tag(&ctx.accel.types, C3_VOID);
		operand = parser_dedup_node_tag(&ctx.tree.dedup.types, C3_VOID);
	else{
		parser_advance();
		operand = p_expr();


@@ 475,10 472,10 @@ p_prefix_expr(void)
			deepest = prefix_root;
		}
		else{
			ctx.tree.nodes[deepest + 1] = c3append(&ctx.tree, prefix, 1, -1);
			if(ctx.tree.nodes[deepest + 1] == -1)
			ctx.tree.ast.nodes[deepest + 1].node_index = c3append(&ctx.tree, prefix, 1, -1);
			if(ctx.tree.ast.nodes[deepest + 1].node_index == -1)
				FATAL("ICE: OOM", 0);
			deepest = ctx.tree.nodes[deepest + 1];
			deepest = ctx.tree.ast.nodes[deepest + 1].node_index;
		}
		prefix = p_prefixops();
	}


@@ 486,7 483,7 @@ p_prefix_expr(void)
	if(primary == -1)
		FATAL("Failed to read primary expr", 0);
	if(prefix_root != -1){
		ctx.tree.nodes[deepest + 2] = primary;
		ctx.tree.ast.nodes[deepest + 2].node_index = primary;
		return prefix_root;
	}
	return primary;


@@ 622,15 619,15 @@ p_import(void)
	// zyg-specific node for them
	uint32_t ident;
	uint32_t index;
	struct c3string string;
	c3string string;
	char *buf;
	parser_advance();
	EXPECT(C3_LPAREN, "Expected lparen in @import!", 0);
	parser_advance();
	EXPECT(C3_LITERAL_STRING, "Expected string literal in @import!", 0);
	ident = ctx.tokens.strings[ctx.i];
	string = ctx.tree.strings[ident];
	buf = file_rel_dir(ctx.path, &ctx.tree.chars[string.index], string.length, NULL);
	string = ctx.tree.core.strings[ident];
	buf = file_rel_dir(ctx.path, &ctx.tree.core.chars[string.index], string.length, NULL);
	queue_job(buf);
	free(buf);
	parser_advance();


@@ 696,7 693,7 @@ p_block(void)
	uint32_t index;
	uint32_t kid;
	kids = NULL;
	kid = parser_dedup_node_tag(&ctx.accel.types, C3_TYPE_UNRES);
	kid = parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE_UNRES);
	if(!stb_sb_push_u32(&kids, kid))
		return -1;
	EXPECT(C3_LBRACE, "Expected lbrace to open block, found '%s'", c3tagstr(ctx.tokens.tags[ctx.i]));


@@ 902,15 899,15 @@ p_primary_type_expr(void)
	if(parser_is(0, C3_KEYWORD_NULL))
		return parser_dedup_node_tag(&ctx.accel.values, C3_VALUE_NULL);
	if(parser_is(0, C3_NORETURN))
		return parser_dedup_node_tag(&ctx.accel.types, C3_NORETURN);
		return parser_dedup_node_tag(&ctx.tree.dedup.types, C3_NORETURN);
	if(parser_is(0, C3_VOID))
		return parser_dedup_node_tag(&ctx.accel.types, C3_VOID);
		return parser_dedup_node_tag(&ctx.tree.dedup.types, C3_VOID);
	if(parser_is(0, C3_TYPE_BOOL))
		return parser_dedup_node_tag(&ctx.accel.types, C3_TYPE_BOOL);
		return parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE_BOOL);
	if(parser_is(0, C3_TYPE_U8))
		return parser_dedup_node_tag(&ctx.accel.types, C3_TYPE_U8);
		return parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE_U8);
	if(parser_is(0, C3_TYPE_U32))
		return parser_dedup_node_tag(&ctx.accel.types, C3_TYPE_U32);
		return parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE_U32);
	if(parser_is(0, C3_DISCARD))
		return parser_dedup_node_tag(&ctx.accel.misc, C3_DISCARD);
	if(parser_is(0, C3_IMPORT))


@@ 920,11 917,11 @@ p_primary_type_expr(void)
		return c3append(&ctx.tree, C3_BUILTIN_PANIC, 1, p_fncall_args());
	}
	if(parser_is(0, C3_BUILTIN_THIS))
		return parser_dedup_node_tag(&ctx.accel.types, C3_BUILTIN_THIS);
		return parser_dedup_node_tag(&ctx.tree.dedup.types, C3_BUILTIN_THIS);
	if(parser_is(0, C3_STRUCT))
		return p_struct();
	if(parser_is(0, C3_TYPE))
		return parser_dedup_node_tag(&ctx.accel.types, C3_TYPE);
		return parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE);
	if(parser_is(0, C3_ENUM))
		return p_enum();
	if(parser_is(0, C3_LINT))


@@ 1056,7 1053,7 @@ p_param_decl(void)
	if(ident == 0)
		ERROR("no ident, tag %s",c3tagstr(ctx.tokens.tags[ctx.i]));
	if(parser_is(0, C3_ANYTYPE))
		type = parser_dedup_node_tag(&ctx.accel.types, C3_ANYTYPE);
		type = parser_dedup_node_tag(&ctx.tree.dedup.types, C3_ANYTYPE);
	else if(parser_is(0, C3_DOT)){
		ERROR("TODO: extern varargs", 0);
		return -1;


@@ 1143,7 1140,7 @@ p_fnproto(void)
	}
	infer = parser_is_consume(C3_EXCLAIM);
	if(parser_is(0, C3_ANYTYPE))
		ret_type = parser_dedup_node_tag(&ctx.accel.types, C3_TYPE_UNRES);
		ret_type = parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE_UNRES);
	else
		ret_type = p_type_expr();
	if(ret_type == -1){


@@ 1235,7 1232,7 @@ p_var_decl(void)
	EXPECT(C3_IDENT, "Expected identifier in vardecl, found '%s'!", c3tagstr(ctx.tokens.tags[ctx.i]));
	ident = p_ident();
	parser_advance();
	type = parser_dedup_node_tag(&ctx.accel.types, C3_TYPE_UNRES);
	type = parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE_UNRES);
	value = parser_dedup_node_tag(&ctx.accel.values, C3_VALUE_UNDEF);
	if(parser_is(0, C3_COLON)){
		parser_advance();


@@ 1256,7 1253,7 @@ p_var_decl(void)
			return -1;
		}
		if(c3nodetag(ctx.tree, value) == C3_VALUE_FN)
			ctx.tree.nodes[value + 1 + 2] = ident;
			ctx.tree.ast.nodes[value + 1 + 2].node_index = ident;
		parser_advance();
	}
	EXPECT(C3_SCOLON, "Expected semicolon to end vardecl, found '%s'",c3tagstr(ctx.tokens.tags[ctx.i]));


@@ 1305,7 1302,7 @@ p_container_field(void)
	if(!parser_is(0, C3_IDENT))
		FATAL("Expected ident for container field", 0);
	ident = p_ident();
	type = parser_dedup_node_tag(&ctx.accel.types, C3_TYPE_UNRES);
	type = parser_dedup_node_tag(&ctx.tree.dedup.types, C3_TYPE_UNRES);
	value = parser_dedup_node_tag(&ctx.accel.values, C3_VALUE_UNDEF);
	if(parser_is(1, C3_COLON)){
		parser_advance();


@@ 1357,15 1354,6 @@ p_tl(void)
}

static int
parser_gen_types(void)
{
	ctx.tree.graphs.type = c3appendarr(&ctx.tree, C3_CONTEXTUAL, stb_sb_count(ctx.accel.types), ctx.accel.types);
	if(ctx.tree.graphs.type == -1)
		OOM();
	return 1;
}

static int
parser_main(void)
{
	uint32_t index;


@@ 1387,14 1375,12 @@ parser_main(void)
	if(root == -1)
		OOM();
	stb_sb_free(kids);
	ctx.tree.nodes[1] = root;
	if(!parser_gen_types())
		return 0;
	ctx.tree.ast.nodes[1].node_index = root;
	return root != -1;
}

int
parse(char *path, struct c3tree *tree)
parse(char *path, c3ctx *tree)
{
	int ret;
	parser_init(path);

M parser.h => parser.h +1 -1
@@ 1,1 1,1 @@
int parse(char *path, struct c3tree *tree);
int parse(char *path, c3ctx *tree);

M queue.c => queue.c +17 -15
@@ 11,16 11,16 @@
#include <sys/wait.h>
#include <sys/select.h>

#include "c3/util.h"
#include "c3/stb.h"
#include "c3/tags.h"
#include "c3/c3.h"

#include "package.h"
#include "context.h"
#include "queue.h"
#include "parser.h"

#include "c3/util.h"
#include "c3/stb.h"
#include "c3/tags.h"
#include "c3/tree.h"

struct job {
	enum {
		QUEUE_UNSTARTED,


@@ 67,10 67,12 @@ queue_find_tire(char *path)
int
queue_job_parent(char *path)
{
	size_t len;
	ssize_t len;
	char buf[2];
	buf[0] = 0;
	len = strlen(path);
	if(len > 0xFFFF)
		FATAL("string too long", 0);
	if(write(state.in_child, buf, 1) != 1)
		FATAL("Failed to write import message type", 0);
	buf[0] = len & 0xFF;


@@ 96,7 98,7 @@ queue_job(char *path)
	i = queue_find_tire(path);
	if(state.mode == QUEUE_PARSER){
		// Don't duplicate job in queue
		if(i != -1){
		if(i != UINT32_MAX){
			free(path);
			return 1;
		}


@@ 112,7 114,7 @@ queue_job(char *path)
		stb_sb_increment(state.ctx->trees, 1);
	}
	if(state.mode == QUEUE_ANALYSIS){
		if(i == -1){
		if(i == UINT32_MAX){
			ERROR("Unable to find '%s' parsetree", path);
			free(path);
			return 0;


@@ 140,7 142,7 @@ queue_get_next(void)
void
job_parse(struct job *job, struct pathed_tire *p)
{
	p->tree = malloc(sizeof(struct c3tree));
	p->tree = malloc(sizeof(c3ctx));
	if(p->tree == NULL){
		ERROR("Out of memory", 0);
		job->state = QUEUE_FAILED;


@@ 156,7 158,7 @@ job_parse(struct job *job, struct pathed_tire *p)
	job->state = QUEUE_SUCCESS;
}

int analysis(struct c3tree *tree, int out);
int analysis(c3ctx *tree, int out);

void
job_analyze(struct job *job, struct pathed_tire *p)


@@ 170,7 172,7 @@ void
queue_parser_child(char *path, int out)
{
	char c = 1;
	struct c3tree tree;
	c3ctx tree;
	if(!parse(path, &tree))
		FATAL("Parsing of '%s' failed",path);
	if(write(out, &c, 1) != 1)


@@ 255,7 257,7 @@ queue_fail(struct job *job, char *msg)
}

int
read_or_kill(struct job *job, char *buf, size_t len)
read_or_kill(struct job *job, char *buf, ssize_t len)
{
	if(read(job->in, buf, len) != len){
		queue_fail(job, "Failed to read pipe");


@@ 303,7 305,7 @@ queue_handle_tire(struct job *job)
	p = &state.ctx->trees[job->index];
	if(p->tree)
		c3free(p->tree);
	p->tree = malloc(sizeof(struct c3tree));
	p->tree = malloc(sizeof(c3ctx));
	if(p->tree == NULL){
		queue_fail(job, "Out of memory");
		return;


@@ 442,11 444,11 @@ queue_wait(void)
	s.tv_sec = 0;
	s.tv_nsec = 10000;
	i = queue_get_next();
	while(i != -1 || queue_active() > 0){
	while(i != UINT32_MAX || queue_active() > 0){
		if(state.ctx->single_process)
			queue_execute(&state.jobs[i]);
		else{
			if(queue_active() < 4 && i != -1)
			if(queue_active() < 4 && i != UINT32_MAX)
				queue_process(&state.jobs[i]);
			queue_handle_death();
			queue_handle_input_all();

M sema.c => sema.c +30 -30
@@ 4,53 4,53 @@
#include <stdlib.h>

#include "c3/tags.h"
#include "c3/tree.h"
#include "c3/c3.h"
#include "c3/util.h"
#include "c3/sema/scope.h"
#include "c3/stb_ds.h"

#include "package.h"
#include "context.h"

int resolve_tree(struct c3tree *);
int serialize_deps(struct c3tree *);
int resolve_tree(c3ctx *);
int serialize_deps(c3ctx *);
// needs to be able to patch the source...
int t_init(struct c3tree *);
int t_init(c3ctx *);
int t_node(uint32_t source);
int expr_init(struct c3tree *);
int expr_init(c3ctx *);
uint32_t l_fn(uint32_t index);
int expr_finish(void);
int expr_gen_test(void);

static void
usagedump(struct c3tree tree)
usagedump(c3ctx c3)
{
	uint32_t i;
	uint32_t dep_node;
	uint16_t kids = c3nodekids(tree, tree.graphs.deps);
	uint32_t kids = stbds_hmlenu(c3.analysis.deps);
	for(i = 0; i < kids; i += 1){
		dep_node = c3nodechild(tree, tree.graphs.deps, i);
		dep_node = c3.analysis.deps[i].value;
		printf("%d: %u: ", i, dep_node);
		c3nodedump(tree, dep_node, 0, 1);
		c3nodedump(c3, dep_node, 0, 1);
		printf("\n");
	}
}

static int
anal_execute(struct c3tree *tree)
anal_execute(c3ctx *c3)
{
	uint32_t i;
	uint32_t dep_node, t;
	uint16_t kids = c3nodekids(*tree, tree->graphs.deps);
	uint32_t t;
	uint16_t kids = stbds_hmlenu(c3->analysis.deps);
	for(i = 0; i < kids; i += 1){
		t = c3nodechild(*tree, tree->graphs.deps, i);
		dep_node = c3nodechild(*tree, t, 0);
		t = c3->analysis.deps[i].key;
		// TODO: comptime engine
		if(!t_node(dep_node)){
		if(!t_node(t)){
			ERROR("Type analysis failed!", 0);
			return 0;
		}
		if(c3nodetag(*tree, dep_node) == C3_VALUE_FN){
			if(l_fn(dep_node) == -1){
		if(c3nodetag(*c3, t) == C3_VALUE_FN){
			if(l_fn(t) == UINT32_MAX){
				ERROR("Failed to extract expression semantics", 0);
				return 0;
			}


@@ 60,7 60,7 @@ anal_execute(struct c3tree *tree)
}

static int
anal_finish(struct c3tree *tree, int good, int out)
anal_finish(c3ctx *c3, int good, int out)
{
	char c = 1;
	if(good && !expr_finish())


@@ 70,40 70,40 @@ anal_finish(struct c3tree *tree, int good, int out)
	if(out == -1)
		return 1;
	if(write(out, &c, 1) != 1){
		ERROR("Failed to write tree message type", 0);
		ERROR("Failed to write c3 message type", 0);
		return 0;
	}
	if(!c3write(tree, out)){
		ERROR("Failed to send tree to parent", 0);
	if(!c3write(c3, out)){
		ERROR("Failed to send c3 to parent", 0);
		return 0;
	}
	return 1;
}

int
analysis(struct c3tree *tree, int out)
analysis(c3ctx *c3, int out)
{
	int good;
	if(!t_init(tree))
	if(!t_init(c3))
		return 0;
	if(!expr_init(tree))
	if(!expr_init(c3))
		return 0;
	if(!resolve_tree(tree)){
	if(!resolve_tree(c3)){
		ERROR("Tree resolution failed!", 0);
		return 0;
	}
	scope_free();
	if(tree->graphs.deps == -1){
	if(c3->analysis.deps == NULL){
		ERROR("ICE: dependency graph not found, old analysis is gone!", 0);
		return 0;
	}
	if(zyg_ctx.tests)
		if(!expr_gen_test())
			return 0;
	if(!serialize_deps(tree))
	if(!serialize_deps(c3))
		return 0;
	if(zyg_ctx.usage_debug)
		usagedump(*tree);
	good = anal_execute(tree);
	return anal_finish(tree, good, out);
		usagedump(*c3);
	good = anal_execute(c3);
	return anal_finish(c3, good, out);
}

M test.bash => test.bash +0 -0
M test/broken => test/broken +1 -0
@@ 3,3 3,4 @@ comptime/recursive_wrap
rk9/8
arithmetic
test_failing
tl_comptime