diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-10-19 21:43:48 +0300 | 
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-10-23 18:25:23 +0300 | 
| commit | e3bb9a4ddc0465d4a75ca64e36416a9568c74d27 (patch) | |
| tree | 2a0281b4885f49ad92a4e5acfe4c28fa88a24129 /src | |
| parent | 7c5f098511b8f612a17f4ccdd8a4924c325d37e1 (diff) | |
| download | lyn-e3bb9a4ddc0465d4a75ca64e36416a9568c74d27.tar.gz lyn-e3bb9a4ddc0465d4a75ca64e36416a9568c74d27.zip | |
some basic programs run
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast.c | 55 | ||||
| -rw-r--r-- | src/lyn.c | 333 | ||||
| -rw-r--r-- | src/main.c | 6 | ||||
| -rw-r--r-- | src/parser.y | 30 | ||||
| -rw-r--r-- | src/vec.c | 67 | 
5 files changed, 438 insertions, 53 deletions
| @@ -1,53 +1,44 @@  #include <stdio.h>  #include <lyn/ast.h> -struct ast *reverse_ast_list(struct ast *root) -{ -	struct ast *new_root = NULL; -	while (root) { -		struct ast *next = root->next; -		root->next = new_root; -		new_root = root; -		root = next; -	} - -	return new_root; -} -  #define dump(depth, fmt, ...)                   \  	do {                                    \  		printf("//%*s", 2 * depth, ""); \  		printf(fmt,##__VA_ARGS__);      \  	} while (0) -void ast_dump(int depth, struct ast *ast) +void ast_dump(int depth, struct lyn_value val)  { -	switch (ast->kind) { -	case LYN_ID: dump(depth, "%s\n", ast->s); return; -	case LYN_STR: dump(depth, "\"%s\"\n", ast->s); return; -	case LYN_INT: dump(depth, "%lld\n", ast->i); return; -	case LYN_FLOAT: dump(depth, "%f\n", ast->d); return; +	switch (val.kind) { +	case LYN_ID: dump(depth, "%s\n", val.s); return; +	case LYN_STR: dump(depth, "\"%s\"\n", val.s); return; +	case LYN_INT: dump(depth, "%lld\n", val.i); return; +	case LYN_FLOAT: dump(depth, "%f\n", val.d); return;  	case LYN_CMD:  			dump(depth, "CMD\n"); -			ast_dump_list(depth + 1, ast->args); -			return; +			foreach_vec(ci, val.args) { +				struct lyn_value v = vect_at(struct lyn_value, val.args, ci); +				ast_dump(depth + 1, v); +			} -	case LYN_LIST: -			dump(depth, "LIST\n"); -			ast_dump_list(depth + 1, ast->args);  			return;  	case LYN_APPLY:  			dump(depth, "APPLY\n"); -			ast_dump_list(depth + 1, ast->args); +			foreach_vec(ai, val.args) { +				struct lyn_value v = vect_at(struct lyn_value, val.args, ai); +				ast_dump(depth + 1, v); +			}  			return; -	} -} -void ast_dump_list(int depth, struct ast *ast) -{ -	while (ast) { -		ast_dump(depth, ast); -		ast = ast->next; +	case LYN_GROUP: +			dump(depth, "GROUP\n"); +			foreach_vec(gi, val.args) { +				struct lyn_value v = vect_at(struct lyn_value, val.args, gi); +				ast_dump(depth + 1, v); +			} +			return; + +	default: abort();  	}  } @@ -1,4 +1,5 @@  #include <errno.h> +#include <assert.h>  #include <stdbool.h>  #include <string.h>  #include <stdio.h> @@ -6,14 +7,326 @@  #include <stdlib.h>  #include <lyn/lyn.h> +#include <lyn/ast.h>  #include <lyn/parser.h>  #include <lyn/debug.h> +static int builtin_let(struct lyn *lyn, struct vec args) +{ +	assert(vec_len(&args) == 3); + +	struct lyn_value name = lyn_at(args, 1); +	assert(name.kind == LYN_ID); + +	struct lyn_value value = lyn_at(args, 2); +	if (lyn_eval(lyn, value)) +		return -1; + +	value = lyn_res(lyn); +	assert(value.kind == LYN_INT); + +	return lyn_create_symbol(lyn, name.s, lyn_var(value)); +} + +static int builtin_set(struct lyn *lyn, struct vec args) +{ +	assert(vec_len(&args) == 3); + +	struct lyn_value name = lyn_at(args, 1); +	assert(name.kind == LYN_ID); + +	struct lyn_value value = lyn_at(args, 2); +	if (lyn_eval(lyn, value)) +		return -1; + +	value = lyn_res(lyn); +	assert(value.kind == LYN_INT); + +	return lyn_replace_symbol(lyn, name.s, lyn_var(value)); +} + +static int builtin_for(struct lyn *lyn, struct vec args) +{ +	assert(vec_len(&args) == 5); + +	struct lyn_value init = lyn_at(args, 1); +	struct lyn_value cond = lyn_at(args, 2); +	struct lyn_value post = lyn_at(args, 3); +	struct lyn_value body = lyn_at(args, 4); + +	if (lyn_eval(lyn, init)) +		return -1; + +top: +	if (lyn_eval(lyn, cond)) +		return -1; + +	struct lyn_value check = lyn_res(lyn); +	assert(check.kind == LYN_INT); + +	if (check.i) { +		if (lyn_eval(lyn, body)) +			return -1; + +		if (lyn_eval(lyn, post)) +			return -1; + +		goto top; +	} + +	return 0; +} + +static int builtin_println(struct lyn *lyn, struct vec args) +{ +	assert(vec_len(&args) == 2); + +	struct lyn_value value = lyn_at(args, 1); +	if (lyn_eval(lyn, value)) +		return -1; + +	value = lyn_res(lyn); +	assert(value.kind == LYN_INT); + +	printf("%lld\n", value.i); +	return 0; +} + +static int builtin_lt(struct lyn *lyn, struct vec args) +{ +	assert(vec_len(&args) == 3); +	struct lyn_value left = lyn_at(args, 1); +	struct lyn_value right = lyn_at(args, 2); + +	if (lyn_eval(lyn, left)) +		return -1; + +	left = lyn_res(lyn); +	assert(left.kind == LYN_INT); + +	if (lyn_eval(lyn, right)) +		return -1; + +	right = lyn_res(lyn); +	assert(right.kind == LYN_INT); + +	lyn_return(lyn, gen_int(left.i < right.i)); +	return 0; +} + +static int builtin_plus(struct lyn *lyn, struct vec args) +{ +	assert(vec_len(&args) == 3); +	struct lyn_value left = lyn_at(args, 1); +	struct lyn_value right = lyn_at(args, 2); + +	if (lyn_eval(lyn, left)) +		return -1; + +	left = lyn_res(lyn); +	assert(left.kind == LYN_INT); + +	if (lyn_eval(lyn, right)) +		return -1; + +	right = lyn_res(lyn); +	assert(right.kind == LYN_INT); + +	lyn_return(lyn, gen_int(left.i + right.i)); +	return 0; +} +  struct lyn lyn_create()  {  	return (struct lyn){};  } +struct visible { +	const char *name; +	struct lyn_symbol symb; +}; + +int lyn_create_scope(struct lyn *lyn) +{ +	struct lyn_scope *scope = calloc(1, sizeof(struct lyn_scope)); +	if (!scope) +		return -1; + +	scope->visible = vec_create(sizeof(struct visible)); +	scope->parent = lyn->cur; + +	if (!lyn->root) +		lyn->root = scope; + +	lyn->cur = scope; +	return 0; +} + +static struct visible *scope_find(struct lyn_scope *scope, const char *name) +{ +	foreach_vec(vi, scope->visible) { +		struct visible *v = vec_at(&scope->visible, vi); +		if (strcmp(v->name, name) == 0) +			return v; +	} + +	return NULL; +} + +static struct visible *scopes_find(struct lyn_scope *scope, const char *name) +{ +	while (scope) { +		struct visible *v = scope_find(scope, name); +		if (v) +			return v; + +		scope = scope->parent; +	} + +	return NULL; +} + +static int scope_add(struct lyn_scope *scope, const char *name, struct lyn_symbol symb) +{ +	if (scope_find(scope, name)) { +		error("%s exists in scope\n", name); +		return -1; +	} + +	struct visible v = {.name = name, .symb = symb}; +	vect_append(struct visible, scope->visible, &v); +	return 0; +} + +int lyn_create_symbol(struct lyn *lyn, const char *name, struct lyn_symbol symb) +{ +	return scope_add(lyn->cur, name, symb); +} + +struct lyn_symbol *lyn_lookup_symbol(struct lyn *lyn, const char *name) +{ +	struct visible *v = scopes_find(lyn->cur, name); +	if (!v) +		return NULL; + +	return &v->symb; +} + +int lyn_replace_symbol(struct lyn *lyn, const char *name, struct lyn_symbol symb) +{ +	struct visible *v = scopes_find(lyn->cur, name); +	if (!v) +		return -1; + +	v->symb = symb; +	return 0; +} + +int lyn_init(struct lyn *lyn) +{ +	if (lyn_create_scope(lyn)) +		return -1; + +	if (lyn_create_symbol(lyn, "let", lyn_syntax(builtin_let))) +		return -1; + +	if (lyn_create_symbol(lyn, "for", lyn_syntax(builtin_for))) +		return -1; + +	if (lyn_create_symbol(lyn, "set", lyn_syntax(builtin_set))) +		return -1; + +	if (lyn_create_symbol(lyn, "println", lyn_proc(builtin_println))) +		return -1; + +	if (lyn_create_symbol(lyn, "<", lyn_proc(builtin_lt))) +		return -1; + +	if (lyn_create_symbol(lyn, "+", lyn_proc(builtin_plus))) +		return -1; + +	return 0; +} + +static int eval_group(struct lyn *lyn, struct lyn_value group) +{ +	assert(group.kind == LYN_GROUP); +	foreach_vec(gi, group.args) { +		struct lyn_value arg = lyn_at(group.args, gi); +		if (lyn_eval(lyn, arg)) +			return -1; +	} + +	return 0; +} + +static int eval_apply(struct lyn *lyn, struct lyn_value apply) +{ +	assert(apply.kind == LYN_APPLY); +	foreach_vec(ai, apply.args) { +		struct lyn_value arg = lyn_at(apply.args, ai); +		if (lyn_eval(lyn, arg)) +			return -1; +	} + +	return 0; +} + +int lyn_apply_cmd(struct lyn *lyn, struct lyn_symbol *cmd, struct vec args) +{ +	switch (cmd->kind) { +	case LYN_BUILTIN_SYNTAX: return cmd->call(lyn, args); +	case LYN_BUILTIN_PROC: return cmd->call(lyn, args); +	default: abort(); +	} + +	return 0; +} + +static int eval_cmd(struct lyn *lyn, struct lyn_value cmd) +{ +	assert(cmd.kind == LYN_CMD); + +	struct lyn_value name = lyn_at(cmd.args, 0); + +	/* to start with */ +	struct lyn_symbol *symb = lyn_lookup_symbol(lyn, name.s); +	assert(symb); + +	return lyn_apply_cmd(lyn, symb, cmd.args); +} + +static int eval_int(struct lyn *lyn, struct lyn_value i) +{ +	assert(i.kind == LYN_INT); +	lyn_return(lyn, i); +	return 0; +} + +static int eval_id(struct lyn *lyn, struct lyn_value id) +{ +	assert(id.kind == LYN_ID); +	struct lyn_symbol *symb = lyn_lookup_symbol(lyn, id.s); +	assert(symb && symb->kind == LYN_VAR); + +	lyn_return(lyn, symb->value); +	return 0; +} + +int lyn_eval(struct lyn *lyn, struct lyn_value value) +{ +	switch (value.kind) { +	case LYN_GROUP: return eval_group(lyn, value); +	case LYN_APPLY: return eval_apply(lyn, value); +	case LYN_CMD: return eval_cmd(lyn, value); +	case LYN_INT: return eval_int(lyn, value); +	case LYN_ID: return eval_id(lyn, value); +	default: error("unhandled case in interp eval"); break; +	} + +	return -1; +} +  int lyn_eval_str(struct lyn *lyn, const char *name, const char *str)  {  	struct parser *p = create_parser(); @@ -21,15 +334,15 @@ int lyn_eval_str(struct lyn *lyn, const char *name, const char *str)  		return -1;  	parse(p, name, str); -	struct ast *ast = p->tree; +	struct lyn_value ast = p->tree;  	bool failed = p->failed;  	destroy_parser(p); -	if (!failed) { -		ast_dump_list(0, ast); -	} +	if (failed) +		return -1; -	return failed; +	ast_dump(0, ast); +	return lyn_eval(lyn, ast);  }  /** @@ -84,6 +397,16 @@ int lyn_eval_file(struct lyn *lyn, const char *fname)  	return ret;  } +void lyn_return(struct lyn *lyn, struct lyn_value ast) +{ +	lyn->res = ast; +} + +struct lyn_value lyn_res(struct lyn *lyn) +{ +	return lyn->res; +} +  void lyn_destroy(struct lyn *lyn)  {  } @@ -9,8 +9,12 @@ int main(int argc, char *argv[])  	}  	struct lyn lyn = lyn_create(); +	if (lyn_init(&lyn)) { +		lyn_destroy(&lyn); +		return -1; +	} +  	int ret = lyn_eval_file(&lyn, argv[1]);  	lyn_destroy(&lyn); -  	return ret;  } diff --git a/src/parser.y b/src/parser.y index 3e0156f..742bc5f 100644 --- a/src/parser.y +++ b/src/parser.y @@ -29,7 +29,7 @@  %parse-param {void *scanner} {struct parser* parser}  %union { -	struct ast *ast; +	struct lyn_value ast;  	char *str;  	long long integer;  	double floating; @@ -128,19 +128,19 @@ static char *strip(const char *s);  %%  arg -	: "(" cmds ")" {$$ = gen_apply($2);} -	| "{" cmds "}" {$$ = gen_list($2);} +	: "(" cmds ")" {$$ = $2; $$.kind = LYN_APPLY;} +	| "{" cmds "}" {$$ = $2; $$.kind = LYN_GROUP;}  	| ID {$$ = gen_id($1);}  	| STRING {$$ = gen_str($1);}  	| INT {$$ = gen_int($1);}  	| FLOAT {$$ = gen_float($1);}  rev_args -	: rev_args arg {$$ = $2; $$->next = $1;} -	| arg +	: rev_args arg {$$ = $1; vect_append(struct lyn_value, $$.args, &$2);} +	| arg {$$ = gen_list(); vect_append(struct lyn_value, $$.args, &$1);}  args -	: rev_args {$$ = reverse_ast_list($1);} +	: rev_args  sep  	: sep ";" @@ -149,21 +149,21 @@ sep  	| NL  cmd -	: args {$$ = gen_cmd($1);} +	: args {$$ = $1; $$.kind = LYN_CMD;}  rev_cmds -	: rev_cmds sep cmd {$$ = $3; $$->next = $1;} -	| cmd +	: rev_cmds sep cmd {$$ = $1; vect_append(struct lyn_value, $$.args, &$3);} +	| cmd {$$ = gen_list(); vect_append(struct lyn_value, $$.args, &$1);}  cmds -	: rev_cmds {$$ = reverse_ast_list($1);} -	| rev_cmds sep {$$ = reverse_ast_list($1);} -	| sep rev_cmds {$$ = reverse_ast_list($2);} -	| sep rev_cmds sep {$$ = reverse_ast_list($2);} -	| {$$ = NULL;} +	: rev_cmds +	| rev_cmds sep +	| sep rev_cmds {$$ = $2;} +	| sep rev_cmds sep {$$ = $2;} +	| {$$ = gen_list();}  input -	: cmds {parser->tree = gen_list($1);} +	: cmds {$1.kind = LYN_GROUP; parser->tree = $1;}  %% diff --git a/src/vec.c b/src/vec.c new file mode 100644 index 0000000..dc7d3b1 --- /dev/null +++ b/src/vec.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: copyleft-next-0.3.1 */ + +#include <stdlib.h> +#include <assert.h> +#include <string.h> + +#include <lyn/vec.h> + +struct vec vec_create(size_t ns) +{ +	return (struct vec) { +		       .n = 0, +		       .s = 1, +		       .ns = ns, +		       .buf = malloc(ns), +	}; +} + +size_t vec_len(struct vec *v) +{ +	return v->n; +} + +void *vec_at(struct vec *v, size_t i) +{ +	assert(i < v->n && "out of vector bounds"); +	return v->buf + i * v->ns; +} + +void *vec_back(struct vec *v) +{ +	assert(v->n); +	return v->buf + (v->n - 1) * v->ns; +} + +void *vec_pop(struct vec *v) +{ +	assert(v->n && "attempting to pop empty vector"); +	v->n--; +	return v->buf + v->n * v->ns; +} + +void vec_append(struct vec *v, void *n) +{ +	v->n++; +	if (v->n >= v->s) { +		v->s *= 2; +		v->buf = realloc(v->buf, v->s * v->ns); +	} + +	void *p = vec_at(v, v->n - 1); +	memcpy(p, n, v->ns); +} + +void vec_reset(struct vec *v) +{ +	v->n = 0; +} + +void vec_destroy(struct vec *v) { +	free(v->buf); +} + +void vec_sort(struct vec *v, vec_comp_t comp) +{ +	qsort(v->buf, v->n, v->ns, comp); +} | 
