This commit is contained in:
CismonX 2020-02-03 01:09:21 +08:00
parent e65c1ab9dc
commit ecdd2828b2
No known key found for this signature in database
GPG Key ID: 315D6652268C5007
10 changed files with 71 additions and 53 deletions

View File

@ -6,6 +6,8 @@ os:
dist: bionic
sudo: required
compiler:
- gcc
- clang
@ -19,3 +21,6 @@ script:
- ./configure
- make
- make check
- sudo make install
- command -v u6a u6ac
# - whatis u6a u6ac # broken on macOS...

View File

@ -1,6 +1,7 @@
# u6a
[![license](https://img.shields.io/badge/licence-GPLv3-blue.svg)](LICENSE)
[![Travis CI](https://travis-ci.com/CismonX/u6a.svg)](https://travis-ci.com/CismonX/u6a)
[![LICENSE](https://img.shields.io/badge/licence-GPLv3-blue.svg)](LICENSE)
Implementation of Unlambda, an esoteric programming language.

View File

@ -1,19 +1,33 @@
AC_PREREQ([2.69])
AC_INIT([u6a], [0.01], [https://cismon.net])
AC_INIT([u6a], [0.01], [bug-report@cismon.net])
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_SRCDIR([src/u6a.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile])
dnl Check for operating system
AC_CANONICAL_HOST
case "${host_os}" in
linux*)
AC_SUBST([MANPATH_CONF], [/etc/manpath.config])
AC_SUBST([REBUILD_MANDB], [mandb])
;;
darwin*)
AC_SUBST([MANPATH_CONF], [/private/etc/man.conf])
AC_SUBST([REBUILD_MANDB], [/usr/libexec/makewhatis])
;;
*)
AC_MSG_ERROR(["Unsupported OS: ${host_os}"])
;;
esac
dnl Checks for programs.
AC_PROG_CC_C99
dnl Checks for libraries.
dnl Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h inttypes.h stddef.h stdint.h stdlib.h string.h unistd.h],
[],
[AC_MSG_ERROR("required header(s) not found")])
[AC_MSG_ERROR(["required header(s) not found"])])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_HEADER_STDBOOL

View File

@ -1,8 +1,10 @@
MAN_DIR = $(prefix)/share/man/man1
MAN_FILES = u6ac.1 u6a.1
MANPATH_MAP = $(shell cat $(MANPATH_CONF) | grep -w -m1 $(prefix))
MAN_DIR = $(word 3, $(MANPATH_MAP))
MAN1_DIR = $(MAN_DIR)/man1
MAN_FILES = u6ac.1 u6a.1
install: $(MAN_FILES)
mkdir -p $(MAN_DIR) && cp -t $(MAN_DIR) $^
cp -t $(MAN1_DIR) $^ && $(REBUILD_MANDB) $(MAN_DIR)
uninstall: $(MAN_FILES)
pushd $(MAN_DIR) && rm -f $^ && popd
pushd $(MAN1_DIR) && rm -f $^ && popd && $(REBUILD_MANDB) $(MAN_DIR)

View File

@ -1,4 +1,4 @@
bin_PROGRAMS = u6ac u6a
u6ac_SOURCES = logging.c lexer.c parser.c codegen.c u6ac.c
u6a_SOURCES = logging.c vm_stack.c vm_pool.c runtime.c u6a.c
u6a_SOURCES = logging.c vm_stack.c vm_pool.c runtime.c u6a.c

View File

@ -144,6 +144,7 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
if (peek_ins.opcode == u6a_vo_app && operand_first.fn == u6a_tf_out && !operand_second.fn) {
rodata_buffer[rodata_len++] = operand_first.ch;
} else {
++stack_top;
break;
}
}
@ -178,7 +179,7 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
struct ins_with_offset* top_elem = stack + stack_top--;
if (top_elem->ins.opcode == u6a_vo_sa) {
text_buffer[text_len].opcode = u6a_vo_sa;
stack[stack_top++] = (struct ins_with_offset) {
stack[++stack_top] = (struct ins_with_offset) {
.ins.opcode = u6a_vo_la,
.offset = text_len++
};

View File

@ -255,7 +255,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
ins = text + func.ref;
func = acc;
// The `s2` function incremenets IP before pushing `j`, so decrement IP here
if (func.token.fn = u6a_vf_s2) {
if (func.token.fn == u6a_vf_s2) {
--ins;
}
arg = STACK_POP();
@ -279,7 +279,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
case u6a_vf_d1_c:
func = POOL_GET1(func.ref);
goto do_apply;
case u6a_vf_d1_s: ;
case u6a_vf_d1_s:
tuple = POOL_GET2(func.ref);
STACK_PUSH1(tuple.v1.fn);
acc = tuple.v2.fn;
@ -339,8 +339,8 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) {
break;
case u6a_vo_del:
delay:
acc = U6A_VM_VAR_FN_REF(u6a_vf_d1_d, ins + 1 - text);
ins = text + ins->operand.offset;
STACK_PUSH1(U6A_VM_VAR_FN_REF(u6a_vf_d1_d, ins + 1 - text));
ins = text + text_subst_len + ins->operand.offset;
continue;
case u6a_vo_lc:
switch (ins->opcode_ex) {

View File

@ -53,20 +53,20 @@ enum u6a_vm_opcode_ex {
enum u6a_vm_fn {
u6a_vf_placeholder_,
u6a_vf_k, u6a_vf_s, u6a_vf_i, u6a_vf_v, u6a_vf_c, u6a_vf_d, u6a_vf_e,
u6a_vf_in, /* @ */
u6a_vf_pipe, /* | */
u6a_vf_out = U6A_VM_FN_CHAR, /* .X */
u6a_vf_cmp, /* ?X */
u6a_vf_k1 = U6A_VM_FN_REF, /* `kX */
u6a_vf_s1, /* `sX */
u6a_vf_s2, /* ``sXY */
u6a_vf_c1, /* `cX */
u6a_vf_d1_s = U6A_VM_FN_PROMISE, /* `d`XZ */
u6a_vf_d1_c, /* `dX */
u6a_vf_d1_d, /* `dF */
u6a_vf_j = U6A_VM_FN_INTERNAL, /* (jump) */
u6a_vf_f, /* (finalize) */
u6a_vf_p /* (print) */
u6a_vf_in, /* @ */
u6a_vf_pipe, /* | */
u6a_vf_out = U6A_VM_FN_CHAR, /* .X */
u6a_vf_cmp, /* ?X */
u6a_vf_k1 = U6A_VM_FN_REF, /* `kX */
u6a_vf_s1, /* `sX */
u6a_vf_s2, /* ``sXY */
u6a_vf_c1, /* `cX */
u6a_vf_d1_s = U6A_VM_FN_PROMISE, /* `d`XZ */
u6a_vf_d1_c, /* `dX */
u6a_vf_d1_d, /* `dF */
u6a_vf_j = U6A_VM_FN_INTERNAL, /* (jump) */
u6a_vf_f, /* (finalize) */
u6a_vf_p /* (print) */
};
struct u6a_vm_ins {

View File

@ -90,20 +90,20 @@ free_stack_pop() {
bool
u6a_vm_pool_init(uint32_t pool_len_, uint32_t ins_len) {
const uint32_t pool_size = sizeof(struct vm_pool) + pool_len * sizeof(struct vm_pool_elem);
const uint32_t pool_size = sizeof(struct vm_pool) + pool_len_ * sizeof(struct vm_pool_elem);
active_pool = malloc(pool_size);
if (UNLIKELY(active_pool == NULL)) {
return false;
}
const uint32_t holes_size = sizeof(struct vm_pool_elem_ptrs) + pool_len * sizeof(struct vm_pool_elem*);
const uint32_t holes_size = sizeof(struct vm_pool_elem_ptrs) + pool_len_ * sizeof(struct vm_pool_elem*);
holes = malloc(holes_size);
if (UNLIKELY(active_pool == NULL)) {
free(active_pool);
if (UNLIKELY(holes == NULL)) {
free(holes);
return false;
}
const uint32_t free_stack_size = fstack_len * sizeof(struct vm_pool_elem*);
const uint32_t free_stack_size = ins_len * sizeof(struct vm_pool_elem*);
fstack = malloc(free_stack_size);
if (UNLIKELY(active_pool == NULL)) {
if (UNLIKELY(fstack == NULL)) {
free(active_pool);
free(holes);
return false;
@ -150,10 +150,8 @@ u6a_vm_pool_alloc2(struct u6a_vm_var_fn v1, struct u6a_vm_var_fn v2) {
if (UNLIKELY(elem == NULL)) {
return UINT32_MAX;
}
elem = &(struct vm_pool_elem) {
.values = { .v1.fn = v1, .v2.fn = v2 },
.flags = 0
};
elem->values = (struct u6a_vm_var_tuple) { .v1.fn = v1, .v2.fn = v2 };
elem->flags = 0;
return elem - active_pool->elems;
}
@ -163,10 +161,8 @@ u6a_vm_pool_alloc2_ptr(void* v1, void* v2) {
if (UNLIKELY(elem == NULL)) {
return UINT32_MAX;
}
elem = &(struct vm_pool_elem) {
.values = { .v1.ptr = v1, .v2.ptr = v2 },
.flags = POOL_ELEM_HOLDS_PTR
};
elem->values = (struct u6a_vm_var_tuple) { .v1.ptr = v1, .v2.ptr = v2 };
elem->flags = POOL_ELEM_HOLDS_PTR;
return elem - active_pool->elems;
}
@ -186,7 +182,7 @@ u6a_vm_pool_free(uint32_t offset) {
fstack_top = UINT32_MAX;
do {
if (--elem->refcnt == 0) {
holes->elems[holes->pos] = elem;
holes->elems[++holes->pos] = elem;
if (elem->flags & POOL_ELEM_HOLDS_PTR) {
// Continuation destroyed before used
u6a_vm_stack_discard(elem->values.v1.ptr);
@ -195,7 +191,7 @@ u6a_vm_pool_free(uint32_t offset) {
free_stack_push(elem->values.v2);
}
}
} while (elem = free_stack_pop());
} while ((elem = free_stack_pop()));
}
void

View File

@ -35,27 +35,26 @@ static uint32_t stack_seg_len;
static inline struct vm_stack*
vm_stack_create(struct vm_stack* prev, uint32_t top) {
const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(union u6a_vm_var);
const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(struct u6a_vm_var_fn);
struct vm_stack* vs = malloc(size);
if (UNLIKELY(vs == NULL)) {
return NULL;
}
return vs = &(struct vm_stack) {
.prev = prev,
.top = top,
.refcnt = 1
};
vs->prev = prev;
vs->top = top;
vs->refcnt = 1;
return vs;
}
static inline struct vm_stack*
vm_stack_dup() {
struct vm_stack* vs = active_stack;
const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(union u6a_vm_var);
const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(struct u6a_vm_var_fn);
struct vm_stack* dup_stack = malloc(size);
if (UNLIKELY(dup_stack == NULL)) {
return NULL;
}
memcpy(dup_stack, vs, sizeof(struct vm_stack) + (vs->top + 1) * sizeof(union u6a_vm_var));
memcpy(dup_stack, vs, sizeof(struct vm_stack) + (vs->top + 1) * sizeof(struct u6a_vm_var_fn));
dup_stack->refcnt = 1;
return dup_stack;
}