Browse Source

support setting the VM's stdout

master
Martin Dørum 3 years ago
parent
commit
fc8bdb9df1
5 changed files with 73 additions and 15 deletions
  1. 2
    0
      include/lang2/io.h
  2. 4
    0
      include/lang2/vm/vm.h
  3. 37
    0
      lib/io.c
  4. 15
    15
      lib/vm/builtins.c
  5. 15
    0
      lib/vm/vm.c

+ 2
- 0
include/lang2/io.h View File

char buf[L2_IO_BUFSIZ]; char buf[L2_IO_BUFSIZ];
}; };


int l2_io_printf(struct l2_io_writer *w, const char *fmt, ...);

void l2_bufio_reader_init(struct l2_bufio_reader *b, struct l2_io_reader *r); void l2_bufio_reader_init(struct l2_bufio_reader *b, struct l2_io_reader *r);
void l2_bufio_shift(struct l2_bufio_reader *b); void l2_bufio_shift(struct l2_bufio_reader *b);
int l2_bufio_shift_peek(struct l2_bufio_reader *b, size_t count); int l2_bufio_shift_peek(struct l2_bufio_reader *b, size_t count);

+ 4
- 0
include/lang2/vm/vm.h View File



#include "../bytecode.h" #include "../bytecode.h"
#include "../bitset.h" #include "../bitset.h"
#include "../io.h"


struct l2_vm; struct l2_vm;
struct l2_vm_array; struct l2_vm_array;
size_t opcount; size_t opcount;
l2_word iptr; l2_word iptr;


struct l2_io_writer *std_output;
struct l2_io_writer *std_error;

struct l2_vm_value *values; struct l2_vm_value *values;
size_t valuessize; size_t valuessize;
struct l2_bitset valueset; struct l2_bitset valueset;

+ 37
- 0
lib/io.c View File

#include "io.h" #include "io.h"


#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>

int l2_io_printf(struct l2_io_writer *w, const char *fmt, ...) {
char buf[256];

va_list va;
va_start(va, fmt);
int n = vsnprintf(buf, sizeof(buf), fmt, va);
if (n < 0) {
va_end(va);
return n;
} else if (n + 1 < sizeof(buf)) {
w->write(w, buf, n);
va_end(va);
return n;
}

// Yeah, this is slower, but it's just a fallback for when
// the output of printf is stupidly long. That shouldn't happen much.
char *buf2 = malloc(n + 1);
if (buf2 == NULL) {
va_end(va);
return -1;
}

n = vsnprintf(buf2, n + 1, fmt, va);
if (n < 0) {
va_end(va);
free(buf2);
return -1;
}

w->write(w, buf2, n);
va_end(va);
free(buf2);
return n;
}


void l2_bufio_reader_init(struct l2_bufio_reader *b, struct l2_io_reader *r) { void l2_bufio_reader_init(struct l2_bufio_reader *b, struct l2_io_reader *r) {
b->r = r; b->r = r;

+ 15
- 15
lib/vm/builtins.c View File



#include <stdio.h> #include <stdio.h>


static void print_val(struct l2_vm *vm, struct l2_vm_value *val) {
static void print_val(struct l2_vm *vm, struct l2_io_writer *out, struct l2_vm_value *val) {
switch (l2_vm_value_type(val)) { switch (l2_vm_value_type(val)) {
case L2_VAL_TYPE_NONE: case L2_VAL_TYPE_NONE:
printf("(none)");
l2_io_printf(out, "(none)");
break; break;


case L2_VAL_TYPE_ATOM: case L2_VAL_TYPE_ATOM:
printf("(atom %u)", val->atom);
l2_io_printf(out, "(atom %u)", val->atom);
break; break;


case L2_VAL_TYPE_REAL: case L2_VAL_TYPE_REAL:
printf("%g", val->real);
l2_io_printf(out, "%g", val->real);
break; break;


case L2_VAL_TYPE_BUFFER: case L2_VAL_TYPE_BUFFER:
if (val->buffer != NULL) { if (val->buffer != NULL) {
fwrite(val->buffer->data, 1, val->buffer->len, stdout);
out->write(out, val->buffer->data, val->buffer->len);
} }
break; break;


case L2_VAL_TYPE_ARRAY: case L2_VAL_TYPE_ARRAY:
if (val->array == NULL) { if (val->array == NULL) {
printf("[]");
out->write(out, "[]", 2);
break; break;
} }


putchar('[');
out->write(out, "[", 1);
for (size_t i = 0; i < val->array->len; ++i) { for (size_t i = 0; i < val->array->len; ++i) {
if (i != 0) { if (i != 0) {
putchar(' ');
out->write(out, " ", 1);
} }


print_val(vm, &vm->values[val->array->data[i]]);
print_val(vm, out, &vm->values[val->array->data[i]]);
} }
putchar(']');
out->write(out, "]", 1);
break; break;


case L2_VAL_TYPE_NAMESPACE: case L2_VAL_TYPE_NAMESPACE:
printf("(namespace)");
l2_io_printf(out, "(namespace)");
break; break;


case L2_VAL_TYPE_FUNCTION: case L2_VAL_TYPE_FUNCTION:
case L2_VAL_TYPE_CFUNCTION: case L2_VAL_TYPE_CFUNCTION:
printf("(function)");
l2_io_printf(out, "(function)");
break; break;
} }
} }
l2_word l2_builtin_print(struct l2_vm *vm, struct l2_vm_array *args) { l2_word l2_builtin_print(struct l2_vm *vm, struct l2_vm_array *args) {
for (size_t i = 0; i < args->len; ++i) { for (size_t i = 0; i < args->len; ++i) {
if (i != 0) { if (i != 0) {
putchar(' ');
vm->std_output->write(vm->std_output, " ", 1);
} }


struct l2_vm_value *val = &vm->values[args->data[i]]; struct l2_vm_value *val = &vm->values[args->data[i]];
print_val(vm, val);
print_val(vm, vm->std_output, val);
} }


putchar('\n');
vm->std_output->write(vm->std_output, "\n", 1);
return 0; return 0;
} }



+ 15
- 0
lib/vm/vm.c View File



#include "vm/builtins.h" #include "vm/builtins.h"


static int stdio_inited = 0;
static struct l2_io_file_writer std_output;
static struct l2_io_file_writer std_error;

static l2_word alloc_val(struct l2_vm *vm) { static l2_word alloc_val(struct l2_vm *vm) {
size_t id = l2_bitset_set_next(&vm->valueset); size_t id = l2_bitset_set_next(&vm->valueset);
if (id >= vm->valuessize) { if (id >= vm->valuessize) {
} }


void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount) { void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount) {
if (!stdio_inited) {
std_output.w.write = l2_io_file_write;
std_output.f = stdout;
std_error.w.write = l2_io_file_write;
std_error.f = stderr;
stdio_inited = 1;
}

vm->std_output = &std_output.w;
vm->std_error = &std_error.w;

vm->ops = ops; vm->ops = ops;
vm->opcount = opcount; vm->opcount = opcount;
vm->iptr = 0; vm->iptr = 0;

Loading…
Cancel
Save