mirror of
https://github.com/samsonjs/lake.git
synced 2026-04-27 14:57:43 +00:00
eval file named on command line before starting repl
This commit is contained in:
parent
ef54e18811
commit
be146520db
6 changed files with 120 additions and 56 deletions
2
eval.c
2
eval.c
|
|
@ -267,7 +267,7 @@ LakeVal *eval(Env *env, LakeVal *expr)
|
||||||
done: return result;
|
done: return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LakeList *eval_exprs(Env *env, LakeList *exprs)
|
LakeList *eval_exprs(Env *env, LakeList *exprs)
|
||||||
{
|
{
|
||||||
LakeList *results = list_make_with_capacity(LIST_N(exprs));
|
LakeList *results = list_make_with_capacity(LIST_N(exprs));
|
||||||
int i;
|
int i;
|
||||||
|
|
|
||||||
1
eval.h
1
eval.h
|
|
@ -14,6 +14,7 @@
|
||||||
#include "lake.h"
|
#include "lake.h"
|
||||||
|
|
||||||
LakeVal *eval(Env *env, LakeVal *expr);
|
LakeVal *eval(Env *env, LakeVal *expr);
|
||||||
|
LakeList *eval_exprs(Env *env, LakeList *exprs);
|
||||||
LakeVal *apply(LakeVal *fnVal, LakeList *args);
|
LakeVal *apply(LakeVal *fnVal, LakeList *args);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
124
lake.c
124
lake.c
|
|
@ -10,6 +10,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -62,46 +63,6 @@ static LakeVal *prompt_read(char *prompt)
|
||||||
return parse_expr(buf, strlen(buf));
|
return parse_expr(buf, strlen(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_repl_with_env(Env *env)
|
|
||||||
{
|
|
||||||
puts("Lake Scheme v" LAKE_VERSION);
|
|
||||||
LakeVal *expr;
|
|
||||||
LakeVal *result;
|
|
||||||
for (;;) {
|
|
||||||
expr = prompt_read("> ");
|
|
||||||
if (expr == VAL(EOF)) break;
|
|
||||||
if (expr == VAL(PARSE_ERR)) {
|
|
||||||
ERR("parse error");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (expr) {
|
|
||||||
result = eval(env, expr);
|
|
||||||
if (result) print(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void run_repl(void)
|
|
||||||
{
|
|
||||||
run_repl_with_env(primitive_bindings());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void run_one_then_repl(int argc, char const *args[])
|
|
||||||
{
|
|
||||||
/* create a top level environment */
|
|
||||||
Env *env = primitive_bindings();
|
|
||||||
|
|
||||||
/* bind args */
|
|
||||||
/*
|
|
||||||
LakeList *lakeArgs = list_of_strings_from_array(argc, args);
|
|
||||||
env_bind(env, "args", lakeArgs);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* eval (load args[0]) in env */
|
|
||||||
|
|
||||||
run_repl_with_env(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *repr(LakeVal *expr)
|
char *repr(LakeVal *expr)
|
||||||
{
|
{
|
||||||
if (expr == NULL) return g_strdup("(null)");
|
if (expr == NULL) return g_strdup("(null)");
|
||||||
|
|
@ -157,13 +118,88 @@ char *repr(LakeVal *expr)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char const *argv[])
|
static void run_repl(Env *env)
|
||||||
{
|
{
|
||||||
if (argc == 1) {
|
puts("Lake Scheme v" LAKE_VERSION);
|
||||||
run_repl();
|
LakeVal *expr;
|
||||||
|
LakeVal *result;
|
||||||
|
for (;;) {
|
||||||
|
expr = prompt_read("> ");
|
||||||
|
if (expr == VAL(EOF)) break;
|
||||||
|
if (expr == VAL(PARSE_ERR)) {
|
||||||
|
ERR("parse error");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (expr) {
|
||||||
|
result = eval(env, expr);
|
||||||
|
if (result) print(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *read_file(char const *filename)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(filename, "r");
|
||||||
|
if (fp) {
|
||||||
|
size_t size = 4096;
|
||||||
|
char buf[size];
|
||||||
|
size_t n = size;
|
||||||
|
size_t i = 0;
|
||||||
|
size_t read;
|
||||||
|
char *s = g_malloc(n);
|
||||||
|
|
||||||
|
while (!feof(fp) && !ferror(fp)) {
|
||||||
|
read = fread(buf, 1, size, fp);
|
||||||
|
if (i + read > n) {
|
||||||
|
n += size;
|
||||||
|
if (!(s = g_realloc(s, n))) OOM();
|
||||||
|
}
|
||||||
|
memcpy(s + i, buf, read);
|
||||||
|
i += read;
|
||||||
|
}
|
||||||
|
s[i] = '\0';
|
||||||
|
if (ferror(fp)) {
|
||||||
|
ERR("failed to read file %s: %s", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
run_one_then_repl(argc, argv);
|
ERR("cannot open file %s: %s", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
/* create a top level environment */
|
||||||
|
Env *env = primitive_bindings();
|
||||||
|
|
||||||
|
/* create and bind args */
|
||||||
|
LakeVal **argVals = g_malloc(argc * sizeof(LakeVal *));
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < argc; ++i) {
|
||||||
|
argVals[i] = VAL(str_from_c((char *)argv[i]));
|
||||||
|
}
|
||||||
|
LakeList *args = list_from_array(argc, argVals);
|
||||||
|
free(argVals);
|
||||||
|
env_define(env, sym_intern("args"), VAL(args));
|
||||||
|
|
||||||
|
/* if a filename is given load the file */
|
||||||
|
if (argc > 1) {
|
||||||
|
char *text = read_file(argv[1]);
|
||||||
|
if (text) {
|
||||||
|
LakeList *exprs = parse_exprs(text, strlen(text));
|
||||||
|
if (exprs) {
|
||||||
|
eval_exprs(env, exprs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* run the repl */
|
||||||
|
run_repl(env);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
list.c
1
list.c
|
|
@ -74,6 +74,7 @@ static void list_grow(LakeList *list)
|
||||||
{
|
{
|
||||||
list->cap *= 2;
|
list->cap *= 2;
|
||||||
list->vals = g_realloc(list->vals, list->cap * sizeof(LakeVal *));
|
list->vals = g_realloc(list->vals, list->cap * sizeof(LakeVal *));
|
||||||
|
if (!list->vals) OOM();
|
||||||
}
|
}
|
||||||
|
|
||||||
LakeVal *list_set(LakeList *list, size_t i, LakeVal *val)
|
LakeVal *list_set(LakeList *list, size_t i, LakeVal *val)
|
||||||
|
|
|
||||||
47
parse.c
47
parse.c
|
|
@ -27,19 +27,43 @@ struct context {
|
||||||
};
|
};
|
||||||
typedef struct context Ctx;
|
typedef struct context Ctx;
|
||||||
|
|
||||||
|
static void warn_trailing(Ctx *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->i < ctx->n) {
|
||||||
|
char *trailing = ctx->s + ctx->i;
|
||||||
|
printf("warning: ignoring %d trailing chars: %s\n", (int)(ctx->n - ctx->i), trailing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static LakeVal *_parse_expr(Ctx *ctx);
|
static LakeVal *_parse_expr(Ctx *ctx);
|
||||||
|
|
||||||
LakeVal *parse_expr(char *s, size_t n)
|
LakeVal *parse_expr(char *s, size_t n)
|
||||||
{
|
{
|
||||||
Ctx ctx = { s, n, 0, 0 };
|
Ctx ctx = { s, n, 0, 0 };
|
||||||
LakeVal *result = _parse_expr(&ctx);
|
LakeVal *result = _parse_expr(&ctx);
|
||||||
if (ctx.i < ctx.n) {
|
warn_trailing(&ctx);
|
||||||
char *trailing = ctx.s + ctx.i;
|
|
||||||
printf("warning: ignoring %d trailing chars: %s\n", (int)(ctx.n - ctx.i), trailing);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LakeList *parse_exprs(char *s, size_t n)
|
||||||
|
{
|
||||||
|
Ctx ctx = { s, n, 0, 0 };
|
||||||
|
LakeList *results = list_make();
|
||||||
|
LakeVal *result;
|
||||||
|
while (ctx.i < ctx.n) {
|
||||||
|
result = _parse_expr(&ctx);
|
||||||
|
if (result && result != VAL(PARSE_ERR)) {
|
||||||
|
list_append(results, result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list_free(results);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
warn_trailing(&ctx);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
static char peek(Ctx *ctx)
|
static char peek(Ctx *ctx)
|
||||||
{
|
{
|
||||||
if (ctx->i < ctx->n) return ctx->s[ctx->i];
|
if (ctx->i < ctx->n) return ctx->s[ctx->i];
|
||||||
|
|
@ -81,7 +105,7 @@ static void backtrack(Ctx *ctx)
|
||||||
ctx->i = ctx->mark;
|
ctx->i = ctx->mark;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean is_space(c)
|
static gboolean is_space(char c)
|
||||||
{
|
{
|
||||||
return strchr(" \r\n\t", c) != NULL;
|
return strchr(" \r\n\t", c) != NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -123,9 +147,7 @@ static char *parse_while(Ctx *ctx, gboolean (*is_valid)(char))
|
||||||
/* grow if necessary */
|
/* grow if necessary */
|
||||||
if (i >= n) {
|
if (i >= n) {
|
||||||
n *= 2;
|
n *= 2;
|
||||||
char *t = g_realloc(s, n);
|
if (!(s = g_realloc(s, n))) OOM();
|
||||||
if (!t) OOM();
|
|
||||||
s = t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s[i] = '\0';
|
s[i] = '\0';
|
||||||
|
|
@ -234,9 +256,7 @@ static LakeVal *parse_str(Ctx *ctx)
|
||||||
/* grow if necessary */
|
/* grow if necessary */
|
||||||
if (i >= n) {
|
if (i >= n) {
|
||||||
n *= 2;
|
n *= 2;
|
||||||
char *t = g_realloc(s, n);
|
if (!(s = g_realloc(s, n))) OOM();
|
||||||
if (!t) OOM();
|
|
||||||
s = t;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s[i] = '\0';
|
s[i] = '\0';
|
||||||
|
|
@ -344,5 +364,10 @@ static LakeVal *_parse_expr(Ctx *ctx)
|
||||||
ctx->i = ctx->n; /* consume the rest */
|
ctx->i = ctx->n; /* consume the rest */
|
||||||
}
|
}
|
||||||
maybe_spaces(ctx);
|
maybe_spaces(ctx);
|
||||||
|
|
||||||
|
if (IS(TYPE_SYM, result)) {
|
||||||
|
/* TODO: try to parse a naked list */
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
parse.h
1
parse.h
|
|
@ -17,5 +17,6 @@
|
||||||
#define PARSE_ERR -2
|
#define PARSE_ERR -2
|
||||||
|
|
||||||
LakeVal *parse_expr(char *s, size_t n);
|
LakeVal *parse_expr(char *s, size_t n);
|
||||||
|
LakeList *parse_exprs(char *s, size_t n);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Loading…
Reference in a new issue