update
This commit is contained in:
parent
e65c1ab9dc
commit
ecdd2828b2
|
@ -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...
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
22
configure.ac
22
configure.ac
|
@ -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
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
MAN_DIR = $(prefix)/share/man/man1
|
||||
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)
|
||||
|
|
|
@ -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++
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue