aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksey Veresov <aleksey@veresov.pro>2021-01-05 16:54:50 +0300
committerAleksey Veresov <aleksey@veresov.pro>2021-01-05 16:54:50 +0300
commit94f089316ffbf2e2e74b0257355f7c390ff5262b (patch)
treeeddfe1a89e2cede726ab44a6fff356492f54f1f5 /src
parente96facabd92d3eb61a4f97dfc3436a34dae4812d (diff)
downloadcsx-94f089316ffbf2e2e74b0257355f7c390ff5262b.tar
csx-94f089316ffbf2e2e74b0257355f7c390ff5262b.tar.xz
csx-94f089316ffbf2e2e74b0257355f7c390ff5262b.zip
Added sx.
Diffstat (limited to 'src')
-rw-r--r--src/csx.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/csx.c b/src/csx.c
index c265631..8951a09 100644
--- a/src/csx.c
+++ b/src/csx.c
@@ -15,7 +15,8 @@ typedef enum csx_type {
type_name,
type_base,
type_int,
- type_fn
+ type_fn,
+ type_sx
} csx_type;
static csx_type type(void *p)
@@ -222,6 +223,7 @@ static void *base_type(void *arg)
case type_base: return csx_name("base");
case type_int: return csx_name("int");
case type_fn: return csx_name("fn");
+ case type_sx: return csx_name("sx");
}
return 0;
}
@@ -246,12 +248,20 @@ static void *base_fn(void *arg)
return res;
}
+static void *base_sx(void *arg)
+{
+ fn_data *res = new(type_sx, sizeof(fn_data));
+ res->params = head(arg);
+ res->body = tail(arg);
+ res->context = context;
+ return res;
+}
+
static void *base_if(void *arg)
{
- void *saved = context;
- void *res = csx_run(head(arg));
- context = saved;
- return type(res) != type_null ?
+ if (type(arg) != type_pair) return null;
+ if (type(tail(arg)) != type_pair) return csx_run(head(arg));
+ return type(csx_run(head(arg))) != type_null ?
csx_run(head(tail(arg))) :
csx_run(head(tail(tail(arg))));
}
@@ -387,14 +397,19 @@ tailcall:
return (*base)(ops);
}
} else if (type(fn) == type_fn) {
- void *saved;
void *res;
+ void *saved = context;
ops = run_each(ops);
- saved = context;
context = new_pair(zip(fn->params, ops), fn->context);
res = base_do(fn->body);
context = saved;
return res;
+ } else if (type(fn) == type_sx) {
+ void *saved = context;
+ context = new_pair(zip(fn->params, ops), fn->context);
+ arg = base_do(fn->body);
+ context = saved;
+ goto tailcall;
} else if (type(fn) == type_pair) {
pair_data *res = (void *)fn;
int pos = *(int *)head(ops);
@@ -425,6 +440,7 @@ static void new_context()
base_set(csx_list(csx_name("type"), csx_base(base_type), 0));
base_set(csx_list(csx_name("do"), csx_base(base_do), 0));
base_set(csx_list(csx_name("fn"), csx_base(base_fn), 0));
+ base_set(csx_list(csx_name("sx"), csx_base(base_sx), 0));
base_set(csx_list(csx_name("if"), csx_base(base_if), 0));
base_set(csx_list(csx_name("+"), csx_base(base_sum), 0));
base_set(csx_list(csx_name("*"), csx_base(base_prod), 0));