update
This commit is contained in:
parent
ab03aa4eb7
commit
e65c1ab9dc
|
@ -1 +1,5 @@
|
|||
*.h linguist-language=c
|
||||
# Attributes for GitHub Linguist
|
||||
*.h linguist-language=c
|
||||
*.1 linguist-documentation
|
||||
*.ac linguist-detectable=false
|
||||
*.am linguist-detectable=false
|
||||
|
|
21
.travis.yml
21
.travis.yml
|
@ -0,0 +1,21 @@
|
|||
language: c
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
dist: bionic
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
script:
|
||||
- autoreconf --install
|
||||
- ./configure
|
||||
- make
|
||||
- make check
|
41
README.md
41
README.md
|
@ -6,56 +6,43 @@ Implementation of Unlambda, an esoteric programming language.
|
|||
|
||||
## Description
|
||||
|
||||
The u6a project provides a C implementation of the [Unlambda](http://www.madore.org/~david/programs/unlambda/) programming language, where Unlambda source code can be compiled into bytecode and executed in a virtual machine.
|
||||
The u6a project provides a bytecode compiler and a runtime system for the [Unlambda](http://www.madore.org/~david/programs/unlambda/) programming language.
|
||||
|
||||
Ideas behind this implementation can be found [here](https://).
|
||||
Ideas behind this implementation can be found [here](https://cismon.net/articles/2020/01/30/1580374678582.html).
|
||||
|
||||
## Requirements
|
||||
## Getting Started
|
||||
|
||||
* A POSIX-compliant operating system
|
||||
* GNU Autotools
|
||||
* GNU Make
|
||||
* A C compiler (with C99 support)
|
||||
|
||||
## Build
|
||||
Building:
|
||||
|
||||
```bash
|
||||
# (If not already) Install the required build tools.
|
||||
sudo apt install build-essential automake
|
||||
|
||||
# Generate configure files.
|
||||
# Generate configuration script.
|
||||
autoreconf --install
|
||||
|
||||
# Run configure script with desired options.
|
||||
# Execute configuration script with desired options.
|
||||
./configure --prefix=$HOME
|
||||
|
||||
# Compile sources and generate executables.
|
||||
# Compile source code and generate executables.
|
||||
make
|
||||
|
||||
# (Optional) Run tests.
|
||||
make check
|
||||
|
||||
# (Optional) Install executables and man pages.
|
||||
make install
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
First, compile an Unlambda source file into bytecode.
|
||||
Usage:
|
||||
|
||||
```bash
|
||||
# Compile an Unlambda source file into bytecode.
|
||||
u6ac -o foo.unl.bc foo.unl
|
||||
```
|
||||
|
||||
Then, execute the bytecode file with the interpreter.
|
||||
|
||||
```bash
|
||||
# execute the bytecode file.
|
||||
u6a foo.unl.bc
|
||||
```
|
||||
|
||||
See [**u6ac**(1)](man/u6ac.1) and [**u6a**(1)](man/u6a.1) man pages for details.
|
||||
|
||||
## TODOs
|
||||
## Future Plans
|
||||
|
||||
* `u6adb` - An interactive debugger for Unlambda
|
||||
* Interactive debugger: `u6adb`
|
||||
* More compile-time optimizations
|
||||
* More test cases
|
||||
* LLVM backend for `u6ac`
|
||||
|
|
|
@ -56,8 +56,8 @@ write_bc_header(FILE* restrict output_stream, uint32_t text_len, uint32_t rodata
|
|||
.prog_header_size = U6A_BC_PROG_HEADER_SIZE
|
||||
},
|
||||
.prog = {
|
||||
.text_size = htonl(text_len * sizeof(uint8_t)),
|
||||
.rodata_size = htonl(rodata_len * sizeof(struct u6a_token))
|
||||
.text_size = htonl(text_len * sizeof(struct u6a_vm_ins)),
|
||||
.rodata_size = htonl(rodata_len * sizeof(uint8_t))
|
||||
}
|
||||
};
|
||||
return 1 == fwrite(&header, sizeof(struct u6a_bc_header), 1, output_stream);
|
||||
|
@ -111,9 +111,9 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
|
|||
struct u6a_ast_node* rchild = U6A_AN_RIGHT(node, ast_arr);
|
||||
if (U6A_AN_FN(lchild) == u6a_tf_app) {
|
||||
if (U6A_AN_FN(rchild) == u6a_tf_app) {
|
||||
stack[stack_top++].ins.opcode = u6a_vo_sa;
|
||||
stack[++stack_top].ins.opcode = u6a_vo_sa;
|
||||
} else {
|
||||
stack[stack_top++].ins = (struct u6a_vm_ins) {
|
||||
stack[++stack_top].ins = (struct u6a_vm_ins) {
|
||||
.opcode = u6a_vo_app,
|
||||
.operand.fn.second = rchild->value
|
||||
};
|
||||
|
@ -122,12 +122,12 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) {
|
|||
if (U6A_AN_FN(rchild) == u6a_tf_app) {
|
||||
if (U6A_AN_FN(lchild) == u6a_tf_d) {
|
||||
text_buffer[text_len].opcode = u6a_vo_del;
|
||||
stack[stack_top++] = (struct ins_with_offset) {
|
||||
stack[++stack_top] = (struct ins_with_offset) {
|
||||
.ins.opcode = u6a_vo_la,
|
||||
.offset = text_len++
|
||||
};
|
||||
} else {
|
||||
stack[stack_top++].ins = (struct u6a_vm_ins) {
|
||||
stack[++stack_top].ins = (struct u6a_vm_ins) {
|
||||
.opcode = u6a_vo_app,
|
||||
.operand.fn.first = lchild->value
|
||||
};
|
||||
|
|
|
@ -118,7 +118,7 @@ vm_var_fn_free(struct u6a_vm_var_fn var) {
|
|||
bool
|
||||
u6a_runtime_info(FILE* restrict input_stream, const char* file_name) {
|
||||
struct u6a_bc_header header;
|
||||
if (UNLIKELY(read_bc_header(&header, input_stream))) {
|
||||
if (UNLIKELY(!read_bc_header(&header, input_stream))) {
|
||||
u6a_err_invalid_bc_file(err_runtime, file_name);
|
||||
return false;
|
||||
}
|
||||
|
@ -137,16 +137,18 @@ u6a_runtime_info(FILE* restrict input_stream, const char* file_name) {
|
|||
bool
|
||||
u6a_runtime_init(struct u6a_runtime_options* options) {
|
||||
struct u6a_bc_header header;
|
||||
if (UNLIKELY(read_bc_header(&header, options->istream))) {
|
||||
if (UNLIKELY(!read_bc_header(&header, options->istream))) {
|
||||
u6a_err_invalid_bc_file(err_runtime, options->file_name);
|
||||
return false;
|
||||
}
|
||||
if (UNLIKELY(CHECK_BC_HEADER_VER(header.file))) {
|
||||
if (UNLIKELY(!CHECK_BC_HEADER_VER(header.file))) {
|
||||
if (!options->force_exec || header.file.prog_header_size != U6A_BC_FILE_HEADER_SIZE) {
|
||||
u6a_err_bad_bc_ver(err_runtime, options->file_name, header.file.ver_major, header.file.ver_minor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
header.prog.text_size = ntohl(header.prog.text_size);
|
||||
header.prog.rodata_size = ntohl(header.prog.rodata_size);
|
||||
text = malloc(header.prog.text_size + sizeof(text_subst));
|
||||
if (UNLIKELY(text == NULL)) {
|
||||
u6a_err_bad_alloc(err_runtime, header.prog.text_size + sizeof(text_subst));
|
||||
|
|
|
@ -73,7 +73,7 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
|||
options->optimize_const = false;
|
||||
bool syntax_only = false;
|
||||
bool verbose = false;
|
||||
char optimize_level;
|
||||
char optimize_level = '1';
|
||||
while (true) {
|
||||
int result = getopt_long(argc, argv, "o:O::vHV", long_opts, NULL);
|
||||
if (result == -1) {
|
||||
|
@ -88,9 +88,6 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
|||
break;
|
||||
case 'O':
|
||||
optimize_level = optarg ? optarg[0] : '1';
|
||||
if (optimize_level > '0') {
|
||||
options->optimize_const = true;
|
||||
}
|
||||
case 'p':
|
||||
if (UNLIKELY(options->output_file_prefix)) {
|
||||
break;
|
||||
|
@ -177,6 +174,9 @@ process_options(struct arg_options* options, int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (optimize_level > '0') {
|
||||
options->optimize_const = true;
|
||||
}
|
||||
u6a_logging_verbose(verbose);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue