diff --git a/README b/README index f81001f..d62ed04 100644 --- a/README +++ b/README @@ -12,4 +12,5 @@ TODO: - [o] "#load" pragma +- [o better dip/keep (avoid using the retain stack for them) - [ ] hand-rolled parser diff --git a/examples/cat.grr b/examples/cat.grr new file mode 100644 index 0000000..f475451 --- /dev/null +++ b/examples/cat.grr @@ -0,0 +1,11 @@ +#load("std.grr") + +def while { + swap dup bury >r >r + if: call dup + [r> dup >r call r> r> swap while] + [drop r> drop r> drop]; +} + +while: [stdin fgetline] + [print]; diff --git a/src/file.c b/src/file.c index 8807182..1aa010c 100644 --- a/src/file.c +++ b/src/file.c @@ -1,5 +1,8 @@ #include +#include +#include "src/gc.h" +#include "src/object.h" #include "string.h" #include "userdata.h" #include "vm.h" @@ -13,6 +16,11 @@ Ut userdata_file = { }; // clang-format on +I prim_file_stdin(Vm *vm) { + vm_push(vm, vm->stdin); + return 0; +} + I prim_file_stdout(Vm *vm) { vm_push(vm, vm->stdout); return 0; @@ -29,13 +37,13 @@ I prim_file_fprint(Vm *vm) { Ud *file_ud = userdata_unwrap(file_obj, &userdata_file); if (file_ud == NULL) { - fprintf(stderr, "expected file object"); + fprintf(stderr, "expected file object\n"); return VM_ERR_TYPE; }; Str *str = string_unwrap(string_obj); if (str == NULL) { - fprintf(stderr, "expected string"); + fprintf(stderr, "expected string\n"); return VM_ERR_TYPE; } @@ -43,6 +51,31 @@ I prim_file_fprint(Vm *vm) { return 0; } +I prim_file_fgetline(Vm *vm) { + O file_obj = vm_pop(vm); + I mark = gc_mark(&vm->gc); + gc_addroot(&vm->gc, &file_obj); + + Ud *file_ud = userdata_unwrap(file_obj, &userdata_file); + if (file_ud == NULL) { + fprintf(stderr, "expected file object\n"); + return VM_ERR_TYPE; + } + + char *lineptr = NULL; + size_t size; + I len = getline(&lineptr, &size, (FILE *)file_ud->data); + if (len == -1) { + vm_push(vm, NIL); + } else { + vm_push(vm, string_make(vm, lineptr, len)); + } + free(lineptr); + + gc_reset(&vm->gc, mark); + return 0; +} + static V finalizer(V *data) { FILE *f = (FILE *)data; if (f && f != stdin && f != stdout && f != stderr) diff --git a/src/file.h b/src/file.h index fa73f79..cb10b11 100644 --- a/src/file.h +++ b/src/file.h @@ -2,6 +2,8 @@ extern Ut userdata_file; +I prim_file_stdin(Vm *); I prim_file_stdout(Vm *); I prim_file_stderr(Vm *); I prim_file_fprint(Vm *); +I prim_file_fgetline(Vm *vm); diff --git a/src/primitive.c b/src/primitive.c index 7f68c1f..983112e 100644 --- a/src/primitive.c +++ b/src/primitive.c @@ -28,9 +28,11 @@ static I prim_printstack(Vm *vm) { Pr primitives_table[] = { {".", prim_pprint}, {".s", prim_printstack}, + {"stdin", prim_file_stdin}, {"stdout", prim_file_stdout}, {"stderr", prim_file_stderr}, {"fprint", prim_file_fprint}, + {"fgetline", prim_file_fgetline}, {NULL, NULL}, }; // clang-format on diff --git a/src/print.c b/src/print.c index 53bdcb8..1407963 100644 --- a/src/print.c +++ b/src/print.c @@ -21,6 +21,7 @@ V print(O o) { printf(""); break; case OBJ_STR: { + // TODO: make this binary safe Str *s = string_unwrap(o); char *escaped = malloc(s->len + 1); memcpy(escaped, s->data, s->len);